diff options
Diffstat (limited to 'Medley/src/screens')
-rw-r--r-- | Medley/src/screens/UScreenScore.pas | 241 | ||||
-rw-r--r-- | Medley/src/screens/UScreenSing.pas | 399 | ||||
-rw-r--r-- | Medley/src/screens/UScreenSong.pas | 150 |
3 files changed, 649 insertions, 141 deletions
diff --git a/Medley/src/screens/UScreenScore.pas b/Medley/src/screens/UScreenScore.pas index ce1b11e5..5a50a3dc 100644 --- a/Medley/src/screens/UScreenScore.pas +++ b/Medley/src/screens/UScreenScore.pas @@ -39,6 +39,7 @@ uses SysUtils, UDisplay, UMusic, + USong, USongs, UThemes, gl, @@ -74,19 +75,30 @@ type BarGolden_ActualHeight: real; end; + TPlayerScoreData = record + Data: array[1..6] of TPlayerScoreScreenData; + end; + TPlayerScoreRatingPics = record // a fine array of the rating pictures RateEaseStep: integer; RateEaseValue: real; end; + TPLayerScorePics = record + Data: array[1..6] of TPlayerScoreRatingPics; + end; + TScreenScore = class(TMenu) private BarTime: cardinal; ArrayStartModifier: integer; public + //TeamInfo: TTeamInfo; aPlayerScoreScreenTextures: array[1..6] of TPlayerScoreScreenTexture; - aPlayerScoreScreenDatas: array[1..6] of TPlayerScoreScreenData; - aPlayerScoreScreenRatings: array[1..6] of TPlayerScoreRatingPics; + aPlayerScoreScreenDatas: array of TPlayerScoreData; + aPlayerScoreScreenRatings: array of TPlayerScorePics; + + ActualRound: integer; BarScore_EaseOut_Step: real; BarPhrase_EaseOut_Step: real; @@ -133,6 +145,7 @@ type procedure OnShow; override; procedure OnShowFinish; override; function Draw: boolean; override; + procedure RefreshTexts; procedure FillPlayer(Item, P: integer); procedure EaseBarIn(PlayerNumber: integer; BarType: string); @@ -190,6 +203,22 @@ begin begin Display.SaveScreenShot; end; + SDLK_RIGHT: + begin + if ActualRound<Length(PlaylistMedley.Stats)-1 then + begin + inc(ActualRound); + RefreshTexts; + end; + end; + SDLK_LEFT: + begin + if ActualRound>0 then + begin + dec(ActualRound); + RefreshTexts; + end; + end; end; end; end; @@ -203,6 +232,37 @@ begin end; end; +procedure TScreenScore.RefreshTexts; +begin + if (ActualRound < Length(PlaylistMedley.Stats)-1) then + begin + Text[TextArtist].Text := IntToStr(ActualRound+1) + '/' + + IntToStr(Length(PlaylistMedley.Stats)-1) + ': ' + + PlaylistMedley.Stats[ActualRound].SongArtist; + Text[TextTitle].Text := PlaylistMedley.Stats[ActualRound].SongTitle; + Text[TextTitle].Visible := true; + Text[TextArtistTitle].Text := IntToStr(ActualRound+1) + '/' + + IntToStr(Length(PlaylistMedley.Stats)-1) + ': ' + + PlaylistMedley.Stats[ActualRound].SongArtist + + ' - ' + PlaylistMedley.Stats[ActualRound].SongTitle; + end else + begin + if (ScreenSong.Mode = smMedley) then + begin + Text[TextArtist].Text := Language.Translate('SING_TOTAL'); + Text[TextTitle].Visible := false; + Text[TextArtistTitle].Text := Language.Translate('SING_TOTAL'); + end else + begin + Text[TextArtist].Text := PlaylistMedley.Stats[ActualRound].SongArtist; + Text[TextTitle].Text := PlaylistMedley.Stats[ActualRound].SongTitle; + Text[TextTitle].Visible := true; + Text[TextArtistTitle].Text := PlaylistMedley.Stats[ActualRound].SongArtist + ' - ' + + PlaylistMedley.Stats[ActualRound].SongTitle; + end; + end; +end; + constructor TScreenScore.Create; var Player: integer; @@ -293,20 +353,21 @@ begin else ArrayStartModifier := 0; //this should never happen end; + ActualRound:=0; + SetLength(aPlayerScoreScreenDatas, Length(PlaylistMedley.Stats)); + SetLength(aPlayerScoreScreenRatings, Length(PlaylistMedley.Stats)); - for P := 1 to PlayersPlay do + for I := 0 to Length(PlaylistMedley.Stats) - 1 do begin - // data - aPlayerScoreScreenDatas[P].Bar_Y := Theme.Score.StaticBackLevel[P + ArrayStartModifier].Y; - - // ratings - aPlayerScoreScreenRatings[P].RateEaseStep := 1; - aPlayerScoreScreenRatings[P].RateEaseValue := 20; + for P := 1 to PlayersPlay do + begin + aPlayerScoreScreenDatas[I].Data[P].Bar_Y := + Theme.Score.StaticBackLevel[P + ArrayStartModifier].Y; + aPlayerScoreScreenRatings[I].Data[P].RateEaseStep := 1; + aPlayerScoreScreenRatings[I].Data[P].RateEaseValue := 20; + end; end; - - Text[TextArtist].Text := CurrentSong.Artist; - Text[TextTitle].Text := CurrentSong.Title; - Text[TextArtistTitle].Text := CurrentSong.Artist + ' - ' + CurrentSong.Title; + RefreshTexts; // set visibility case PlayersPlay of @@ -405,18 +466,6 @@ var PStart: integer; PHigh: integer; begin -{* - player[0].ScoreInt := 7000; - player[0].ScoreLineInt := 2000; - player[0].ScoreGoldenInt := 1000; - player[0].ScoreTotalInt := 10000; - - player[1].ScoreInt := 2500; - player[1].ScoreLineInt := 1100; - player[1].ScoreGoldenInt := 900; - player[1].ScoreTotalInt := 4500; -*} - //Draw the Background DrawBG; @@ -548,7 +597,8 @@ begin Text[TextNotesScore[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100); // total score - Text[TextTotalScore[ThemeIndex]].Text := IntToStr(TextScore_ActualValue[PlayerNumber] + TextPhrase_ActualValue[PlayerNumber] + TextGolden_ActualValue[PlayerNumber]); + Text[TextTotalScore[ThemeIndex]].Text := IntToStr(TextScore_ActualValue[PlayerNumber] + + TextPhrase_ActualValue[PlayerNumber] + TextGolden_ActualValue[PlayerNumber]); Text[TextTotalScore[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100); Text[TextTotal[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100); @@ -562,9 +612,13 @@ begin end; procedure TScreenScore.ShowRating(PlayerNumber: integer); +const + rate_factor: array[0..7] of real = (2.0, 4.0, 5.0, 6.0, 7.5, 8.5, 9.0, 10.0); var Rating: integer; ThemeIndex: integer; + rate_max: array[0..7] of integer; + max, I: integer; begin // We have to do this here because we use the same Theme Object @@ -575,55 +629,57 @@ begin 6: ThemeIndex := ((PlayerNumber-1) mod 3) + 1 + ArrayStartModifier; end; - case (Player[PlayerNumber-1].ScoreTotalInt) of - 0..2009: - begin - Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_TONE_DEAF'); - Rating := 0; - end; - 2010..4009: - begin - Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_AMATEUR'); - Rating := 1; - end; - 4010..5009: - begin - Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_WANNABE'); - Rating := 2; - end; - 5010..6009: - begin - Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_HOPEFUL'); - Rating := 3; - end; - 6010..7509: - begin - Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_RISING_STAR'); - Rating := 4; - end; - 7510..8509: - begin - Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_LEAD_SINGER'); - Rating := 5; - end; - 8510..9009: - begin - Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_SUPERSTAR'); - Rating := 6; - end; - 9010..10000: - begin - Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_ULTRASTAR'); - Rating := 7; - end; + //build rating scores + if ActualRound = Length(PlaylistMedley.Stats)-1 then + max := MAX_SONG_SCORE else + max := max_song_score_medley; + + for I := 0 to 6 do + rate_max[I] := round(max/10*rate_factor[I])+9; + + //fix 7 + rate_max[7] := 10000; + + if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[0] then + begin + Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_TONE_DEAF'); + Rating := 0; + end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[1] then + begin + Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_AMATEUR'); + Rating := 1; + end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[2] then + begin + Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_WANNABE'); + Rating := 2; + end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[3] then + begin + Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_HOPEFUL'); + Rating := 3; + end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[4] then + begin + Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_RISING_STAR'); + Rating := 4; + end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[5] then + begin + Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_LEAD_SINGER'); + Rating := 5; + end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[6] then + begin + Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_SUPERSTAR'); + Rating := 6; + end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[7] then + begin + Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_ULTRASTAR'); + Rating := 7; + end else Rating := 0; // Cheata :P - end; //todo: this could break if the width is not given, for instance when there's a skin with no picture for ratings - if ( Theme.Score.StaticRatings[ThemeIndex].W > 0 ) and ( aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue > 0 ) then + if ( Theme.Score.StaticRatings[ThemeIndex].W > 0 ) and ( aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseValue > 0 ) then begin - Text[TextScore[ThemeIndex]].Alpha := aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue / Theme.Score.StaticRatings[ThemeIndex].W; + Text[TextScore[ThemeIndex]].Alpha := aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseValue / Theme.Score.StaticRatings[ThemeIndex].W; end; // end todo @@ -642,7 +698,7 @@ begin PosX := Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].X + (Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].W * 0.5); PosY := Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].Y + (Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].H * 0.5); ; - Width := aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue/2; + Width := aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseValue/2; glBindTexture(GL_TEXTURE_2D, Tex_Score_Ratings[Rating].TexNum); @@ -669,7 +725,7 @@ var RaiseStep, MaxVal: real; EaseOut_Step: integer; begin - EaseOut_Step := aPlayerScoreScreenRatings[PlayerNumber].RateEaseStep; + EaseOut_Step := aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseStep; MaxVal := Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].W; RaiseStep := EaseOut_Step; @@ -688,8 +744,8 @@ begin s := p/(2*PI) * arcsin (1); ReturnValue := MaxVal * power(2,-5 * RaiseStep) * sin( (RaiseStep * MaxVal - s) * (2 * PI) / p) + MaxVal; - inc(aPlayerScoreScreenRatings[PlayerNumber].RateEaseStep); - aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue := ReturnValue; + inc(aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseStep); + aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseValue := ReturnValue; end; Result := ReturnValue; @@ -716,21 +772,21 @@ begin // EaseOut_Step is the actual step in the raising process, like the 20iest step of EaseOut_MaxSteps if (BarType = 'Note') then begin - Score := Player[PlayerNumber - 1].ScoreInt; + Score := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber - 1].ScoreInt; RaiseStep := BarScore_EaseOut_Step; BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y + MaxHeight; end else if (BarType = 'Line') then begin - Score := Player[PlayerNumber - 1].ScoreLineInt; + Score := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber - 1].ScoreLineInt; RaiseStep := BarPhrase_EaseOut_Step; - BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight + MaxHeight; + BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarScore_ActualHeight + MaxHeight; end else if (BarType = 'Golden') then begin - Score := Player[PlayerNumber - 1].ScoreGoldenInt; + Score := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber - 1].ScoreGoldenInt; RaiseStep := BarGolden_EaseOut_Step; - BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight - aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight + MaxHeight; + BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarScore_ActualHeight - aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarLine_ActualHeight + MaxHeight; end else begin @@ -739,9 +795,12 @@ begin end; // the height dependend of the score - Height2Reach := (Score / MAX_SONG_SCORE) * MaxHeight; + if ActualRound=Length(PlaylistMedley.Stats)-1 then + Height2Reach := (Score / MAX_SONG_SCORE) * MaxHeight + else + Height2Reach := (Score / max_song_score_medley) * MaxHeight; - if (aPlayerScoreScreenDatas[PlayerNumber].Bar_Actual_Height < Height2Reach) then + if (aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].Bar_Actual_Height < Height2Reach) then begin // Check http://proto.layer51.com/d.aspx?f=400 for more info on easing functions // Calculate the actual step according to the maxsteps @@ -761,11 +820,11 @@ begin DrawBar(BarType, PlayerNumber, BarStartPosY, NewHeight); if (BarType = 'Note') then - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight := NewHeight + aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarScore_ActualHeight := NewHeight else if (BarType = 'Line') then - aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight := NewHeight + aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarLine_ActualHeight := NewHeight else if (BarType = 'Golden') then - aPlayerScoreScreenDatas[PlayerNumber].BarGolden_ActualHeight := NewHeight; + aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarGolden_ActualHeight := NewHeight; end; procedure TscreenScore.DrawBar(BarType: string; PlayerNumber: integer; BarStartPosY: single; NewHeight: real); @@ -839,19 +898,19 @@ begin begin EaseOut_Step := BarScore_EaseOut_Step; ActualScoreValue := TextScore_ActualValue[PlayerNumber]; - ScoreReached := Player[PlayerNumber-1].ScoreInt; + ScoreReached := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreInt; end; if (ScoreType = 'Line') then begin EaseOut_Step := BarPhrase_EaseOut_Step; ActualScoreValue := TextPhrase_ActualValue[PlayerNumber]; - ScoreReached := Player[PlayerNumber-1].ScoreLineInt; + ScoreReached := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreLineInt; end; if (ScoreType = 'Golden') then begin EaseOut_Step := BarGolden_EaseOut_Step; ActualScoreValue := TextGolden_ActualValue[PlayerNumber]; - ScoreReached := Player[PlayerNumber-1].ScoreGoldenInt; + ScoreReached := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreGoldenInt; end; // EaseOut_Step is the actual step in the raising process, like the 20iest step of EaseOut_MaxSteps @@ -893,7 +952,7 @@ var begin Text[TextName[Item]].Text := Ini.Name[P]; - S := IntToStr((Round(Player[P].Score) div 10) * 10); + S := IntToStr((Round(PlaylistMedley.Stats[ActualRound].Player[P].Score) div 10) * 10); while (Length(S)<4) do S := '0' + S; Text[TextNotesScore[Item]].Text := S; @@ -903,17 +962,17 @@ begin //fixed: line bonus and golden notes don't show up, // another bug: total score was shown without added golden-, linebonus - S := IntToStr(Player[P].ScoreTotalInt); + S := IntToStr(PlaylistMedley.Stats[ActualRound].Player[P].ScoreTotalInt); while (Length(S)<5) do S := '0' + S; Text[TextTotalScore[Item]].Text := S; - S := IntToStr(Player[P].ScoreLineInt); + S := IntToStr(PlaylistMedley.Stats[ActualRound].Player[P].ScoreLineInt); while (Length(S)<4) do S := '0' + S; Text[TextLineBonusScore[Item]].Text := S; - S := IntToStr(Player[P].ScoreGoldenInt); + S := IntToStr(PlaylistMedley.Stats[ActualRound].Player[P].ScoreGoldenInt); while (Length(S)<4) do S := '0' + S; Text[TextGoldenNotesScore[Item]].Text := S; diff --git a/Medley/src/screens/UScreenSing.pas b/Medley/src/screens/UScreenSing.pas index 342abac1..1bc16754 100644 --- a/Medley/src/screens/UScreenSing.pas +++ b/Medley/src/screens/UScreenSing.pas @@ -46,10 +46,12 @@ uses UMenu, UMusic, USingScores, + USong, USongs, UTexture, UThemes, UPath, + UPathUtils, UTime; type @@ -95,6 +97,11 @@ type FadeOut: boolean; Lyrics: TLyricEngine; + SongNameStatic: integer; + SongNameText: integer; + + ApplauseSounds: array of TAudioPlaybackStream; + // score manager: Scores: TSingScores; @@ -112,6 +119,8 @@ type function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override; function Draw: boolean; override; + procedure LoadNextSong; + procedure UpdateMedleyStats(medley_end: boolean); procedure Finish; virtual; procedure Pause; // toggle pause @@ -130,7 +139,6 @@ uses ULanguage, UNote, URecord, - USong, UDisplay, UUnicodeUtils; @@ -149,7 +157,14 @@ begin begin // when not ask before exit then finish now if (Ini.AskbeforeDel <> 1) then - Finish + begin + if ScreenSong.Mode=smMedley then + PlaylistMedley.CurrentMedleySong:=PlaylistMedley.NumMedleySongs+1; + Finish; + AudioPlayback.PlaySound(SoundLib.Back); + FadeOut := true; + FadeTo(@ScreenScore); + end // else just pause and let the popup make the work else if not Paused then Pause; @@ -185,9 +200,11 @@ begin begin // record sound hack: //Sound[0].BufferLong - + if ScreenSong.Mode=smMedley then + PlaylistMedley.CurrentMedleySong:=PlaylistMedley.NumMedleySongs+1; Finish; AudioPlayback.PlaySound(SoundLib.Back); + FadeOut := true; FadeTo(@ScreenScore); end; @@ -307,11 +324,18 @@ begin // <note> pausepopup is not visibile at the beginning </note> Static[StaticPausePopup].Visible := false; + SongNameStatic := AddStatic(Theme.Sing.StaticSongName); + SongNameText := AddText(Theme.Sing.TextSongName); + Lyrics := TLyricEngine.Create( Theme.LyricBar.UpperX, Theme.LyricBar.UpperY, Theme.LyricBar.UpperW, Theme.LyricBar.UpperH, Theme.LyricBar.LowerX, Theme.LyricBar.LowerY, Theme.LyricBar.LowerW, Theme.LyricBar.LowerH); LyricsSync := TLyricsSyncSource.Create(); + + SetLength(ApplauseSounds, 1); + FreeAndNil(ApplauseSounds[0]); + ApplauseSounds[0] := AudioPlayback.OpenSound(SoundPath.Append('Applause.mp3')); end; procedure TScreenSing.OnShow; @@ -334,6 +358,19 @@ begin //the song was sung to the end SungToEnd := false; + //Reset Player Medley stats + if ScreenSong.Mode = smMedley then + begin + PlaylistMedley.CurrentMedleySong:=1; + PlaylistMedley.ApplausePlayed := false; + + //max_song_score_medley := round(MAX_SONG_SCORE / NumMedleySongs); + //max_song_line_bonus_medley := round(MAX_SONG_LINE_BONUS / NumMedleySongs); + PlaylistMedley.NumPlayer := PlayersPlay; + SetLength(PlaylistMedley.Stats, 0); + max_song_score_medley := round(MAX_SONG_SCORE / PlaylistMedley.NumMedleySongs); + max_song_line_bonus_medley := round(MAX_SONG_LINE_BONUS / PlaylistMedley.NumMedleySongs); + end; // reset video playback engine, to play video clip ... fCurrentVideoPlaybackEngine := VideoPlayback; @@ -425,10 +462,43 @@ begin Static[StaticP3R].Visible := V3R; Text[TextP3R].Visible := V3R; + if ScreenSong.Mode = smMedley then + begin + Static[SongNameStatic].Visible := true; + Text[SongNameText].Visible := true; + end else + begin + Static[SongNameStatic].Visible := false; + Text[SongNameText].Visible := false; + end; + + LoadNextSong; + + Log.LogStatus('End', 'OnShow'); +end; + +procedure TScreenSing.LoadNextSong; +var + Index: integer; + VideoFile, BgFile: IPath; + success: boolean; + +begin // FIXME: sets path and filename to '' + //AudioPlayback.Stop(); ResetSingTemp; - - CurrentSong := CatSongs.Song[CatSongs.Selected]; + + if ScreenSong.Mode <> smMedley then + CurrentSong := CatSongs.Song[CatSongs.Selected] + else + begin + CurrentSong := CatSongs.Song[PlaylistMedley.Song[PlaylistMedley.CurrentMedleySong-1]]; + {AudioPlayback.Open(CurrentSong[CatSongsMedley.Selected].Path.Append(CatSongsMedley.Song[CatSongsMedley.Selected].Mp3)); + CurrentSong := CatSongsMedley.Song[CatSongsMedley.Selected]; + Text[SongNameText].Text := 'Medley ' + IntToStr(CurrentMedleySong)+'/'+ + IntToStr(NumMedleySongs)+': '+ + CurrentSong.Artist+' - '+CurrentSong.Title;} + end; // FIXME: bad style, put the try-except into loadsong() and not here try @@ -445,6 +515,7 @@ begin begin // error loading song -> go back to song screen and show some error message FadeTo(@ScreenSong); + // select new song in party mode if ScreenSong.Mode = smPartyMode then ScreenSong.SelectRandomSong(); @@ -453,10 +524,17 @@ begin else ScreenPopupError.ShowPopup(Language.Translate('ERROR_CORRUPT_SONG')); // FIXME: do we need this? - CurrentSong.Path := CatSongs.Song[CatSongs.Selected].Path; + //CurrentSong.Path := CatSongs.Song[CatSongs.Selected].Path; Exit; end; + if ScreenSong.Mode = smMedley then + begin + CurrentSong.SetMedleyMode; + Text[SongNameText].Text := IntToStr(PlaylistMedley.CurrentMedleySong) + + '/' + IntToStr(PlaylistMedley.NumMedleySongs) + ': ' + + CurrentSong.Artist + ' - ' + CurrentSong.Title; + end; // reset video playback engine, to play video clip ... fCurrentVideoPlaybackEngine.Close; fCurrentVideoPlaybackEngine := VideoPlayback; @@ -484,7 +562,12 @@ begin begin fShowVisualization := false; fCurrentVideoPlaybackEngine := VideoPlayback; - fCurrentVideoPlaybackEngine.Position := CurrentSong.VideoGAP + CurrentSong.Start; + if ScreenSong.Mode <> smMedley then + fCurrentVideoPlaybackEngine.Position := CurrentSong.VideoGAP + CurrentSong.Start + else + fCurrentVideoPlaybackEngine.Position := CurrentSong.VideoGAP + + GetTimeFromBeat(CurrentSong.Medley.StartBeat) - CurrentSong.Medley.FadeIn_time + + CurrentSong.Start; fCurrentVideoPlaybackEngine.Play; VideoLoaded := true; end; @@ -534,17 +617,34 @@ begin // prepare lyrics timer LyricsState.Reset(); - LyricsState.SetCurrentTime(CurrentSong.Start); - LyricsState.StartTime := CurrentSong.Gap; - if (CurrentSong.Finish > 0) then - LyricsState.TotalTime := CurrentSong.Finish / 1000 - else - LyricsState.TotalTime := AudioPlayback.Length; - LyricsState.UpdateBeats(); + if ScreenSong.Mode <> smMedley then + begin + LyricsState.SetCurrentTime(CurrentSong.Start); //in seconds + LyricsState.StartTime := CurrentSong.Gap; //in milliseconds + if (CurrentSong.Finish > 0) then + LyricsState.TotalTime := CurrentSong.Finish / 1000 //in seconds + else + LyricsState.TotalTime := AudioPlayback.Length; + LyricsState.UpdateBeats(); - // prepare music - AudioPlayback.Stop(); - AudioPlayback.Position := CurrentSong.Start; + // prepare music + AudioPlayback.Stop(); + AudioPlayback.Position := CurrentSong.Start; + end else + begin + LyricsState.SetCurrentTime(GetTimeFromBeat(CurrentSong.Medley.StartBeat) - CurrentSong.Medley.FadeIn_time); + LyricsState.StartTime := CurrentSong.Gap; + if (CurrentSong.Finish > 0) then + LyricsState.TotalTime := CurrentSong.Finish / 1000 //in seconds + else + LyricsState.TotalTime := AudioPlayback.Length; + LyricsState.UpdateBeats(); + + // prepare music + AudioPlayback.Stop(); + AudioPlayback.Open(CurrentSong.Path.Append(CurrentSong.Mp3)); + AudioPlayback.Position := GetTimeFromBeat(CurrentSong.Medley.StartBeat) - CurrentSong.Medley.FadeIn_time; + end; // synchronize music to the lyrics AudioPlayback.SetSyncSource(LyricsSync); @@ -572,7 +672,7 @@ begin // main text Lyrics.Clear(CurrentSong.BPM[0].BPM, CurrentSong.Resolution); - + // set custom options case Ini.LyricsFont of 0: // normal fonts @@ -615,42 +715,82 @@ begin end; end; // case - // initialize lyrics by filling its queue - while (not Lyrics.IsQueueFull) and + if ScreenSong.Mode <> smMedley then + begin + // initialize lyrics by filling its queue + while (not Lyrics.IsQueueFull) and (Lyrics.LineCounter <= High(Lines[0].Line)) do + begin + Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]); + end; + + // deactivate pause + Paused := false; + + // kill all stars not killed yet (goldenstarstwinkle mod) + GoldenRec.SentenceChange; + + // set position of line bonus - line bonus end + // set number of empty sentences for line bonus + NumEmptySentences := 0; + for Index := Low(Lines[0].Line) to High(Lines[0].Line) do + if Lines[0].Line[Index].TotalNotes = 0 then + Inc(NumEmptySentences); + end else begin - Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]); + // initialize lyrics by filling its queue + while (not Lyrics.IsQueueFull) and + (Lyrics.LineCounter <= High(Lines[0].Line)) do + begin + Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]); + end; + + // deactivate pause + Paused := false; + + // kill all stars not killed yet (goldenstarstwinkle mod) + GoldenRec.SentenceChange; + + // set position of line bonus - line bonus end + // set number of empty sentences for line bonus + NumEmptySentences := 0; + for Index := Low(Lines[0].Line) to High(Lines[0].Line) do + if Lines[0].Line[Index].TotalNotes = 0 then + Inc(NumEmptySentences); end; - // deactivate pause - Paused := false; + //Test + // start lyrics + LyricsState.Resume(); - // kill all stars not killed yet (goldenstarstwinkle mod) - GoldenRec.SentenceChange; + // start music + if ScreenSong.Mode <> smMedley then + AudioPlayback.Play() + else + begin + AudioPlayback.SetVolume(0.3); + AudioPlayback.FadeIn(CurrentSong.Medley.FadeIn_time, 1.0); + end; - // set position of line bonus - line bonus end - // set number of empty sentences for line bonus - NumEmptySentences := 0; - for Index := Low(Lines[0].Line) to High(Lines[0].Line) do - if Lines[0].Line[Index].TotalNotes = 0 then - Inc(NumEmptySentences); + // start timer + CountSkipTimeSet; - Log.LogStatus('End', 'OnShow'); + PlaylistMedley.ApplausePlayed := false; end; procedure TScreenSing.onShowFinish; begin - // hide cursor on singscreen show + //hide cursor on singscreen show Display.SetCursor; - + // start lyrics - LyricsState.Resume(); + //LyricsState.Resume(); // start music - AudioPlayback.Play(); + //AudioPlayback.Play(); // start timer - CountSkipTimeSet; + //CountSkipTimeSet; end; procedure TScreenSing.OnHide; @@ -672,6 +812,8 @@ var Sec: integer; T: integer; CurLyricsTime: real; + medley_end: boolean; + medley_start_applause: boolean; Line: TLyricLine; LastWord: TLyricWord; begin @@ -742,7 +884,12 @@ begin // retrieve current lyrics time, we have to store the value to avoid // that min- and sec-values do not match - CurLyricsTime := LyricsState.GetCurrentTime(); + if ScreenSong.Mode <> smMedley then + CurLyricsTime := LyricsState.TotalTime - LyricsState.GetCurrentTime() + else + CurLyricsTime := GetTimeFromBeat(CurrentSong.Medley.EndBeat) + + CurrentSong.Medley.FadeOut_time - LyricsState.GetCurrentTime(); + Min := Round(CurLyricsTime) div 60; Sec := Round(CurLyricsTime) mod 60; @@ -785,24 +932,44 @@ begin // draw static menu (FG) DrawFG; + if (ScreenSong.Mode = smMedley) and (LyricsState.GetCurrentTime() > + GetTimeFromBeat(CurrentSong.Medley.EndBeat) + CurrentSong.Medley.FadeOut_time) then + medley_end := true + else + medley_end := false; + + if (ScreenSong.Mode = smMedley) and (LyricsState.GetCurrentTime() > + GetTimeFromBeat(CurrentSong.Medley.EndBeat)) then + medley_start_applause := true + else + medley_start_applause := false; + // check for music finish //Log.LogError('Check for music finish: ' + BoolToStr(Music.Finished) + ' ' + FloatToStr(LyricsState.CurrentTime*1000) + ' ' + IntToStr(CurrentSong.Finish)); if ShowFinish then begin - if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or + if (not AudioPlayback.Finished) and not medley_end and ((CurrentSong.Finish = 0) or (LyricsState.GetCurrentTime() * 1000 <= CurrentSong.Finish)) then begin // analyze song if not paused if (not Paused) then + begin Sing(Self); + //Update Medley Stats + if (ScreenSong.Mode = smMedley) and not FadeOut then + UpdateMedleyStats(medley_start_applause); + end; end else begin if (not FadeOut) then begin Finish; - FadeOut := true; - FadeTo(@ScreenScore); + if ScreenSong.Mode = smNormal then + begin + FadeOut := true; + FadeTo(@ScreenScore); + end; end; end; end; @@ -850,7 +1017,49 @@ begin Result := true; end; +procedure TScreenSing.UpdateMedleyStats(medley_end: boolean); +var + len, num, I : integer; + lastline: boolean; + vol: real; +begin + len := Length(PlaylistMedley.Stats); + num := PlaylistMedley.NumPlayer; + + if (PlaylistMedley.CurrentMedleySong>len) and + (PlaylistMedley.CurrentMedleySong<=PlaylistMedley.NumMedleySongs) then + begin + inc(len); + SetLength(PlaylistMedley.Stats, len); + SetLength(PlaylistMedley.Stats[len-1].Player, num); + PlaylistMedley.Stats[len-1].SongArtist := CurrentSong.Artist; + PlaylistMedley.Stats[len-1].SongTitle := CurrentSong.Title; + end; + + if (PlaylistMedley.CurrentMedleySong<=PlaylistMedley.NumMedleySongs) then + for I := 0 to num - 1 do + PlaylistMedley.Stats[len-1].Player[I] := Player[I]; + + if medley_end and not PlaylistMedley.ApplausePlayed and + (PlaylistMedley.CurrentMedleySong<=PlaylistMedley.NumMedleySongs) then + begin + PlaylistMedley.ApplausePlayed:=true; + AudioPlayback.PlaySound(ApplauseSounds[0]); + end; + + if(LyricsState.GetCurrentTime() > GetTimeFromBeat(CurrentSong.Medley.EndBeat)) then + begin + vol := 1-(LyricsState.GetCurrentTime() - GetTimeFromBeat(CurrentSong.Medley.EndBeat))/ + CurrentSong.Medley.FadeOut_time ; + AudioPlayback.SetVolume(vol); //used as fade out! + end; +end; + procedure TScreenSing.Finish; +var + I, J: integer; + len, num: integer; + Color: TRGB; begin AudioInput.CaptureStop; AudioPlayback.Stop; @@ -879,6 +1088,91 @@ begin end; SetFontItalic(false); + + if ScreenSong.Mode = smMedley then + begin + {***** just a quick and dirty fix.... *******} + // setup score manager + Scores.ClearPlayers; // clear old player values + + Color.R := 0; + Color.G := 0; + Color.B := 0; + // add new players + for I := 0 to PlayersPlay - 1 do + begin + Scores.AddPlayer(Tex_ScoreBG[I], Color); + end; + + Scores.Init; // get positions for players + + // prepare players + SetLength(Player, PlayersPlay); + {***** end of quick and dirty fix ******} + + if not FadeOut then + begin + inc(PlaylistMedley.CurrentMedleySong); + if PlaylistMedley.CurrentMedleySong<=PlaylistMedley.NumMedleySongs then + begin + //AudioPlayback.PlaySound(SoundLib.Applause); + LoadNextSong; + end else + begin + //build sums + len := Length(PlaylistMedley.Stats); + num := PlaylistMedley.NumPlayer; + + SetLength(PlaylistMedley.Stats, len+1); + SetLength(PlaylistMedley.Stats[len].Player, num); + + for J := 0 to len - 1 do + begin + for I := 0 to num - 1 do + begin + PlaylistMedley.Stats[len].Player[I].Score := + PlaylistMedley.Stats[len].Player[I].Score + + PlaylistMedley.Stats[J].Player[I].Score; + + PlaylistMedley.Stats[len].Player[I].ScoreLine := + PlaylistMedley.Stats[len].Player[I].ScoreLine + + PlaylistMedley.Stats[J].Player[I].ScoreLine; + + PlaylistMedley.Stats[len].Player[I].ScoreGolden := + PlaylistMedley.Stats[len].Player[I].ScoreGolden + + PlaylistMedley.Stats[J].Player[I].ScoreGolden; + + PlaylistMedley.Stats[len].Player[I].ScoreInt := + PlaylistMedley.Stats[len].Player[I].ScoreInt + + PlaylistMedley.Stats[J].Player[I].ScoreInt; + + PlaylistMedley.Stats[len].Player[I].ScoreLineInt := + PlaylistMedley.Stats[len].Player[I].ScoreLineInt + + PlaylistMedley.Stats[J].Player[I].ScoreLineInt; + + PlaylistMedley.Stats[len].Player[I].ScoreGoldenInt := + PlaylistMedley.Stats[len].Player[I].ScoreGoldenInt + + PlaylistMedley.Stats[J].Player[I].ScoreGoldenInt; + + PlaylistMedley.Stats[len].Player[I].ScoreTotalInt := + PlaylistMedley.Stats[len].Player[I].ScoreTotalInt + + PlaylistMedley.Stats[J].Player[I].ScoreTotalInt; + end; //of for I + end; //of for J + + FadeOut:=true; + FadeTo(@ScreenScore); + end; + end; + end else + begin + SetLength(PlaylistMedley.Stats, 1); + SetLength(PlaylistMedley.Stats[0].Player, PlayersPlay); + for I := 0 to PlayersPlay - 1 do + PlaylistMedley.Stats[0].Player[I] := Player[I]; + PlaylistMedley.Stats[0].SongArtist := CurrentSong.Artist; + PlaylistMedley.Stats[0].SongTitle := CurrentSong.Title; + end; end; procedure TScreenSing.OnSentenceEnd(SentenceIndex: cardinal); @@ -904,10 +1198,19 @@ begin Exit; // set max song score - if (Ini.LineBonus = 0) then - MaxSongScore := MAX_SONG_SCORE - else - MaxSongScore := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS; + if ScreenSong.Mode <> smMedley then + begin + if (Ini.LineBonus = 0) then + MaxSongScore := MAX_SONG_SCORE + else + MaxSongScore := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS; + end else + begin + if (Ini.LineBonus = 0) then + MaxSongScore := max_song_score_medley + else + MaxSongScore := max_song_score_medley - max_song_line_bonus_medley; + end; // Note: ScoreValue is the sum of all note values of the song MaxLineScore := MaxSongScore * (Line.TotalNotes / Lines[0].ScoreValue); @@ -941,7 +1244,11 @@ begin if (Ini.LineBonus > 0) then begin // line-bonus points (same for each line, no matter how long the line is) - LineBonus := MAX_SONG_LINE_BONUS / (Length(Lines[0].Line) - + if ScreenSong.Mode <> smMedley then + LineBonus := MAX_SONG_LINE_BONUS / (Length(Lines[0].Line) - + NumEmptySentences) + else + LineBonus := max_song_line_bonus_medley / (Length(Lines[0].Line) - NumEmptySentences); // apply line-bonus CurrentPlayer.ScoreLine := diff --git a/Medley/src/screens/UScreenSong.pas b/Medley/src/screens/UScreenSong.pas index bd5eebe5..bab2ef51 100644 --- a/Medley/src/screens/UScreenSong.pas +++ b/Medley/src/screens/UScreenSong.pas @@ -53,6 +53,8 @@ uses UTime; type + TVisArr = array of integer; + TScreenSong = class(TMenu) private Equalizer: Tms_Equalizer; @@ -138,6 +140,9 @@ type procedure HideCatTL;// Show Cat in Tob left procedure Refresh; //Refresh Song Sorting procedure ChangeMusic; + + function getVisibleMedleyArr(): TVisArr; + procedure StartMedley(num: integer); //Party Mode procedure SelectRandomSong; procedure SetJoker; @@ -345,6 +350,21 @@ begin Exit; end; + Ord('S'): + begin + if (Length(getVisibleMedleyArr()) > 0) and (Mode = smNormal) and + (CatSongs.Song[Interaction].Medley.Source = msTag) then + begin + StartMedley(0); + end; + end; + Ord('D'): + begin + if (Length(getVisibleMedleyArr()) > 0) and (Mode = smNormal) then + begin + StartMedley(5); + end; + end; Ord('M'): //Show SongMenu begin if (Songs.SongList.Count > 0) then @@ -1002,6 +1022,11 @@ begin // Set texts Text[TextArtist].Text := CatSongs.Song[Interaction].Artist; Text[TextTitle].Text := CatSongs.Song[Interaction].Title; + + //medley mod + if CatSongs.Song[Interaction].Medley.Source = msTag then + Text[TextTitle].Text := Text[TextTitle].Text + '[M]'; + if (Ini.TabsAtStartup = 1) and (CatSongs.CatNumShow = -1) then begin Text[TextNumber].Text := IntToStr(CatSongs.Song[Interaction].OrderNum) + '/' + IntToStr(CatSongs.CatCount); @@ -1496,6 +1521,9 @@ begin AudioPlayback.Stop; + if Mode = smMedley then + Mode := smNormal; + if Ini.Players <= 3 then PlayersPlay := Ini.Players + 1; if Ini.Players = 4 then PlayersPlay := 6; @@ -1725,19 +1753,29 @@ end; procedure TScreenSong.StartMusicPreview(); var - Song: TSong; + Song: TSong; + success: boolean; begin AudioPlayback.Close(); + if CatSongs.Song[Interaction].Main then + Exit; + Song := CatSongs.Song[Interaction]; - if not assigned(Song) then + if not assigned(Song) or Song.Main then Exit; if AudioPlayback.Open(Song.Path.Append(Song.Mp3)) then begin PreviewOpened := Interaction; - - AudioPlayback.Position := AudioPlayback.Length / 4; + + if Song.Medley.Source <> msNone then + begin + CurrentSong := Song; + AudioPlayback.Position := GetTimeFromBeat(Song.Medley.StartBeat); + end else + AudioPlayback.Position := AudioPlayback.Length / 4; + // set preview volume if (Ini.PreviewFading = 0) then begin @@ -1747,6 +1785,10 @@ begin end else begin + AudioPlayback.Position := AudioPlayback.Position - Ini.PreviewFading; + if AudioPlayback.Position<0 then + AudioPlayback.Position := 0; + // music fade enabled: start muted and fade-in AudioPlayback.SetVolume(0); AudioPlayback.FadeIn(Ini.PreviewFading, IPreviewVolumeVals[Ini.PreviewVolume]); @@ -1796,6 +1838,106 @@ begin end; end; +function TScreenSong.getVisibleMedleyArr(): TVisArr; +var + I: integer; + res: TVisArr; +begin + SetLength(res, 0); + for I := 0 to Length(CatSongs.Song) - 1 do + begin + if CatSongs.Song[I].Visible and (CatSongs.Song[I].Medley.Source = msTag) then + begin + SetLength(res, Length(res)+1); + res[Length(res)-1] := I; + end; + end; + Result := res; +end; + +//start Medley round +procedure TScreenSong.StartMedley(num: integer); + procedure AddSong(SongNr: integer); + begin + SetLength(PlaylistMedley.Song, Length(PlaylistMedley.Song)+1); + PlaylistMedley.Song[Length(PlaylistMedley.Song)-1] := SongNr; + end; + + function SongAdded(SongNr: integer): boolean; + var + i: integer; + skipped :boolean; + begin + skipped := false; + for i := 0 to Length(PlaylistMedley.Song) - 1 do + begin + if (SongNr=PlaylistMedley.Song[i]) then + begin + skipped:=true; + break; + end; + end; + Result:=skipped; + end; + + function NumSongsAdded(): Integer; + begin + Result := Length(PlaylistMedley.Song); + end; + + function GetNextSongNr: integer; + var + I, num: integer; + unused_arr: array of integer; + visible_arr: TVisArr; + begin + SetLength(unused_arr, 0); + visible_arr := getVisibleMedleyArr(); + for I := 0 to Length(visible_arr) - 1 do + begin + if (not SongAdded(visible_arr[I])) then + begin + SetLength(unused_arr, Length(unused_arr)+1); + unused_arr[Length(unused_arr)-1] := visible_arr[I]; + end; + end; + + num := random(Length(unused_arr)); + Result := unused_arr[num]; +end; + +var + I: integer; + VS: integer; + +begin + StopMusicPreview(); + Mode := smMedley; + + if num>0 then + begin + VS := Length(getVisibleMedleyArr()); + if VS < num then + PlaylistMedley.NumMedleySongs := VS + else + PlaylistMedley.NumMedleySongs := num; + + Randomize; + //set up Playlist Medley + SetLength(PlaylistMedley.Song, 0); + for I := 0 to PlaylistMedley.NumMedleySongs - 1 do + begin + AddSong(GetNextSongNr); + end; + end else + begin + SetLength(PlaylistMedley.Song, 1); + PlaylistMedley.Song[0] := Interaction; + PlaylistMedley.NumMedleySongs := 1; + end; + FadeTo(@ScreenSing); +end; + procedure TScreenSong.SkipTo(Target: cardinal); var i: integer; |