public VoicesBuilder(string path, Encoding enc, bool isRelativeSongFile) { this.isRelativeSongFile = isRelativeSongFile; currentVoice = new Voice(Voice.soloVoiceName); voiceNameToVoiceMap.Add(Voice.soloVoiceName, currentVoice); using (StreamReader reader = TxtReader.GetFileStreamReader(path, enc)) { ParseStreamReader(reader); } }
public static SongMeta ParseFile(string path, Encoding enc = null) { using (StreamReader reader = TxtReader.GetFileStreamReader(path, enc)) { bool finishedHeaders = false; string directory = new FileInfo(path).Directory.FullName; string filename = new FileInfo(path).Name; Dictionary <string, string> requiredFields = new() { { "artist", null }, { "bpm", null },
public static Dictionary <string, Voice> ParseFile(string path, Encoding enc, IEnumerable <string> voiceIdentifiers) { Dictionary <string, MutableVoice> res = new Dictionary <string, MutableVoice>(); foreach (string voiceIdentifier in voiceIdentifiers) { res.Add(voiceIdentifier, new MutableVoice()); } MutableVoice currentVoice = null; MutableSentence currentSentence = null; bool endFound = false; // if this is a solo song (without a named voice) then just add one with identifier "" (empty string) if (res.Count == 0) { res.Add("", new MutableVoice()); currentVoice = res[""]; } using (StreamReader reader = TxtReader.GetFileStreamReader(path, enc)) { uint lineNumber = 0; while (!endFound && !reader.EndOfStream) { ++lineNumber; string line = reader.ReadLine(); switch (line[0]) { case '#': // headers are ignored at this stage break; case 'E': // finish any current open sentence if (currentVoice != null && currentSentence != null) { currentVoice.Add((Sentence)currentSentence); } // now we are done endFound = true; break; case 'P': // save the current sentence, if any if (currentVoice != null && currentSentence != null) { currentVoice.Add((Sentence)currentSentence); } // switch to the new voice try { currentVoice = res[line]; currentSentence = null; } catch (KeyNotFoundException) { ThrowLineError(lineNumber, "No such voice: " + line); } break; case '-': if (currentVoice == null) { ThrowLineError(lineNumber, "Linebreak encountered but no voice is active"); } else if (currentSentence == null) { ThrowLineError(lineNumber, "Linebreak encountered without preceding notes"); } try { currentSentence.SetLinebreakBeat(ParseLinebreak(line.Substring(2))); currentVoice.Add((Sentence)currentSentence); currentSentence = null; } catch (VoicesBuilderException e) { ThrowLineError(lineNumber, e.Message); } break; case ':': case '*': case 'F': case 'R': case 'G': if (currentVoice == null) { ThrowLineError(lineNumber, "Note encountered but no voice is active"); } else if (currentSentence == null) { currentSentence = new MutableSentence(); } try { currentSentence.Add(ParseNote(line)); } catch (VoicesBuilderException e) { ThrowLineError(lineNumber, e.Message); } break; default: ThrowLineError(lineNumber, "Invalid instruction: " + line); break; } } } Dictionary <string, Voice> actualRes = new Dictionary <string, Voice>(); foreach (var item in res) { actualRes.Add(item.Key, (Voice)item.Value); } return(actualRes); }
public static bool ParseSongFile(string path, Encoding enc = null) { Note lastNote = null; //Holds last parsed note. Get's reset on player change bool endFound = false; // True if end tag was found int player = 1; char[] trimChars = { ' ', ':' }; char[] splitChars = { ' ' }; Dictionary <ESongHeader, System.Object> headers = new Dictionary <ESongHeader, System.Object>(); List <List <Sentence> > voicesSentences = new List <List <Sentence> > { new List <Sentence>(), new List <Sentence>(), new List <Sentence>() }; try { using (StreamReader reader = TxtReader.GetFileStreamReader(path, enc)) { bool finishedHeaders = false; string directory = new FileInfo(path).Directory.FullName; while (!reader.EndOfStream) { string line = reader.ReadLine(); if (line == "" || line[0].Equals(" ") || (finishedHeaders && line[0].Equals('#'))) { Debug.Log(String.Format("Invalid linestart found in {0} :: \"{1}\". Aborting.", path, line.ToString())); return(false); } if (!finishedHeaders && line[0].Equals('#')) { int pos = line.IndexOf(":", StringComparison.Ordinal); string identifier = line.Substring(1, pos - 1).Trim().ToUpper(); if (identifier.Contains(" ") || identifier.Length < 2) { HandleParsingError("invalid file...", EParsingErrorSeverity.Critical); continue; } string value = line.Substring(pos + 1).Trim(); if (value == "") { // invalid tag. HandleParsingError("Invalid empty tag found", EParsingErrorSeverity.Minor); continue; } if (identifier.Equals("ENCODING")) { if (value.Equals("UTF8")) { value = "UTF-8"; } Encoding newEncoding = Encoding.GetEncoding(value); if (!newEncoding.Equals(reader.CurrentEncoding)) { reader.Dispose(); return(ParseSongFile(path, newEncoding)); } } identifier = ParseHeaderField(headers, directory, identifier, value); } else { if (!finishedHeaders) { finishedHeaders = true; } ParseLyricsTxtLine(ref lastNote, ref endFound, ref player, trimChars, splitChars, ref line); } } if (reader.EndOfStream && !finishedHeaders) { HandleParsingError("Lyrics/Notes missing", EParsingErrorSeverity.Critical); } CheckMinimalRequiredHeaders(headers); } } catch (Exception e) { Debug.Log("Error reading song file" + e.Message); return(false); } Song song = new Song(headers, voicesSentences, path); SongsManager.AddSongs(song); return(true); }
public static SongMeta ParseFile(string path, Encoding enc = null) { using (StreamReader reader = TxtReader.GetFileStreamReader(path, enc)) { bool finishedHeaders = false; string directory = new FileInfo(path).Directory.FullName; string filename = new FileInfo(path).Name; Dictionary <string, string> requiredFields = new Dictionary <string, string> { { "artist", null }, { "bpm", null }, { "mp3", null }, { "title", null } }; Dictionary <string, string> voiceNames = new Dictionary <string, string>(); Dictionary <string, string> otherFields = new Dictionary <string, string>(); uint lineNumber = 0; while (!finishedHeaders && !reader.EndOfStream) { ++lineNumber; string line = reader.ReadLine(); if (!line.StartsWith("#", StringComparison.Ordinal)) { if (lineNumber == 1) { throw new SongMetaBuilderException(path + " does not look like a song file; ignoring"); } finishedHeaders = true; break; } char[] separator = { ':' }; string[] parts = line.Substring(1).Split(separator, 2); if (parts.Length < 2 || parts[0].Length < 1 || parts[1].Length < 1) { Debug.LogWarning("Invalid line formatting on line " + line + " of file " + path); // Ignore this line. Continue with the next line. continue; } string tag = parts[0].ToLowerInvariant(); string val = parts[1]; if (tag.Equals("encoding", StringComparison.Ordinal)) { if (val.Equals("UTF8", StringComparison.Ordinal)) { val = "UTF-8"; } Encoding newEncoding = Encoding.GetEncoding(val); if (!newEncoding.Equals(reader.CurrentEncoding)) { reader.Dispose(); return(ParseFile(path, newEncoding)); } } else if (requiredFields.ContainsKey(tag)) { requiredFields[tag] = val; } else if (tag.Equals("previewstart")) { otherFields[tag] = val; } else if (tag.StartsWith("previewend")) { otherFields[tag] = val; } else if (tag.StartsWith("p", StringComparison.Ordinal) && tag.Length == 2 && Char.IsDigit(tag, 1)) { if (!voiceNames.ContainsKey(tag.ToUpperInvariant())) { voiceNames.Add(tag.ToUpperInvariant(), val); } // silently ignore already set voiceNames } else if (tag.StartsWith("duetsingerp", StringComparison.Ordinal) && tag.Length == 12 && Char.IsDigit(tag, 11)) { string shorttag = tag.Substring(10).ToUpperInvariant(); if (!voiceNames.ContainsKey(shorttag)) { voiceNames.Add(shorttag, val); } // silently ignore already set voiceNames } else { if (otherFields.ContainsKey(tag)) { throw new SongMetaBuilderException("Cannot set '" + tag + "' twice in file " + path); } otherFields.Add(tag, val); } } // this _should_ get handled by the ArgumentNullException // further down below, but that produces really vague // messages about a parameter 's' for some reason foreach (var item in requiredFields) { if (item.Value == null) { throw new SongMetaBuilderException("Required tag '" + item.Key + "' was not set in file: " + path); } } //Read the song file body StringBuilder songBody = new StringBuilder(); string bodyLine; while ((bodyLine = reader.ReadLine()) != null) { songBody.Append(bodyLine); //Ignorning the newlines for the hash } //Hash the song file body string songHash = Hashing.Md5(Encoding.UTF8.GetBytes(songBody.ToString())); try { SongMeta res = new SongMeta( directory, filename, songHash, requiredFields["artist"], ConvertToFloat(requiredFields["bpm"]), requiredFields["mp3"], requiredFields["title"], voiceNames, reader.CurrentEncoding ); foreach (var item in otherFields) { switch (item.Key) { case "background": res.Background = item.Value; break; case "cover": res.Cover = item.Value; break; case "edition": res.Edition = item.Value; break; case "end": res.End = ConvertToFloat(item.Value); break; case "gap": res.Gap = ConvertToFloat(item.Value); break; case "genre": res.Genre = item.Value; break; case "language": res.Language = item.Value; break; case "previewstart": res.PreviewStart = ConvertToFloat(item.Value); break; case "previewend": res.PreviewEnd = ConvertToFloat(item.Value); break; case "start": res.Start = ConvertToFloat(item.Value); break; case "video": res.Video = item.Value; break; case "videogap": res.VideoGap = ConvertToFloat(item.Value); break; case "year": res.Year = ConvertToUInt32(item.Value); break; default: res.AddUnkownHeaderEntry(item.Key, item.Value); break; } } return(res); } catch (ArgumentNullException e) { // if you get these with e.ParamName == "s", it's probably one of the non-nullable things (ie, float, uint, etc) throw new SongMetaBuilderException("Required tag '" + e.ParamName + "' was not set in file: " + path); } } }