コード例 #1
0
    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);
        }
    }
コード例 #2
0
    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 },
コード例 #3
0
ファイル: VoicesBuilder.cs プロジェクト: ST3ALth/Play
    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);
    }
コード例 #4
0
ファイル: SongParser.cs プロジェクト: gitter-badger/Play
    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);
    }
コード例 #5
0
ファイル: SongMetaBuilder.cs プロジェクト: Zeitless/Play
    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);
            }
        }
    }