From 46bb010ca7c5eb04551c030105f9999ca80e472f Mon Sep 17 00:00:00 2001 From: tobigun Date: Sun, 8 Jun 2008 15:33:48 +0000 Subject: - set svn:eol-style to native - removed some svn:executable properties from non-executable files git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1144 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UXMLSong.pas | 1146 ++++++++++++++++++++-------------------- 1 file changed, 573 insertions(+), 573 deletions(-) (limited to 'Game/Code/Classes/UXMLSong.pas') diff --git a/Game/Code/Classes/UXMLSong.pas b/Game/Code/Classes/UXMLSong.pas index ddcb173a..1a1fe6bc 100644 --- a/Game/Code/Classes/UXMLSong.pas +++ b/Game/Code/Classes/UXMLSong.pas @@ -1,573 +1,573 @@ -unit UXMLSong; - -interface -uses Classes; - -type - TNote = record - Start: Cardinal; - Duration: Cardinal; - Tone: Integer; - NoteTyp: Byte; - Lyric: String; - end; - ANote = Array of TNote; - - TSentence = record - Singer: Byte; - Duration: Cardinal; - Notes: ANote; - end; - ASentence = Array of TSentence; - - TSongInfo = Record - ID: Cardinal; - DualChannel: Boolean; - Header: Record - Artist: String; - Title: String; - Gap: Cardinal; - BPM: Real; - Resolution: Byte; - Edition: String; - Genre: String; - Year: String; - Language: String; - end; - CountSentences: Cardinal; - Sentences: ASentence; - end; - - TParser = class - private - SSFile: TStringList; - - ParserState: Byte; - CurPosinSong: Cardinal; //Cur Beat Pos in the Song - CurDuettSinger: Byte; //Who sings this Part? - BindLyrics: Boolean; //Should the Lyrics be bind to the last Word (no Space) - FirstNote: Boolean; //Is this the First Note found? For Gap calculating - - Function ParseLine(Line: String): Boolean; - public - SongInfo: TSongInfo; - ErrorMessage: String; - Edition: String; - SingstarVersion: String; - - Settings: Record - DashReplacement: Char; - end; - - Constructor Create; - - Function ParseConfigforEdition(const Filename: String): String; - - Function ParseSongHeader(const Filename: String): Boolean; //Parse Song Header only - Function ParseSong (const Filename: String): Boolean; //Parse whole Song - end; - -const - PS_None = 0; - PS_Melody = 1; - PS_Sentence = 2; - - NT_Normal = 1; - NT_Freestyle = 0; - NT_Golden = 2; - - DS_Player1 = 1; - DS_Player2 = 2; - DS_Both = 3; - -implementation -uses SysUtils, StrUtils; - -Constructor TParser.Create; -begin - inherited Create; - ErrorMessage := ''; - - DecimalSeparator := '.'; -end; - -Function TParser.ParseSong (const Filename: String): Boolean; -var I: Integer; -begin - Result := False; - if FileExists(Filename) then - begin - SSFile := TStringList.Create; - - try - ErrorMessage := 'Can''t open melody.xml file'; - SSFile.LoadFromFile(Filename); - ErrorMessage := ''; - Result := True; - I := 0; - - SongInfo.CountSentences := 0; - CurDuettSinger := DS_Both; //Both is Singstar Standard - CurPosinSong := 0; //Start at Pos 0 - BindLyrics := True; //Dont start with Space - FirstNote := True; //First Note found should be the First Note ;) - - SongInfo.Header.Language := ''; - SongInfo.Header.Edition := Edition; - SongInfo.DualChannel := False; - - ParserState := PS_None; - - SetLength(SongInfo.Sentences, 0); - - While Result And (I < SSFile.Count) do - begin - Result := ParseLine(SSFile.Strings[I]); - - Inc(I); - end; - - finally - SSFile.Free; - end; - end; -end; - -Function TParser.ParseSongHeader (const Filename: String): Boolean; -var I: Integer; -begin - Result := False; - if FileExists(Filename) then - begin - SSFile := TStringList.Create; - SSFile.Clear; - - try - SSFile.LoadFromFile(Filename); - - If (SSFile.Count > 0) then - begin - Result := True; - I := 0; - - SongInfo.CountSentences := 0; - CurDuettSinger := DS_Both; //Both is Singstar Standard - CurPosinSong := 0; //Start at Pos 0 - BindLyrics := True; //Dont start with Space - FirstNote := True; //First Note found should be the First Note ;) - - SongInfo.ID := 0; - SongInfo.Header.Language := ''; - SongInfo.Header.Edition := Edition; - SongInfo.DualChannel := False; - ParserState := PS_None; - - While (SongInfo.ID < 4) AND Result And (I < SSFile.Count) do - begin - Result := ParseLine(SSFile.Strings[I]); - - Inc(I); - end; - end - else - ErrorMessage := 'Can''t open melody.xml file'; - - finally - SSFile.Free; - end; - end - else - ErrorMessage := 'Can''t find melody.xml file'; -end; - -Function TParser.ParseLine(Line: String): Boolean; -var - Tag: String; - Values: String; - AValues: Array of Record - Name: String; - Value: String; - end; - I, J, K: Integer; - Duration, Tone: Integer; - Lyric: String; - NoteType: Byte; - - Procedure MakeValuesArray; - var Len, Pos, State, StateChange: Integer; - begin - Len := -1; - SetLength(AValues, Len + 1); - - Pos := 1; - State := 0; - While (Pos <= Length(Values)) AND (Pos <> 0) do - begin - Case State of - - 0: begin //Search for ValueName - If (Values[Pos] <> ' ') AND (Values[Pos] <> '=') then - begin - //Found Something - State := 1; //State search for '=' - StateChange := Pos; //Save Pos of Change - Pos := PosEx('=', Values, Pos + 1); - end - else Inc(Pos); //When nothing found then go to next char - end; - - 1: begin //Search for Equal Mark - //Add New Value - Inc(Len); - SetLength(AValues, Len + 1); - - AValues[Len].Name := UpperCase(Copy(Values, StateChange, Pos - StateChange)); - - - State := 2; //Now Search for starting '"' - StateChange := Pos; //Save Pos of Change - Pos := PosEx('"', Values, Pos + 1); - end; - - 2: begin //Search for starting '"' or ' ' <- End if there was no " - If (Values[Pos] = '"') then - begin //Found starting '"' - State := 3; //Now Search for ending '"' - StateChange := Pos; //Save Pos of Change - Pos := PosEx('"', Values, Pos + 1); - end - else If (Values[Pos] = ' ') then //Found ending Space - begin - //Save Value to Array - AValues[Len].Value := Copy(Values, StateChange + 1, Pos - StateChange - 1); - - //Search for next Valuename - State := 0; - StateChange := Pos; - Inc(Pos); - end; - end; - - 3: begin //Search for ending '"' - //Save Value to Array - AValues[Len].Value := Copy(Values, StateChange + 1, Pos - StateChange - 1); - - //Search for next Valuename - State := 0; - StateChange := Pos; - Inc(Pos); - end; - end; - - If (State >= 2) then - begin //Save Last Value - AValues[Len].Value := Copy(Values, StateChange + 1, Length(Values) - StateChange); - end; - end; - end; -begin - Result := True; - - Line := Trim(Line); - If (Length(Line) > 0) then - begin - I := Pos('<', Line); - J := PosEx(' ', Line, I+1); - K := PosEx('>', Line, I+1); - - If (J = 0) then J := K - Else If (K < J) AND (K <> 0) then J := K; //Use nearest Tagname End indicator - Tag := UpperCase(copy(Line, I + 1, J - I - 1)); - Values := copy(Line, J + 1, K - J - 1); - - Case ParserState of - PS_None: begin//Search for Melody Tag - If (Tag = 'MELODY') then - begin - Inc(SongInfo.ID); //Inc SongID when header Information is added - MakeValuesArray; - For I := 0 to High(AValues) do - begin - If (AValues[I].Name = 'TEMPO') then - begin - SongInfo.Header.BPM := StrtoFloatDef(AValues[I].Value, 0); - If (SongInfo.Header.BPM <= 0) then - begin - Result := False; - ErrorMessage := 'Can''t read BPM from Song'; - end; - end - - Else If (AValues[I].Name = 'RESOLUTION') then - begin - AValues[I].Value := Uppercase(AValues[I].Value); - //Ultrastar Resolution is "how often a Beat is split / 4" - If (AValues[I].Value = 'HEMIDEMISEMIQUAVER') then - SongInfo.Header.Resolution := 64 div 4 - Else If (AValues[I].Value = 'DEMISEMIQUAVER') then - SongInfo.Header.Resolution := 32 div 4 - Else If (AValues[I].Value = 'SEMIQUAVER') then - SongInfo.Header.Resolution := 16 div 4 - Else If (AValues[I].Value = 'QUAVER') then - SongInfo.Header.Resolution := 8 div 4 - Else If (AValues[I].Value = 'CROTCHET') then - SongInfo.Header.Resolution := 4 div 4 - Else - begin //Can't understand teh Resolution :/ - Result := False; - ErrorMessage := 'Can''t read Resolution from Song'; - end; - end - - Else If (AValues[I].Name = 'GENRE') then - begin - SongInfo.Header.Genre := AValues[I].Value; - end - - Else If (AValues[I].Name = 'YEAR') then - begin - SongInfo.Header.Year := AValues[I].Value; - end - - Else If (AValues[I].Name = 'VERSION') then - begin - SingstarVersion := AValues[I].Value; - end; - end; - - ParserState := PS_Melody; //In Melody Tag - end; - end; - - - PS_Melody: begin //Search for Sentence, Artist/Title Info or eo Melody - If (Tag = 'SENTENCE') then - begin - ParserState := PS_Sentence; //Parse in a Sentence Tag now - - //Increase SentenceCount - Inc(SongInfo.CountSentences); - - BindLyrics := True; //Don't let Txts Begin w/ Space - - //Search for Duett Singer Info - MakeValuesArray; - For I := 0 to High(AValues) do - If (AValues[I].Name = 'SINGER') then - begin - AValues[I].Value := Uppercase(AValues[I].Value); - If (AValues[I].Value = 'SOLO 1') then - CurDuettSinger := DS_Player1 - Else If (AValues[I].Value = 'SOLO 2') then - CurDuettSinger := DS_Player2 - Else - CurDuettSinger := DS_Both; //In case of "Group" or anything that is not identified use Both - end; - end - - Else If (Tag = '!--') then - begin //Comment, this may be Artist or Title Info - I := Pos(':', Values); //Search for Delimiter - - If (I <> 0) then //If Found check for Title or Artist - begin - //Copy Title or Artist Tag to Tag String - Tag := Uppercase(Trim(Copy(Values, 1, I - 1))); - - If (Tag = 'ARTIST') then - begin - SongInfo.Header.Artist := Trim(Copy(Values, I + 1, Length(Values) - I - 2)); - Inc(SongInfo.ID); //Inc SongID when header Information is added - end - Else If (Tag = 'TITLE') then - begin - SongInfo.Header.Title := Trim(Copy(Values, I + 1, Length(Values) - I - 2)); - Inc(SongInfo.ID); //Inc SongID when header Information is added - end; - end; - end - - //Parsing for weird "Die toten Hosen" Tags - Else If (Tag = '!--ARTIST:') OR (Tag = '!--ARTIST') then - begin //Comment, with Artist Info - I := Pos(':', Values); //Search for Delimiter - - Inc(SongInfo.ID); //Inc SongID when header Information is added - - SongInfo.Header.Artist := Trim(Copy(Values, I + 1, Length(Values) - I - 2)); - end - - Else If (Tag = '!--TITLE:') OR (Tag = '!--TITLE') then - begin //Comment, with Artist Info - I := Pos(':', Values); //Search for Delimiter - - Inc(SongInfo.ID); //Inc SongID when header Information is added - - SongInfo.Header.Title := Trim(Copy(Values, I + 1, Length(Values) - I - 2)); - end - - Else If (Tag = '/MELODY') then - begin - ParserState := PS_None; - Exit; //Stop Parsing, Melody iTag ended - end - end; - - - PS_Sentence: begin //Search for Notes or eo Sentence - If (Tag = 'NOTE') then - begin //Found Note - //Get Values - MakeValuesArray; - - NoteType := NT_Normal; - For I := 0 to High(AValues) do - begin - If (AValues[I].Name = 'DURATION') then - begin - Duration := StrtoIntDef(AValues[I].Value, -1); - If (Duration < 0) then - begin - Result := False; - ErrorMessage := 'Can''t read duration from Note in Line: "' + Line + '"'; - Exit; - end; - end - Else If (AValues[I].Name = 'MIDINOTE') then - begin - Tone := StrtoIntDef(AValues[I].Value, 0); - end - Else If (AValues[I].Name = 'BONUS') AND (Uppercase(AValues[I].Value) = 'YES') then - begin - NoteType := NT_Golden; - end - Else If (AValues[I].Name = 'FREESTYLE') AND (Uppercase(AValues[I].Value) = 'YES') then - begin - NoteType := NT_Freestyle; - end - Else If (AValues[I].Name = 'LYRIC') then - begin - Lyric := AValues[I].Value; - - If (Length(Lyric) > 0) then - begin - If (Lyric = '-') then - Lyric[1] := Settings.DashReplacement; - - If (not BindLyrics) then - Lyric := ' ' + Lyric; - - - If (Length(Lyric) > 2) AND (Lyric[Length(Lyric)-1] = ' ') AND (Lyric[Length(Lyric)] = '-') then - begin //Between this and the next Lyric should be no space - BindLyrics := True; - SetLength(Lyric, Length(Lyric) - 2); - end - else - BindLyrics := False; //There should be a Space - end; - end; - end; - - //Add Note - I := SongInfo.CountSentences - 1; - - If (Length(Lyric) > 0) then - begin //Real note, no rest - //First Note of Sentence - If (Length(SongInfo.Sentences) < SongInfo.CountSentences) then - begin - SetLength(SongInfo.Sentences, SongInfo.CountSentences); - SetLength(SongInfo.Sentences[I].Notes, 0); - end; - - //First Note of Song -> Generate Gap - If (FirstNote) then - begin - //Calculate Gap - If (SongInfo.Header.Resolution <> 0) AND (SongInfo.Header.BPM <> 0) then - SongInfo.Header.Gap := Round(CurPosinSong / (SongInfo.Header.BPM*SongInfo.Header.Resolution) * 60000) - Else - begin - Result := False; - ErrorMessage := 'Can''t calculate Gap, no Resolution or BPM present.'; - Exit; - end; - - CurPosinSong := 0; //Start at 0, because Gap goes until here - Inc(SongInfo.ID); //Add Header Value therefore Inc - FirstNote := False; - end; - - J := Length(SongInfo.Sentences[I].Notes); - SetLength(SongInfo.Sentences[I].Notes, J + 1); - SongInfo.Sentences[I].Notes[J].Start := CurPosinSong; - SongInfo.Sentences[I].Notes[J].Duration := Duration; - SongInfo.Sentences[I].Notes[J].Tone := Tone; - SongInfo.Sentences[I].Notes[J].NoteTyp := NoteType; - SongInfo.Sentences[I].Notes[J].Lyric := Lyric; - - //Inc Pos in Song - Inc(CurPosInSong, Duration); - end - else - begin - //just change pos in Song - Inc(CurPosInSong, Duration); - end; - - - end - Else If (Tag = '/SENTENCE') then - begin //End of Sentence Tag - ParserState := PS_Melody; - - //Delete Sentence if no Note is Added - If (Length(SongInfo.Sentences) <> SongInfo.CountSentences) then - begin - SongInfo.CountSentences := Length(SongInfo.Sentences); - end; - end; - end; - end; - - end - else //Empty Line -> parsed succesful ;) - Result := true; -end; - -Function TParser.ParseConfigforEdition(const Filename: String): String; -var - txt: TStringlist; - I: Integer; - J, K: Integer; - S: String; -begin - Result := ''; - txt := TStringlist.Create; - try - txt.LoadFromFile(Filename); - - For I := 0 to txt.Count-1 do - begin - S := Trim(txt.Strings[I]); - J := Pos('', S); - - If (J <> 0) then - begin - Inc(J, 14); - K := Pos('', S); - If (K 0) then + begin + Result := True; + I := 0; + + SongInfo.CountSentences := 0; + CurDuettSinger := DS_Both; //Both is Singstar Standard + CurPosinSong := 0; //Start at Pos 0 + BindLyrics := True; //Dont start with Space + FirstNote := True; //First Note found should be the First Note ;) + + SongInfo.ID := 0; + SongInfo.Header.Language := ''; + SongInfo.Header.Edition := Edition; + SongInfo.DualChannel := False; + ParserState := PS_None; + + While (SongInfo.ID < 4) AND Result And (I < SSFile.Count) do + begin + Result := ParseLine(SSFile.Strings[I]); + + Inc(I); + end; + end + else + ErrorMessage := 'Can''t open melody.xml file'; + + finally + SSFile.Free; + end; + end + else + ErrorMessage := 'Can''t find melody.xml file'; +end; + +Function TParser.ParseLine(Line: String): Boolean; +var + Tag: String; + Values: String; + AValues: Array of Record + Name: String; + Value: String; + end; + I, J, K: Integer; + Duration, Tone: Integer; + Lyric: String; + NoteType: Byte; + + Procedure MakeValuesArray; + var Len, Pos, State, StateChange: Integer; + begin + Len := -1; + SetLength(AValues, Len + 1); + + Pos := 1; + State := 0; + While (Pos <= Length(Values)) AND (Pos <> 0) do + begin + Case State of + + 0: begin //Search for ValueName + If (Values[Pos] <> ' ') AND (Values[Pos] <> '=') then + begin + //Found Something + State := 1; //State search for '=' + StateChange := Pos; //Save Pos of Change + Pos := PosEx('=', Values, Pos + 1); + end + else Inc(Pos); //When nothing found then go to next char + end; + + 1: begin //Search for Equal Mark + //Add New Value + Inc(Len); + SetLength(AValues, Len + 1); + + AValues[Len].Name := UpperCase(Copy(Values, StateChange, Pos - StateChange)); + + + State := 2; //Now Search for starting '"' + StateChange := Pos; //Save Pos of Change + Pos := PosEx('"', Values, Pos + 1); + end; + + 2: begin //Search for starting '"' or ' ' <- End if there was no " + If (Values[Pos] = '"') then + begin //Found starting '"' + State := 3; //Now Search for ending '"' + StateChange := Pos; //Save Pos of Change + Pos := PosEx('"', Values, Pos + 1); + end + else If (Values[Pos] = ' ') then //Found ending Space + begin + //Save Value to Array + AValues[Len].Value := Copy(Values, StateChange + 1, Pos - StateChange - 1); + + //Search for next Valuename + State := 0; + StateChange := Pos; + Inc(Pos); + end; + end; + + 3: begin //Search for ending '"' + //Save Value to Array + AValues[Len].Value := Copy(Values, StateChange + 1, Pos - StateChange - 1); + + //Search for next Valuename + State := 0; + StateChange := Pos; + Inc(Pos); + end; + end; + + If (State >= 2) then + begin //Save Last Value + AValues[Len].Value := Copy(Values, StateChange + 1, Length(Values) - StateChange); + end; + end; + end; +begin + Result := True; + + Line := Trim(Line); + If (Length(Line) > 0) then + begin + I := Pos('<', Line); + J := PosEx(' ', Line, I+1); + K := PosEx('>', Line, I+1); + + If (J = 0) then J := K + Else If (K < J) AND (K <> 0) then J := K; //Use nearest Tagname End indicator + Tag := UpperCase(copy(Line, I + 1, J - I - 1)); + Values := copy(Line, J + 1, K - J - 1); + + Case ParserState of + PS_None: begin//Search for Melody Tag + If (Tag = 'MELODY') then + begin + Inc(SongInfo.ID); //Inc SongID when header Information is added + MakeValuesArray; + For I := 0 to High(AValues) do + begin + If (AValues[I].Name = 'TEMPO') then + begin + SongInfo.Header.BPM := StrtoFloatDef(AValues[I].Value, 0); + If (SongInfo.Header.BPM <= 0) then + begin + Result := False; + ErrorMessage := 'Can''t read BPM from Song'; + end; + end + + Else If (AValues[I].Name = 'RESOLUTION') then + begin + AValues[I].Value := Uppercase(AValues[I].Value); + //Ultrastar Resolution is "how often a Beat is split / 4" + If (AValues[I].Value = 'HEMIDEMISEMIQUAVER') then + SongInfo.Header.Resolution := 64 div 4 + Else If (AValues[I].Value = 'DEMISEMIQUAVER') then + SongInfo.Header.Resolution := 32 div 4 + Else If (AValues[I].Value = 'SEMIQUAVER') then + SongInfo.Header.Resolution := 16 div 4 + Else If (AValues[I].Value = 'QUAVER') then + SongInfo.Header.Resolution := 8 div 4 + Else If (AValues[I].Value = 'CROTCHET') then + SongInfo.Header.Resolution := 4 div 4 + Else + begin //Can't understand teh Resolution :/ + Result := False; + ErrorMessage := 'Can''t read Resolution from Song'; + end; + end + + Else If (AValues[I].Name = 'GENRE') then + begin + SongInfo.Header.Genre := AValues[I].Value; + end + + Else If (AValues[I].Name = 'YEAR') then + begin + SongInfo.Header.Year := AValues[I].Value; + end + + Else If (AValues[I].Name = 'VERSION') then + begin + SingstarVersion := AValues[I].Value; + end; + end; + + ParserState := PS_Melody; //In Melody Tag + end; + end; + + + PS_Melody: begin //Search for Sentence, Artist/Title Info or eo Melody + If (Tag = 'SENTENCE') then + begin + ParserState := PS_Sentence; //Parse in a Sentence Tag now + + //Increase SentenceCount + Inc(SongInfo.CountSentences); + + BindLyrics := True; //Don't let Txts Begin w/ Space + + //Search for Duett Singer Info + MakeValuesArray; + For I := 0 to High(AValues) do + If (AValues[I].Name = 'SINGER') then + begin + AValues[I].Value := Uppercase(AValues[I].Value); + If (AValues[I].Value = 'SOLO 1') then + CurDuettSinger := DS_Player1 + Else If (AValues[I].Value = 'SOLO 2') then + CurDuettSinger := DS_Player2 + Else + CurDuettSinger := DS_Both; //In case of "Group" or anything that is not identified use Both + end; + end + + Else If (Tag = '!--') then + begin //Comment, this may be Artist or Title Info + I := Pos(':', Values); //Search for Delimiter + + If (I <> 0) then //If Found check for Title or Artist + begin + //Copy Title or Artist Tag to Tag String + Tag := Uppercase(Trim(Copy(Values, 1, I - 1))); + + If (Tag = 'ARTIST') then + begin + SongInfo.Header.Artist := Trim(Copy(Values, I + 1, Length(Values) - I - 2)); + Inc(SongInfo.ID); //Inc SongID when header Information is added + end + Else If (Tag = 'TITLE') then + begin + SongInfo.Header.Title := Trim(Copy(Values, I + 1, Length(Values) - I - 2)); + Inc(SongInfo.ID); //Inc SongID when header Information is added + end; + end; + end + + //Parsing for weird "Die toten Hosen" Tags + Else If (Tag = '!--ARTIST:') OR (Tag = '!--ARTIST') then + begin //Comment, with Artist Info + I := Pos(':', Values); //Search for Delimiter + + Inc(SongInfo.ID); //Inc SongID when header Information is added + + SongInfo.Header.Artist := Trim(Copy(Values, I + 1, Length(Values) - I - 2)); + end + + Else If (Tag = '!--TITLE:') OR (Tag = '!--TITLE') then + begin //Comment, with Artist Info + I := Pos(':', Values); //Search for Delimiter + + Inc(SongInfo.ID); //Inc SongID when header Information is added + + SongInfo.Header.Title := Trim(Copy(Values, I + 1, Length(Values) - I - 2)); + end + + Else If (Tag = '/MELODY') then + begin + ParserState := PS_None; + Exit; //Stop Parsing, Melody iTag ended + end + end; + + + PS_Sentence: begin //Search for Notes or eo Sentence + If (Tag = 'NOTE') then + begin //Found Note + //Get Values + MakeValuesArray; + + NoteType := NT_Normal; + For I := 0 to High(AValues) do + begin + If (AValues[I].Name = 'DURATION') then + begin + Duration := StrtoIntDef(AValues[I].Value, -1); + If (Duration < 0) then + begin + Result := False; + ErrorMessage := 'Can''t read duration from Note in Line: "' + Line + '"'; + Exit; + end; + end + Else If (AValues[I].Name = 'MIDINOTE') then + begin + Tone := StrtoIntDef(AValues[I].Value, 0); + end + Else If (AValues[I].Name = 'BONUS') AND (Uppercase(AValues[I].Value) = 'YES') then + begin + NoteType := NT_Golden; + end + Else If (AValues[I].Name = 'FREESTYLE') AND (Uppercase(AValues[I].Value) = 'YES') then + begin + NoteType := NT_Freestyle; + end + Else If (AValues[I].Name = 'LYRIC') then + begin + Lyric := AValues[I].Value; + + If (Length(Lyric) > 0) then + begin + If (Lyric = '-') then + Lyric[1] := Settings.DashReplacement; + + If (not BindLyrics) then + Lyric := ' ' + Lyric; + + + If (Length(Lyric) > 2) AND (Lyric[Length(Lyric)-1] = ' ') AND (Lyric[Length(Lyric)] = '-') then + begin //Between this and the next Lyric should be no space + BindLyrics := True; + SetLength(Lyric, Length(Lyric) - 2); + end + else + BindLyrics := False; //There should be a Space + end; + end; + end; + + //Add Note + I := SongInfo.CountSentences - 1; + + If (Length(Lyric) > 0) then + begin //Real note, no rest + //First Note of Sentence + If (Length(SongInfo.Sentences) < SongInfo.CountSentences) then + begin + SetLength(SongInfo.Sentences, SongInfo.CountSentences); + SetLength(SongInfo.Sentences[I].Notes, 0); + end; + + //First Note of Song -> Generate Gap + If (FirstNote) then + begin + //Calculate Gap + If (SongInfo.Header.Resolution <> 0) AND (SongInfo.Header.BPM <> 0) then + SongInfo.Header.Gap := Round(CurPosinSong / (SongInfo.Header.BPM*SongInfo.Header.Resolution) * 60000) + Else + begin + Result := False; + ErrorMessage := 'Can''t calculate Gap, no Resolution or BPM present.'; + Exit; + end; + + CurPosinSong := 0; //Start at 0, because Gap goes until here + Inc(SongInfo.ID); //Add Header Value therefore Inc + FirstNote := False; + end; + + J := Length(SongInfo.Sentences[I].Notes); + SetLength(SongInfo.Sentences[I].Notes, J + 1); + SongInfo.Sentences[I].Notes[J].Start := CurPosinSong; + SongInfo.Sentences[I].Notes[J].Duration := Duration; + SongInfo.Sentences[I].Notes[J].Tone := Tone; + SongInfo.Sentences[I].Notes[J].NoteTyp := NoteType; + SongInfo.Sentences[I].Notes[J].Lyric := Lyric; + + //Inc Pos in Song + Inc(CurPosInSong, Duration); + end + else + begin + //just change pos in Song + Inc(CurPosInSong, Duration); + end; + + + end + Else If (Tag = '/SENTENCE') then + begin //End of Sentence Tag + ParserState := PS_Melody; + + //Delete Sentence if no Note is Added + If (Length(SongInfo.Sentences) <> SongInfo.CountSentences) then + begin + SongInfo.CountSentences := Length(SongInfo.Sentences); + end; + end; + end; + end; + + end + else //Empty Line -> parsed succesful ;) + Result := true; +end; + +Function TParser.ParseConfigforEdition(const Filename: String): String; +var + txt: TStringlist; + I: Integer; + J, K: Integer; + S: String; +begin + Result := ''; + txt := TStringlist.Create; + try + txt.LoadFromFile(Filename); + + For I := 0 to txt.Count-1 do + begin + S := Trim(txt.Strings[I]); + J := Pos('', S); + + If (J <> 0) then + begin + Inc(J, 14); + K := Pos('', S); + If (K