diff --git a/PartyModes/PartyModeTicTacToe/CPartyScreenTicTacToeMain.cs b/PartyModes/PartyModeTicTacToe/CPartyScreenTicTacToeMain.cs index 1ffe157b..35f45351 100644 --- a/PartyModes/PartyModeTicTacToe/CPartyScreenTicTacToeMain.cs +++ b/PartyModes/PartyModeTicTacToe/CPartyScreenTicTacToeMain.cs @@ -73,7 +73,6 @@ namespace VocaluxeLib.PartyModes.TicTacToe private const int _FieldSpace = 10; private float _FieldSize = 100; - private int _PreviewStream = -1; private int _OldSelectedField = -1; private int[,] _Possibilities; @@ -267,8 +266,6 @@ namespace VocaluxeLib.PartyModes.TicTacToe { base.OnShow(); - _PreviewStream = -1; - if (_PartyMode.GameData.CurrentRoundNr == 1) { _BuildWinnerPossibilities(); @@ -334,13 +331,6 @@ namespace VocaluxeLib.PartyModes.TicTacToe return true; } - public override void OnClose() - { - base.OnClose(); - CBase.BackgroundMusic.SetDisabled(false); - CBase.Sound.Fade(_PreviewStream, 0, 0.5f, EStreamAction.Close); - } - private void _CreateFields() { for (int i = 0; i < 25; i++) @@ -490,14 +480,7 @@ namespace VocaluxeLib.PartyModes.TicTacToe private void _StartPreview(int songID) { CSong song = CBase.Songs.GetSongByID(songID); - CBase.BackgroundMusic.SetDisabled(true); - - _PreviewStream = CBase.Sound.Load(song.GetMP3()); - CBase.Sound.SetGlobalVolume(CBase.Config.GetMusicVolume(EMusicType.Preview)); - CBase.Sound.SetPosition(_PreviewStream, song.Preview.StartTime); - CBase.Sound.SetStreamVolume(_PreviewStream, 0); - CBase.Sound.Play(_PreviewStream); - CBase.Sound.Fade(_PreviewStream, 100, 1f); + CBase.BackgroundMusic.LoadPreview(song); } private void _UpdatePlayerInformation() @@ -525,8 +508,6 @@ namespace VocaluxeLib.PartyModes.TicTacToe if (_PartyMode.GameData.NumJokerRandom[teamNr] > 0) { _PartyMode.GameData.NumJokerRandom[teamNr]--; - if (!CBase.Sound.IsFinished(_PreviewStream)) - CBase.Sound.Fade(_PreviewStream, 0, 1, EStreamAction.Close); _FieldSelected(true); } break; @@ -537,8 +518,6 @@ namespace VocaluxeLib.PartyModes.TicTacToe { _PartyMode.GameData.NumJokerRetry[teamNr]--; _PartyMode.GameData.Team = teamNr; - if (!CBase.Sound.IsFinished(_PreviewStream)) - CBase.Sound.Fade(_PreviewStream, 0, 1, EStreamAction.Close); _Status = EStatus.JokerRetry; _OldSelectedField = _PartyMode.GameData.FieldNr; _PartyMode.GameData.FieldNr = -1; @@ -579,13 +558,11 @@ namespace VocaluxeLib.PartyModes.TicTacToe private void _NextRound() { - CBase.Sound.Fade(_PreviewStream, 0, 0.5f, EStreamAction.Close); _PartyMode.Next(); } private void _EndParty() { - CBase.Sound.Fade(_PreviewStream, 0, 0.5f, EStreamAction.Close); CBase.Graphics.FadeTo(EScreen.Party); } @@ -604,7 +581,6 @@ namespace VocaluxeLib.PartyModes.TicTacToe private void _Back() { - CBase.Sound.Fade(_PreviewStream, 0, 0.5f, EStreamAction.Close); _PartyMode.Back(); } diff --git a/Vocaluxe/Base/CBackgroundMusic.cs b/Vocaluxe/Base/CBackgroundMusic.cs index 1e38e42b..c01a334d 100644 --- a/Vocaluxe/Base/CBackgroundMusic.cs +++ b/Vocaluxe/Base/CBackgroundMusic.cs @@ -18,7 +18,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using VocaluxeLib; using VocaluxeLib.Songs; using VocaluxeLib.Draw; @@ -30,12 +29,12 @@ namespace Vocaluxe.Base { private static bool _Initialized; - private static CSongPlayer _SongPlayer; - private static CSongPlayer _PreviewPlayer; + private static readonly CSongPlayer _BGPlayer = new CSongPlayer(); + private static readonly CSongPlayer _PreviewPlayer = new CSongPlayer(true); + private static CSongPlayer _CurPlayer; private static bool _OwnSongsAvailable; private static EBackgroundMusicSource _MusicSource; - private static bool _VideoEnabled; private static CPlaylistElement _CurrentPlaylistElement; //Currently played music private static int _PreviousMusicIndex = -1; @@ -47,29 +46,20 @@ namespace Vocaluxe.Base private static bool _OwnMusicAdded; private static bool _BackgroundMusicAdded; private static bool _Disabled; - private static bool _PlaysPreview; public static bool VideoEnabled { - get { return _PlaysPreview ? _PreviewPlayer.VideoEnabled : _SongPlayer.VideoEnabled; } - set - { - if (_PlaysPreview) - _PreviewPlayer.VideoEnabled = value; - else - _SongPlayer.VideoEnabled = value; - } + get { return _CurPlayer.VideoEnabled; } + set { _CurPlayer.VideoEnabled = value; } } public static bool CanSing { get { - if (_PlaysPreview) + if (IsPlayingPreview) return false; - if (_BGMusicFiles.Contains(_CurrentPlaylistElement)) - return false; - return true; + return !_BGMusicFiles.Contains(_CurrentPlaylistElement); } } @@ -81,54 +71,63 @@ namespace Vocaluxe.Base if (Disabled == value) return; _Disabled = value; - Pause(); + if (_Disabled) + Pause(); + else + Play(); } } + /// + /// Repeat the background song (preview songs are always repeating!) + /// public static bool RepeatSong { - get { return _SongPlayer.RepeatSong; } - set { _SongPlayer.RepeatSong = value; } + get { return _BGPlayer.Loop; } + set { _BGPlayer.Loop = value; } } public static int SongID { - get { return _SongPlayer.SongID; } + get { return _CurPlayer.SongID; } } public static bool SongHasVideo { - get { return _SongPlayer.SongHasVideo; } + get { return _CurPlayer.SongHasVideo; } } public static bool IsPlaying { - get { return _PlaysPreview ? _PreviewPlayer.IsPlaying : _SongPlayer.IsPlaying; } + get { return _CurPlayer.IsPlaying; } } public static bool IsPlayingPreview { - get { return _PlaysPreview; } + get { return _CurPlayer == _PreviewPlayer; } + set + { + if (IsPlayingPreview == value) + return; + Pause(); + _CurPlayer = value ? _PreviewPlayer : _BGPlayer; + Play(); + } } public static string ArtistAndTitle { - get - { - if (_PlaysPreview) - return _PreviewPlayer.ArtistAndTitle; - return _BGMusicFiles.Contains(_CurrentPlaylistElement) ? Path.GetFileNameWithoutExtension(_CurrentPlaylistElement.MusicFilePath) : _SongPlayer.ArtistAndTitle; - } + get { return _CurPlayer.ArtistAndTitle; } } public static float Length { - get { return _PlaysPreview ? _PreviewPlayer.Length : _SongPlayer.Length; } + get { return _CurPlayer.Length; } } public static CTextureRef Cover { - get { return _PlaysPreview ? _PreviewPlayer.Cover : _SongPlayer.Cover; } + get { return _CurPlayer.Cover; } } //Use this to set whether own songs are available for access @@ -160,21 +159,15 @@ namespace Vocaluxe.Base _MusicSource = EBackgroundMusicSource.TR_CONFIG_NO_OWN_MUSIC; _AddBackgroundMusic(); - _SongPlayer = new CSongPlayer(); - - _PreviewPlayer = new CSongPlayer {RepeatSong = true}; - - _VideoEnabled = (CConfig.Config.Video.VideoBackgrounds == EOffOn.TR_CONFIG_ON && CConfig.Config.Video.VideosToBackground == EOffOn.TR_CONFIG_ON); SetMusicSource(CConfig.Config.Sound.BackgroundMusicSource); + _CurPlayer = _BGPlayer; _Initialized = true; } public static void Close() { - if (_SongPlayer != null) - _SongPlayer.Stop(); - if (_PreviewPlayer != null) - _PreviewPlayer.Stop(); + _BGPlayer.Close(); + _PreviewPlayer.Close(); _BGMusicFiles.Clear(); _NotPlayedFiles.Clear(); @@ -185,124 +178,88 @@ namespace Vocaluxe.Base public static void Play() { - if (IsPlaying || (CConfig.Config.Sound.BackgroundMusic != EBackgroundMusicOffOn.TR_CONFIG_ON && !_PlaysPreview)) + if (!IsPlayingPreview && CConfig.Config.Sound.BackgroundMusic == EBackgroundMusicOffOn.TR_CONFIG_OFF) return; - if (_PlaysPreview) - _PreviewPlayer.Play(); - else if (CConfig.Config.Sound.BackgroundMusic == EBackgroundMusicOffOn.TR_CONFIG_ON) - { - if (_SongPlayer.SongLoaded) - //Resume - _SongPlayer.TogglePause(); - else - Next(); - } + if (IsPlayingPreview || _BGPlayer.SoundLoaded) + _CurPlayer.Play(); + else + Next(); } public static void Stop() { - if (!IsPlaying) - return; - - if (_PlaysPreview) - { - _PreviewPlayer.Stop(); - _PlaysPreview = false; - Pause(); - CSound.SetGlobalVolume(CConfig.BackgroundMusicVolume); - } - else - { - _SongPlayer.Stop(); + _CurPlayer.Stop(); + if (!IsPlayingPreview) _CurrentPlaylistElement = null; - } } public static void Pause() { - if (_PlaysPreview) - { - if (!_PreviewPlayer.SongLoaded) - return; - _PreviewPlayer.TogglePause(); - } - else if (CConfig.Config.Sound.BackgroundMusic == EBackgroundMusicOffOn.TR_CONFIG_ON) - { - if (!_SongPlayer.SongLoaded) - Next(); - else - _SongPlayer.TogglePause(); - } + _CurPlayer.Pause(); } public static void Next() { - if (!_PlaysPreview) + if (IsPlayingPreview) + return; + + Stop(); //stop last song if any + if (_PreviousMusicIndex < _PreviousFiles.Count - 2) { - Stop(); //stop last song if any - if (_PreviousMusicIndex < _PreviousFiles.Count - 2) - { - //We are in the previous list and next element exists - _PreviousMusicIndex++; - _CurrentPlaylistElement = _PreviousFiles[_PreviousMusicIndex]; - } - else - { - //We are not in the previous list (anymore) - if (_NotPlayedFiles.Count == 0) - { - if (_PreviousFiles.Count == 0) - return; //No songs to play - _NotPlayedFiles.AddRange(_PreviousFiles); - } - - _CurrentPlaylistElement = _NotPlayedFiles[CGame.Rand.Next(_NotPlayedFiles.Count)]; - _NotPlayedFiles.Remove(_CurrentPlaylistElement); - - _PreviousFiles.Add(_CurrentPlaylistElement); - _PreviousMusicIndex = _PreviousFiles.Count - 1; - } - _StartSong(); + //We are in the previous list and next element exists + _PreviousMusicIndex++; + _CurrentPlaylistElement = _PreviousFiles[_PreviousMusicIndex]; } + else + { + //We are not in the previous list (anymore) + if (_NotPlayedFiles.Count == 0) + { + if (_PreviousFiles.Count == 0) + return; //No songs to play + _NotPlayedFiles.AddRange(_PreviousFiles); + } + + _CurrentPlaylistElement = _NotPlayedFiles[CGame.Rand.Next(_NotPlayedFiles.Count)]; + _NotPlayedFiles.Remove(_CurrentPlaylistElement); + + _PreviousFiles.Add(_CurrentPlaylistElement); + _PreviousMusicIndex = _PreviousFiles.Count - 1; + } + _StartSong(); } public static void Previous() { - if (!_PlaysPreview) - { - if (_PreviousMusicIndex < 0) - return; - Debug.Assert(_CurrentPlaylistElement != null); - if (_SongPlayer.Position <= 1.5f && _PreviousMusicIndex > 0) - { - Stop(); //stop last song - _PreviousMusicIndex--; + if (IsPlayingPreview) + return; + if (_PreviousMusicIndex < 0) + return; - _CurrentPlaylistElement = _PreviousFiles[_PreviousMusicIndex]; - } - _StartSong(); + if (_CurrentPlaylistElement == null || (_BGPlayer.Position <= 1.5f && _PreviousMusicIndex > 0)) + { + Stop(); //stop last song + _PreviousMusicIndex--; + + _CurrentPlaylistElement = _PreviousFiles[_PreviousMusicIndex]; } + _StartSong(); } public static void Update() { - if (!IsPlaying && (!_SongPlayer.SongLoaded || !_PreviewPlayer.SongLoaded)) + if (!IsPlaying) return; - if (_PlaysPreview) - _PreviewPlayer.Update(); - else - { - _SongPlayer.Update(); - if (_SongPlayer.IsFinished) - Next(); - } + _CurPlayer.Update(); + if (!IsPlayingPreview && _BGPlayer.IsFinished) + Next(); } public static CTextureRef GetVideoTexture() { - return _PlaysPreview ? _PreviewPlayer.GetVideoTexture() : _SongPlayer.GetVideoTexture(); + return _CurPlayer.GetVideoTexture(); } public static void SetMusicSource(EBackgroundMusicSource source) @@ -328,54 +285,42 @@ namespace Vocaluxe.Base } } - public static void LoadPreview(CSong song, float start = 0f) + public static void LoadPreview(CSong song, float start = -1f) { - if (!_PlaysPreview) - Pause(); - else - StopPreview(); - if (song == null) - return; + throw new ArgumentNullException("song"); - // ReSharper disable CompareOfFloatsByEqualityOperator - if (start == 0f) - start = song.Preview.StartTime; - // ReSharper restore CompareOfFloatsByEqualityOperator + if (!IsPlayingPreview) + { + Pause(); + _CurPlayer = _PreviewPlayer; + CSound.SetGlobalVolume(CConfig.PreviewMusicVolume); + } - _PlaysPreview = true; - CSound.SetGlobalVolume(CConfig.PreviewMusicVolume); - _PreviewPlayer.Load(song, start); - - float startposition = song.Preview.StartTime; + _PreviewPlayer.Load(song); float length = _PreviewPlayer.Length; + if (length < 1) + length = 30; // If length is unknow or invalid assume a length of 30s - if (song.Preview.Source == EDataSource.None) - startposition = length / 4f; - else if (startposition > length - 5f) - startposition = Math.Max(0f, Math.Min(length / 4f, length - 5f)); + if (start < 0) + start = (song.Preview.Source == EDataSource.None) ? length / 4f : song.Preview.StartTime; + if (start > length - 5f) + start = Math.Max(0f, Math.Min(length / 4f, length - 5f)); + if (start >= 0.5f) + start -= 0.5f; - if (startposition >= 0.5f) - startposition -= 0.5f; - - _PreviewPlayer.Position = startposition; - - Play(); - } - - public static void PlayPreview(float start = -1f) - { - if (start > -1f) - _PreviewPlayer.Position = start; + _PreviewPlayer.Position = start; Play(); } public static void StopPreview() { - _PreviewPlayer.Stop(); - _PlaysPreview = false; + if (!IsPlayingPreview) + return; + Stop(); + _CurPlayer = _BGPlayer; CSound.SetGlobalVolume(CConfig.BackgroundMusicVolume); } @@ -387,19 +332,23 @@ namespace Vocaluxe.Base Debug.Assert(_CurrentPlaylistElement != null); //If current song same as loaded restart only - if (_CurrentPlaylistElement.SongID == _SongPlayer.SongID && _SongPlayer.SongLoaded) - _SongPlayer.Play(); + if (_BGPlayer.SoundLoaded && _CurrentPlaylistElement.MusicFilePath == _BGPlayer.FilePath) + { + _BGPlayer.Stop(); + _BGPlayer.Play(); + return; + } //otherwhise load - if (_BGMusicFiles.Contains(_CurrentPlaylistElement)) - _SongPlayer.LoadFile(_CurrentPlaylistElement.MusicFilePath, 0f, true); + if (!_CurrentPlaylistElement.HasMetaData) + _BGPlayer.Load(_CurrentPlaylistElement.MusicFilePath, 0f, true); else { //Seek to #Start-Tag, if found float start = 0f; if (_CurrentPlaylistElement.Start > 0.001 && CConfig.Config.Sound.BackgroundMusicUseStart == EOffOn.TR_CONFIG_ON) start = _CurrentPlaylistElement.Start; - _SongPlayer.Load(CBase.Songs.GetSongByID(_CurrentPlaylistElement.SongID), start, true); + _BGPlayer.Load(_CurrentPlaylistElement.Song, start, true); } } diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs index be0f4149..575002c3 100644 --- a/Vocaluxe/Base/CConfig.cs +++ b/Vocaluxe/Base/CConfig.cs @@ -348,8 +348,14 @@ namespace Vocaluxe.Base }; } + private static readonly List _CommentsGot = new List(); + private static string _GetComment(string elName) { + // Avoid multiple comments (e.g. for array entries) + if (_CommentsGot.Contains(elName)) + return null; + _CommentsGot.Add(elName); switch (elName) { case "DebugLevel": @@ -419,7 +425,7 @@ namespace Vocaluxe.Base case "Language": return "Game-Language"; case "SongFolder": - return "SongFolder: SongFolder1, SongFolder2, SongFolder3, ..."; + return "SongFolder: Add each song folder in a seperate SongFolder entry"; case "SongMenu": return "SongMenu: " + CHelper.ListStrings(Enum.GetNames(typeof(ESongMenu))); case "SongSorting": @@ -467,6 +473,7 @@ namespace Vocaluxe.Base public static void SaveConfig() { + _CommentsGot.Clear(); var xml = new CXmlSerializer(true, _GetComment); xml.Serialize(_FileConfig, Config); } diff --git a/Vocaluxe/Base/CGraphics.cs b/Vocaluxe/Base/CGraphics.cs index 5d4ea1c6..d5967687 100644 --- a/Vocaluxe/Base/CGraphics.cs +++ b/Vocaluxe/Base/CGraphics.cs @@ -224,16 +224,18 @@ namespace Vocaluxe.Base NextScreen.ProcessMouseMove(_Cursor.X, _Cursor.Y); HidePopup(EPopupScreens.PopupPlayerControl); + if (NextScreen.CurrentMusicType != EMusicType.Background && NextScreen.CurrentMusicType != EMusicType.Preview) + CBackgroundMusic.Disabled = true; } if (_Fading != null) { + Debug.Assert(NextScreen != null); bool finished; float newAlpha = _Fading.GetValue(out finished); if (!finished) { - GlobalAlpha = 1f; ZOffset = CSettings.ZFar / 2; _DrawScreen(CurrentScreen); @@ -242,6 +244,9 @@ namespace Vocaluxe.Base _DrawScreen(NextScreen); GlobalAlpha = 1f; + int oldVol = CConfig.GetVolumeByType(CurrentScreen.CurrentMusicType); + int newVol = CConfig.GetVolumeByType(NextScreen.CurrentMusicType); + CSound.SetGlobalVolume((int)((newVol - oldVol) * newAlpha + oldVol)); } else { @@ -274,6 +279,11 @@ namespace Vocaluxe.Base NextScreen = null; CurrentScreen.OnShowFinish(); CSound.SetGlobalVolume(CConfig.GetVolumeByType(CurrentScreen.CurrentMusicType)); + if (CurrentScreen.CurrentMusicType == EMusicType.Background || CurrentScreen.CurrentMusicType == EMusicType.Preview) + { + CBackgroundMusic.Disabled = false; + CBackgroundMusic.IsPlayingPreview = CurrentScreen.CurrentMusicType == EMusicType.Preview; + } _Fading = null; } @@ -305,8 +315,8 @@ namespace Vocaluxe.Base { if (screen == null) throw new ArgumentNullException("screen"); - Debug.Assert(NextScreen==null || NextScreen!=screen, "Don't fade to currently fading screen!"); - if(screen==NextScreen) + Debug.Assert(NextScreen == null || NextScreen != screen, "Don't fade to currently fading screen!"); + if (screen == NextScreen) return; // Make sure the last screen change is done _FinishScreenFading(); @@ -348,7 +358,7 @@ namespace Vocaluxe.Base SKeyEvent inputKeyEvent = new SKeyEvent(); SMouseEvent inputMouseEvent = new SMouseEvent(); - bool popupPlayerControlAllowed = CurrentScreen.CurrentMusicType == EMusicType.Background && !CBackgroundMusic.Disabled; + bool popupPlayerControlAllowed = CurrentScreen.CurrentMusicType == EMusicType.Background; bool popupVolumeControlAllowed = CurrentScreen.CurrentMusicType != EMusicType.None; //Hide volume control for bg-music if bg-music is disabled if (popupVolumeControlAllowed && CurrentScreen.CurrentMusicType == EMusicType.Background && CConfig.Config.Sound.BackgroundMusic == EBackgroundMusicOffOn.TR_CONFIG_OFF) diff --git a/Vocaluxe/Base/CMain.cs b/Vocaluxe/Base/CMain.cs index 320b8697..1224a1c0 100644 --- a/Vocaluxe/Base/CMain.cs +++ b/Vocaluxe/Base/CMain.cs @@ -355,21 +355,21 @@ namespace Vocaluxe.Base CBackgroundMusic.Stop(); } - public void LoadPreview(CSong song, float start = 0f) + public void LoadPreview(CSong song, float start = -1f) { CBackgroundMusic.LoadPreview(song, start); } - public void PlayPreview(float start = -1f) - { - CBackgroundMusic.PlayPreview(start); - } - public void StopPreview() { CBackgroundMusic.StopPreview(); } + public void SetPlayingPreview(bool playPreview) + { + CBackgroundMusic.IsPlayingPreview = playPreview; + } + public CTextureRef GetVideoTexture() { return CBackgroundMusic.GetVideoTexture(); @@ -877,6 +877,11 @@ namespace Vocaluxe.Base { CSound.SetGlobalVolume(volume); } + + public bool IsPaused(int streamID) + { + return CSound.IsPaused(streamID); + } } class CBcover : ICover diff --git a/Vocaluxe/Base/CPlaylistElement.cs b/Vocaluxe/Base/CPlaylistElement.cs index eec209c1..4e82592a 100644 --- a/Vocaluxe/Base/CPlaylistElement.cs +++ b/Vocaluxe/Base/CPlaylistElement.cs @@ -23,61 +23,70 @@ namespace Vocaluxe.Base { class CPlaylistElement { - private readonly CSong _Song; + public readonly CSong Song; private readonly string _MusicFilePath = String.Empty; + public bool HasMetaData + { + get { return Song != null; } + } + public int SongID { - get { return (_Song == null) ? -1 : _Song.ID; } + get { return HasMetaData ? Song.ID : -1; } } public string MusicFilePath { - get { return _Song != null ? _Song.GetMP3() : _MusicFilePath; } + get { return HasMetaData ? Song.GetMP3() : _MusicFilePath; } } public string VideoFilePath { - get { return _Song != null ? _Song.GetVideo() : string.Empty; } + get { return HasMetaData ? Song.GetVideo() : string.Empty; } } public string Title { - get { return _Song != null ? _Song.Title : ""; } + get { return HasMetaData ? Song.Title : ""; } } public string Artist { - get { return _Song != null ? _Song.Artist : ""; } + get { return HasMetaData ? Song.Artist : ""; } } public float Start { - get { return _Song != null ? _Song.Start : 0f; } + get { return HasMetaData ? Song.Start : 0f; } } public float Finish { - get { return _Song != null ? _Song.Finish : 0f; } + get { return HasMetaData ? Song.Finish : 0f; } } public CTextureRef Cover { - get { return _Song != null ? _Song.CoverTextureSmall : CCover.NoCover; } + get { return HasMetaData ? Song.CoverTextureSmall : CCover.NoCover; } } public float VideoGap { - get { return _Song != null ? _Song.VideoGap : 0; } + get { return HasMetaData ? Song.VideoGap : 0; } } public CPlaylistElement(CSong song) { - _Song = song; + if (song == null) + throw new ArgumentNullException("song"); + Song = song; } public CPlaylistElement(string filePath) { + if (String.IsNullOrEmpty(filePath)) + throw new ArgumentNullException("filePath"); _MusicFilePath = filePath; } } diff --git a/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudioStream.cs b/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudioStream.cs index c66ba54b..7a6fc6a4 100644 --- a/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudioStream.cs +++ b/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudioStream.cs @@ -175,7 +175,7 @@ namespace Vocaluxe.Lib.Sound.Playback.GstreamerSharp // Passing CLOCK_TIME_NONE here causes the pipeline to block for a long time so with // prescan enabled the pipeline will wait 500ms for stream to initialize and then continue // if it takes more than 500ms, duration queries will be performed asynchronously - Message msg = _Element.Bus.TimedPopFiltered(prescan ? ulong.MaxValue : 0L, MessageType.AsyncDone | MessageType.Error | MessageType.DurationChanged); + Message msg = _Element.Bus.TimedPopFiltered(prescan ? ulong.MaxValue : 0L, MessageType.AsyncDone | MessageType.Error); if (!_OnMessage(msg)) { _Dispose(true); diff --git a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPt1.cs b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPt1.cs index ea854457..a4a7d561 100644 --- a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPt1.cs +++ b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPt1.cs @@ -49,8 +49,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio _CurrentTime = value; _OldTime = value; - _Timer.Reset(); - _Timer.Start(); + _Timer.Restart(); } } diff --git a/Vocaluxe/Lib/Sound/Playback/PortAudio/CSyncTimer.cs b/Vocaluxe/Lib/Sound/Playback/PortAudio/CSyncTimer.cs index 887c37cf..7a924663 100644 --- a/Vocaluxe/Lib/Sound/Playback/PortAudio/CSyncTimer.cs +++ b/Vocaluxe/Lib/Sound/Playback/PortAudio/CSyncTimer.cs @@ -44,8 +44,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio { _ExternTime.Time = value; _SetValue = value; - _Timer.Reset(); - _Timer.Start(); + _Timer.Restart(); } } diff --git a/Vocaluxe/Lib/Video/IVideoDecoder.cs b/Vocaluxe/Lib/Video/IVideoDecoder.cs index 205b157c..c4484f9e 100644 --- a/Vocaluxe/Lib/Video/IVideoDecoder.cs +++ b/Vocaluxe/Lib/Video/IVideoDecoder.cs @@ -36,7 +36,7 @@ namespace Vocaluxe.Lib.Video /// Loads the file with the given file path. /// /// Absolute file path of the video file - /// stream >=0 on success or -1 on failure + /// Loaded video stream or null on failure CVideoStream Load(string videoFileName); /// diff --git a/Vocaluxe/Screens/CPopupScreenPlayerControl.cs b/Vocaluxe/Screens/CPopupScreenPlayerControl.cs index 0ed15bc7..0ce70b67 100644 --- a/Vocaluxe/Screens/CPopupScreenPlayerControl.cs +++ b/Vocaluxe/Screens/CPopupScreenPlayerControl.cs @@ -112,7 +112,7 @@ namespace Vocaluxe.Screens if (_Buttons[_ButtonPrevious].Selected) CBackgroundMusic.Previous(); if (_Buttons[_ButtonPlay].Selected) - CBackgroundMusic.Pause(); + CBackgroundMusic.Play(); if (_Buttons[_ButtonPause].Selected) CBackgroundMusic.Pause(); if (_Buttons[_ButtonRepeat].Selected) @@ -140,7 +140,7 @@ namespace Vocaluxe.Screens if (_Buttons[_ButtonPrevious].Selected) CBackgroundMusic.Previous(); if (_Buttons[_ButtonPlay].Selected) - CBackgroundMusic.Pause(); + CBackgroundMusic.Play(); if (_Buttons[_ButtonPause].Selected) CBackgroundMusic.Pause(); if (_Buttons[_ButtonRepeat].Selected) diff --git a/Vocaluxe/Screens/CScreenNames.cs b/Vocaluxe/Screens/CScreenNames.cs index bd04a3ab..f6d59be9 100644 --- a/Vocaluxe/Screens/CScreenNames.cs +++ b/Vocaluxe/Screens/CScreenNames.cs @@ -65,6 +65,11 @@ namespace Vocaluxe.Screens private bool _AvatarsChanged; private bool _ProfilesChanged; + public override EMusicType CurrentMusicType + { + get { return EMusicType.Preview; } + } + #region public methods public override void Init() { diff --git a/Vocaluxe/Screens/CScreenOptionsRecord.cs b/Vocaluxe/Screens/CScreenOptionsRecord.cs index df51de82..dca9586b 100644 --- a/Vocaluxe/Screens/CScreenOptionsRecord.cs +++ b/Vocaluxe/Screens/CScreenOptionsRecord.cs @@ -303,7 +303,6 @@ namespace Vocaluxe.Screens public override void OnShowFinish() { base.OnShowFinish(); - CBackgroundMusic.Disabled = true; } public override void Draw() @@ -332,7 +331,6 @@ namespace Vocaluxe.Screens CRecord.Stop(); _DelayTest.Reset(); - CBackgroundMusic.Disabled = false; } private void _OnDeviceEvent() diff --git a/Vocaluxe/Screens/CScreenScore.cs b/Vocaluxe/Screens/CScreenScore.cs index adce6bf6..ffb5cc86 100644 --- a/Vocaluxe/Screens/CScreenScore.cs +++ b/Vocaluxe/Screens/CScreenScore.cs @@ -124,8 +124,6 @@ namespace Vocaluxe.Screens public override void OnShow() { - CBackgroundMusic.Disabled = false; - base.OnShow(); //-1 --> Show average _Round = CGame.NumRounds > 1 ? -1 : 0; diff --git a/Vocaluxe/Screens/CScreenSing.cs b/Vocaluxe/Screens/CScreenSing.cs index 24584cd1..febdde72 100644 --- a/Vocaluxe/Screens/CScreenSing.cs +++ b/Vocaluxe/Screens/CScreenSing.cs @@ -96,8 +96,7 @@ namespace Vocaluxe.Screens private int _CurrentBeat; private int _CurrentStream = -1; private float _Length = -1f; - //private int _NextStream = -1; - private const int _Volume = 100; + private CVideoStream _CurrentVideo; private EAspect _VideoAspect = EAspect.Crop; private CTextureRef _CurrentWebcamFrameTexture; @@ -414,7 +413,6 @@ namespace Vocaluxe.Screens public override void OnShowFinish() { base.OnShowFinish(); - CBackgroundMusic.Disabled = true; CGame.Start(); _LoadNextSong(); @@ -528,7 +526,7 @@ namespace Vocaluxe.Screens _Texts[_TextSongName].Text = songname; _CurrentStream = CSound.Load(song.GetMP3(), false, true); - CSound.SetStreamVolume(_CurrentStream, _Volume); + CSound.SetStreamVolume(_CurrentStream, 100); CSound.SetPosition(_CurrentStream, song.Start); _CurrentTime = song.Start; _FinishTime = song.Finish; diff --git a/VocaluxeLib/IBasic.cs b/VocaluxeLib/IBasic.cs index 5262668b..6c18ddde 100644 --- a/VocaluxeLib/IBasic.cs +++ b/VocaluxeLib/IBasic.cs @@ -121,9 +121,9 @@ namespace VocaluxeLib CTextureRef GetVideoTexture(); - void LoadPreview(CSong song, float start = 0f); - void PlayPreview(float start = -1f); + void LoadPreview(CSong song, float start = -1f); void StopPreview(); + void SetPlayingPreview(bool playPreview); } public interface IDrawing @@ -266,17 +266,18 @@ namespace VocaluxeLib public interface ISound { int Load(string soundFile, bool loop = false, bool prescan = false); - void SetPosition(int soundStream, float newPosition); - void Play(int soundStream); - void Fade(int soundStream, int targetVolume, float duration, EStreamAction afterFadeAction = EStreamAction.Nothing); - void Close(int soundStream); + void SetPosition(int streamID, float newPosition); + void Play(int streamID); + void Fade(int streamID, int targetVolume, float duration, EStreamAction afterFadeAction = EStreamAction.Nothing); + void Close(int streamID); - bool IsFinished(int soundStream); - float GetPosition(int soundStream); - float GetLength(int soundStream); + bool IsFinished(int streamID); + float GetPosition(int streamID); + float GetLength(int streamID); - void SetStreamVolume(int soundStream, int volume); + void SetStreamVolume(int streamID, int volume); void SetGlobalVolume(int volume); + bool IsPaused(int streamID); } public interface ICover diff --git a/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs b/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs index d3668346..c0bfb6f3 100644 --- a/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs +++ b/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs @@ -121,7 +121,7 @@ namespace VocaluxeLib.Menu.SongMenu else if (value >= CBase.Songs.GetNumCategories()) { value = -1; - CBase.BackgroundMusic.Stop(); + CBase.BackgroundMusic.SetPlayingPreview(false); } _PreviewNrInternal = value; @@ -371,7 +371,7 @@ namespace VocaluxeLib.Menu.SongMenu return; CBase.BackgroundMusic.StopPreview(); - + CBase.Sound.SetGlobalVolume(CBase.Config.GetMusicVolume(EMusicType.Background)); if (playBGagain) CBase.BackgroundMusic.Play(); diff --git a/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs b/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs index 99469947..f74e81f9 100644 --- a/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs +++ b/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs @@ -99,7 +99,7 @@ namespace VocaluxeLib.Menu.SongMenu if (value == base._PreviewNr) { if (!CBase.BackgroundMusic.IsPlaying() && value != -1) - CBase.BackgroundMusic.PlayPreview(); + CBase.BackgroundMusic.Play(); return; } base._PreviewNr = value; diff --git a/VocaluxeLib/Utils/Player/CSongPlayer.cs b/VocaluxeLib/Utils/Player/CSongPlayer.cs index 0b22f47b..ea61b271 100644 --- a/VocaluxeLib/Utils/Player/CSongPlayer.cs +++ b/VocaluxeLib/Utils/Player/CSongPlayer.cs @@ -39,28 +39,32 @@ namespace VocaluxeLib.Utils.Player _VideoEnabled = value; if (_VideoEnabled) _LoadVideo(); - else if (_Video != null) - CBase.Video.Close(ref _Video); + else + _CloseVideo(); } } + public int SongID { get { return _Song == null ? -1 : _Song.ID; } } - public bool SongHasVideo - { - get { return _Song != null && File.Exists(Path.Combine(_Song.Folder, _Song.VideoFileName)); } - } - public string ArtistAndTitle + public bool SongHasVideo { get { - if (_Song == null) - return ""; - if (_Song.Artist != "" && _Song.Title != "") + return _Song != null && !String.IsNullOrEmpty(_Song.Folder) && !String.IsNullOrEmpty(_Song.VideoFileName) && + File.Exists(Path.Combine(_Song.Folder, _Song.VideoFileName)); + } + } + + public override string ArtistAndTitle + { + get + { + if (_Song != null && !String.IsNullOrEmpty(_Song.Artist) && !String.IsNullOrEmpty(_Song.Title)) return _Song.Artist + " - " + _Song.Title; - return Path.GetFileNameWithoutExtension(_Song.MP3FileName); + return base.ArtistAndTitle; } } @@ -69,26 +73,8 @@ namespace VocaluxeLib.Utils.Player get { return _Song == null ? CBase.Cover.GetNoCover() : _Song.CoverTextureBig; } } - public bool SongLoaded - { - get { return _StreamID != -1; } - } - public CSongPlayer(bool loop = false) : base(loop) {} - public CSongPlayer(CSong song, bool loop = false, float position = 0f, bool autoplay = false) - : base(Path.Combine(song.Folder, song.MP3FileName), loop, position, autoplay) - { - _Song = song; - _LoadVideo(); - } - - public CSongPlayer(string file, bool loop = false, float position = 0f, bool autoplay = false) - : base(file, loop, position, autoplay) - { - _Song = null; - } - public CTextureRef GetVideoTexture() { if (_Video == null || _Song == null) @@ -110,49 +96,11 @@ namespace VocaluxeLib.Utils.Player public void Load(CSong song, float position = 0f, bool autoplay = false) { if (song == null) - return; + throw new ArgumentNullException("song"); - Stop(); - - _Song = song; - - Load(Path.Combine(song.Folder, song.MP3FileName), position, autoplay); + Load(song.GetMP3(), position, autoplay); _LoadVideo(); - - if (autoplay) - Play(); - } - - public void LoadFile(string file, float position = 0f, bool autoplay = false) - { - if (String.IsNullOrEmpty(file)) - return; - - Stop(); - - Load(file, position, autoplay); - } - - public override void Stop() - { - base.Stop(); - - _Song = null; - - if (_Video != null) - CBase.Video.Close(ref _Video); - } - - public override void TogglePause() - { - if (IsPlaying && _Video != null) - { - CBase.Video.Pause(_Video); - CBase.Video.Skip(_Video, CBase.Sound.GetPosition(_StreamID) + _FadeTime, _Song.VideoGap); - } - else if (_Video != null) - CBase.Video.Resume(_Video); - base.TogglePause(); + _Song = song; } private void _LoadVideo() @@ -160,11 +108,13 @@ namespace VocaluxeLib.Utils.Player if (_Song == null) return; - string videoFilePath = Path.Combine(_Song.Folder, _Song.VideoFileName); - if (_Video != null || String.IsNullOrEmpty(videoFilePath)) + if (_Video != null || !SongHasVideo) return; + string videoFilePath = Path.Combine(_Song.Folder, _Song.VideoFileName); _Video = CBase.Video.Load(videoFilePath); - CBase.Video.Skip(_Video, 0f, _Song.VideoGap); //Use gap, otherwhise we will overwrite position in GetVideoTexture + if (_Video == null) + return; + _VideoFading = new CFading(0f, 1f, 3f); if (IsPlaying) @@ -172,6 +122,57 @@ namespace VocaluxeLib.Utils.Player CBase.Video.Skip(_Video, Position, _Song.VideoGap); CBase.Video.Resume(_Video); } + else + CBase.Video.Skip(_Video, 0f, _Song.VideoGap); + } + + public override bool Play() + { + if (!base.Play()) + return false; + + if (_Video != null) + { + CBase.Video.Skip(_Video, Position, _Song.VideoGap); + CBase.Video.Resume(_Video); + } + return true; + } + + public override bool Pause() + { + if (!base.Pause()) + return false; + + if (_Video != null) + CBase.Video.Pause(_Video); + return true; + } + + public override bool Stop() + { + if (!base.Stop()) + return false; + if (_Video != null) + { + CBase.Video.Pause(_Video); + CBase.Video.Skip(_Video, 0f, _Song.VideoGap); + } + return true; + } + + private void _CloseVideo() + { + if (_Video != null) + CBase.Video.Close(ref _Video); + } + + public override void Close() + { + base.Close(); + + _Song = null; + _CloseVideo(); } } } \ No newline at end of file diff --git a/VocaluxeLib/Utils/Player/CSoundPlayer.cs b/VocaluxeLib/Utils/Player/CSoundPlayer.cs index b132643b..51337d42 100644 --- a/VocaluxeLib/Utils/Player/CSoundPlayer.cs +++ b/VocaluxeLib/Utils/Player/CSoundPlayer.cs @@ -15,58 +15,52 @@ // along with Vocaluxe. If not, see . #endregion +using System.IO; + namespace VocaluxeLib.Utils.Player { public class CSoundPlayer { protected int _StreamID = -1; - protected int _Volume = 100; - protected float _StartPosition; protected readonly float _FadeTime = CBase.Settings.GetSoundPlayerFadeTime(); + public string FilePath { get; private set; } - public int Volume - { - set - { - _Volume = value; - _ApplyVolume(); - } - get { return _Volume; } - } public bool Loop; + /// + /// Gets the current stream position or sets it + /// public float Position { set { - if (_StreamID == -1) + if (!SoundLoaded) return; - _StartPosition = value; - } - get - { - if (_StreamID == -1) - return -1; - return CBase.Sound.GetPosition(_StreamID); + CBase.Sound.SetPosition(_StreamID, value); } + get { return !SoundLoaded ? -1 : CBase.Sound.GetPosition(_StreamID); } } public float Length { - get - { - if (_StreamID == -1) - return 0; - return CBase.Sound.GetLength(_StreamID); - } + get { return !SoundLoaded ? -1 : CBase.Sound.GetLength(_StreamID); } } - public bool RepeatSong; - public bool IsPlaying { get; protected set; } + public bool IsPlaying { get; private set; } public bool IsFinished { - get { return !RepeatSong && CBase.Sound.IsFinished(_StreamID); } + get { return !Loop && CBase.Sound.IsFinished(_StreamID); } + } + + public bool SoundLoaded + { + get { return _StreamID != -1; } + } + + public virtual string ArtistAndTitle + { + get { return string.IsNullOrEmpty(FilePath) ? "" : Path.GetFileNameWithoutExtension(FilePath); } } public CSoundPlayer(bool loop = false) @@ -74,95 +68,97 @@ namespace VocaluxeLib.Utils.Player Loop = loop; } - public CSoundPlayer(string file, bool loop = false, float position = 0f, bool autoplay = false) + public void Load(string file, float position = -1f, bool autoplay = false) { - _StreamID = CBase.Sound.Load(file, false, true); - if (position > 0f) - Position = position; - Loop = loop; - if (autoplay) - Play(); - } - - public void Load(string file, float position = 0f, bool autoplay = false) - { - if (IsPlaying) - Stop(); + Close(); _StreamID = CBase.Sound.Load(file, false, true); - if (position > 0f) - Position = position; - if (autoplay) - Play(); - } - - public void Play() - { - if (_StreamID == -1 || IsPlaying) + if (_StreamID < 0) return; + FilePath = file; + if (position > 0f) + Position = position; + if (autoplay) + Play(); + } + + /// + /// Starts or resumes the player + /// + /// True if state changed, false if nothing loaded or already playing + public virtual bool Play() + { + if (!SoundLoaded || IsPlaying) + return false; - CBase.Sound.SetPosition(_StreamID, _StartPosition); CBase.Sound.SetStreamVolume(_StreamID, 0); - CBase.Sound.Fade(_StreamID, Volume, _FadeTime); + CBase.Sound.Fade(_StreamID, 100, _FadeTime); CBase.Sound.Play(_StreamID); IsPlaying = true; + return true; } - public virtual void TogglePause() + /// + /// Pauses the player + /// + /// True if state changed, false if nothing loaded or already paused + public virtual bool Pause() { - if (_StreamID == -1) - return; + if (!SoundLoaded || CBase.Sound.IsPaused(_StreamID)) + return false; - if (IsPlaying) - CBase.Sound.Fade(_StreamID, 0, _FadeTime, EStreamAction.Pause); - else - { - CBase.Sound.Fade(_StreamID, Volume, _FadeTime); - CBase.Sound.Play(_StreamID); - } - - IsPlaying = !IsPlaying; + CBase.Sound.Fade(_StreamID, 0, _FadeTime, EStreamAction.Pause); + IsPlaying = false; + return true; } - public virtual void Stop() + /// + /// Stops the player (no playback and position is set to start) + /// + /// True if playback was stopped + public virtual bool Stop() { - if (_StreamID == -1 || !IsPlaying) + if (!SoundLoaded) + return false; + + CBase.Sound.Fade(_StreamID, 0, _FadeTime, EStreamAction.Stop); + IsPlaying = false; + return true; + } + + public virtual void Close() + { + if (!SoundLoaded) return; CBase.Sound.Fade(_StreamID, 0, _FadeTime, EStreamAction.Close); _StreamID = -1; - + FilePath = ""; IsPlaying = false; } public void Update() { - if (_StreamID == -1 || !IsPlaying) + if (!IsPlaying) return; + bool finished = CBase.Sound.IsFinished(_StreamID); + if (Loop) + { + if (finished) + { + // Restart + Stop(); + Play(); + } + return; + } + float len = CBase.Sound.GetLength(_StreamID); float timeToPlay = (len > 0f) ? len - CBase.Sound.GetPosition(_StreamID) : _FadeTime + 1f; - bool finished = CBase.Sound.IsFinished(_StreamID); if (timeToPlay <= _FadeTime || finished) - { - if (RepeatSong) - { - //Set to false for restarting - IsPlaying = false; - Play(); - } - else - Stop(); - } - } - - private void _ApplyVolume() - { - if (_StreamID == -1) - return; - - CBase.Sound.SetStreamVolume(_StreamID, Volume); + Stop(); } } } \ No newline at end of file diff --git a/VocaluxeLib/Xml/CXmlSerializer.cs b/VocaluxeLib/Xml/CXmlSerializer.cs index c0db420d..46b44539 100644 --- a/VocaluxeLib/Xml/CXmlSerializer.cs +++ b/VocaluxeLib/Xml/CXmlSerializer.cs @@ -63,7 +63,7 @@ namespace VocaluxeLib.Xml /// Type of the value /// Object to write /// When true, value will be written as an attribute to the currently open node, otherwhise it will create a new node - /// >Name of the sub nodes for array types(Array,List,Dictionary), can be set by XmlArrayItemAttribute and defaults to the type name + /// Name of the sub nodes for array types(Array,List,Dictionary), can be set by XmlArrayItemAttribute and defaults to the type name /// If set, an attribute 'name' with this value will be written private void _WriteValue(XmlWriter writer, string name, Type type, object value, bool isAttribute, string arrayItemName = null, string nameAttribute = null) { @@ -165,8 +165,14 @@ namespace VocaluxeLib.Xml if (field.IsEmbeddedList) { IEnumerable values = (IEnumerable)value; + bool empty = true; foreach (object subValue in values) + { _WriteValue(writer, field.Name, field.SubType, subValue, field.IsAttribute); + empty = false; + } + if (empty && _WriteDefaults) + writer.WriteElementString(field.Name, ""); } else if (field.IsByteArray) writer.WriteElementString(field.Name, Convert.ToBase64String((byte[])value)); diff --git a/VocaluxeTests/XmlSerializerTest.cs b/VocaluxeTests/XmlSerializerTest.cs index 56e45410..91605a7e 100644 --- a/VocaluxeTests/XmlSerializerTest.cs +++ b/VocaluxeTests/XmlSerializerTest.cs @@ -301,6 +301,11 @@ namespace VocaluxeTests 2 3 "; + private const string _XmlListEmb4 = _Head + @" + 2 + + 3 +"; [TestMethod] public void TestListEmbedded() @@ -321,6 +326,10 @@ namespace VocaluxeTests Assert.AreEqual(foo.Ints.Count, 0, "Deserialization failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlListEmb3, res, "Serialization failed"); + ser = new CXmlSerializer(true); + foo.Ints.Clear(); + res = ser.Serialize(foo); + Assert.AreEqual(_XmlListEmb4, res, "Serialization failed"); _AssertFail(_Empty); } @@ -343,6 +352,10 @@ namespace VocaluxeTests Assert.AreEqual(foo.Ints.Length, 0, "Deserialization failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlListEmb3, res, "Serialization failed"); + ser = new CXmlSerializer(true); + foo.Ints = new SEntry[0]; + res = ser.Serialize(foo); + Assert.AreEqual(_XmlListEmb4, res, "Serialization failed"); _AssertFail(_Empty); }