public void LoadFromString(string cueString) { TextReader tr = new StringReader(cueString); bool track_has_pregap = false; bool track_has_postgap = false; int last_index_num = -1; CueFile currFile = null; CueTrack currTrack = null; for (; ; ) { string line = tr.ReadLine(); if (line == null) break; line = line.Trim(); if (line == "") continue; var clp = new CueLineParser(line); string key = clp.ReadToken().ToUpper(); switch (key) { case "REM": break; case "FILE": { currTrack = null; currFile = new CueFile(); Files.Add(currFile); currFile.Path = clp.ReadPath().Trim('"'); if (!clp.EOF) { string temp = clp.ReadToken().ToUpper(); switch (temp) { case "BINARY": currFile.FileType = CueFileType.Binary; break; case "WAVE": case "MP3": currFile.FileType = CueFileType.Wave; break; } currFile.StrFileType = temp; } break; } case "TRACK": { if (currFile == null) throw new CueBrokenException("invalid cue structure"); if (clp.EOF) throw new CueBrokenException("invalid cue structure"); string strtracknum = clp.ReadToken(); int tracknum; if (!int.TryParse(strtracknum, out tracknum)) throw new CueBrokenException("malformed track number"); if (clp.EOF) throw new CueBrokenException("invalid cue structure"); if (tracknum < 0 || tracknum > 99) throw new CueBrokenException("`All track numbers must be between 1 and 99 inclusive.`"); string strtracktype = clp.ReadToken().ToUpper(); currTrack = new CueTrack(); switch (strtracktype) { case "MODE1/2352": currTrack.TrackType = ETrackType.Mode1_2352; break; case "MODE1/2048": currTrack.TrackType = ETrackType.Mode1_2048; break; case "MODE2/2352": currTrack.TrackType = ETrackType.Mode2_2352; break; case "AUDIO": currTrack.TrackType = ETrackType.Audio; break; default: throw new CueBrokenException("unhandled track type"); } currTrack.TrackNum = tracknum; currFile.Tracks.Add(currTrack); track_has_pregap = false; track_has_postgap = false; last_index_num = -1; break; } case "INDEX": { if (currTrack == null) throw new CueBrokenException("invalid cue structure"); if (clp.EOF) throw new CueBrokenException("invalid cue structure"); if (track_has_postgap) throw new CueBrokenException("`The POSTGAP command must appear after all INDEX commands for the current track.`"); string strindexnum = clp.ReadToken(); int indexnum; if (!int.TryParse(strindexnum, out indexnum)) throw new CueBrokenException("malformed index number"); if (clp.EOF) throw new CueBrokenException("invalid cue structure (missing index timestamp)"); string str_timestamp = clp.ReadToken(); if (indexnum < 0 || indexnum > 99) throw new CueBrokenException("`All index numbers must be between 0 and 99 inclusive.`"); if (indexnum != 1 && indexnum != last_index_num + 1) throw new CueBrokenException("`The first index must be 0 or 1 with all other indexes being sequential to the first one.`"); last_index_num = indexnum; CueTrackIndex cti = new CueTrackIndex(indexnum) { Timestamp = new Timestamp(str_timestamp), IndexNum = indexnum }; currTrack.Indexes[indexnum] = cti; break; } case "PREGAP": if (track_has_pregap) throw new CueBrokenException("`Only one PREGAP command is allowed per track.`"); if (currTrack.Indexes.Count > 0) throw new CueBrokenException("`The PREGAP command must appear after a TRACK command, but before any INDEX commands.`"); currTrack.PreGap = new Timestamp(clp.ReadToken()); track_has_pregap = true; break; case "POSTGAP": if (track_has_postgap) throw new CueBrokenException("`Only one POSTGAP command is allowed per track.`"); track_has_postgap = true; currTrack.PostGap = new Timestamp(clp.ReadToken()); break; case "CATALOG": case "PERFORMER": case "SONGWRITER": case "TITLE": case "ISRC": //TODO - keep these for later? break; default: throw new CueBrokenException("unsupported cue command: " + key); } } //end cue parsing loop }
public void LoadFromString(string cueString) { TextReader tr = new StringReader(cueString); bool track_has_pregap = false; bool track_has_postgap = false; int last_index_num = -1; CueFile currFile = null; CueTrack currTrack = null; for (; ;) { string line = tr.ReadLine(); if (line == null) { break; } line = line.Trim(); if (line == "") { continue; } var clp = new CueLineParser(line); string key = clp.ReadToken().ToUpper(); switch (key) { case "REM": break; case "FILE": { currTrack = null; currFile = new CueFile(); Files.Add(currFile); currFile.Path = clp.ReadPath().Trim('"'); if (!clp.EOF) { string temp = clp.ReadToken().ToUpper(); switch (temp) { case "BINARY": currFile.FileType = CueFileType.Binary; break; case "WAVE": case "MP3": currFile.FileType = CueFileType.Wave; break; } currFile.StrFileType = temp; } break; } case "TRACK": { if (currFile == null) { throw new CueBrokenException("invalid cue structure"); } if (clp.EOF) { throw new CueBrokenException("invalid cue structure"); } string strtracknum = clp.ReadToken(); int tracknum; if (!int.TryParse(strtracknum, out tracknum)) { throw new CueBrokenException("malformed track number"); } if (clp.EOF) { throw new CueBrokenException("invalid cue structure"); } if (tracknum < 0 || tracknum > 99) { throw new CueBrokenException("`All track numbers must be between 1 and 99 inclusive.`"); } string strtracktype = clp.ReadToken().ToUpper(); currTrack = new CueTrack(); switch (strtracktype) { case "MODE1/2352": currTrack.TrackType = ETrackType.Mode1_2352; break; case "MODE1/2048": currTrack.TrackType = ETrackType.Mode1_2048; break; case "MODE2/2352": currTrack.TrackType = ETrackType.Mode2_2352; break; case "AUDIO": currTrack.TrackType = ETrackType.Audio; break; default: throw new CueBrokenException("unhandled track type"); } currTrack.TrackNum = tracknum; currFile.Tracks.Add(currTrack); track_has_pregap = false; track_has_postgap = false; last_index_num = -1; break; } case "INDEX": { if (currTrack == null) { throw new CueBrokenException("invalid cue structure"); } if (clp.EOF) { throw new CueBrokenException("invalid cue structure"); } if (track_has_postgap) { throw new CueBrokenException("`The POSTGAP command must appear after all INDEX commands for the current track.`"); } string strindexnum = clp.ReadToken(); int indexnum; if (!int.TryParse(strindexnum, out indexnum)) { throw new CueBrokenException("malformed index number"); } if (clp.EOF) { throw new CueBrokenException("invalid cue structure (missing index timestamp)"); } string str_timestamp = clp.ReadToken(); if (indexnum < 0 || indexnum > 99) { throw new CueBrokenException("`All index numbers must be between 0 and 99 inclusive.`"); } if (indexnum != 1 && indexnum != last_index_num + 1) { throw new CueBrokenException("`The first index must be 0 or 1 with all other indexes being sequential to the first one.`"); } last_index_num = indexnum; CueTrackIndex cti = new CueTrackIndex(indexnum) { Timestamp = new Timestamp(str_timestamp), IndexNum = indexnum }; currTrack.Indexes[indexnum] = cti; break; } case "PREGAP": if (track_has_pregap) { throw new CueBrokenException("`Only one PREGAP command is allowed per track.`"); } if (currTrack.Indexes.Count > 0) { throw new CueBrokenException("`The PREGAP command must appear after a TRACK command, but before any INDEX commands.`"); } currTrack.PreGap = new Timestamp(clp.ReadToken()); track_has_pregap = true; break; case "POSTGAP": if (track_has_postgap) { throw new CueBrokenException("`Only one POSTGAP command is allowed per track.`"); } track_has_postgap = true; currTrack.PostGap = new Timestamp(clp.ReadToken()); break; case "CATALOG": case "PERFORMER": case "SONGWRITER": case "TITLE": case "ISRC": //TODO - keep these for later? break; default: throw new CueBrokenException("unsupported cue command: " + key); } } //end cue parsing loop }