Fix possible crashes and glitches when playing song previews (#898)
* Add AutoplayPending * Add locks * Add Base Update * Add Base Update * Add locks
This commit is contained in:
1 parent
52bdf3950e
commit
e7fc959def
4 files changed
+184
-102
No files matched your search
@@ -177,6 +177,7 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
|
|
||||||
protected int _AutoplayDelayinMs = CBase.Config.GetAutoplayPreviewDelay();
|
protected int _AutoplayDelayinMs = CBase.Config.GetAutoplayPreviewDelay();
|
||||||
protected System.Timers.Timer _AutoplayTimer = new System.Timers.Timer();
|
protected System.Timers.Timer _AutoplayTimer = new System.Timers.Timer();
|
||||||
|
protected volatile bool _AutoplayPending = false;
|
||||||
|
|
||||||
private SColorF _ColorInternal;
|
private SColorF _ColorInternal;
|
||||||
protected SColorF _Color
|
protected SColorF _Color
|
||||||
@@ -228,12 +229,22 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
_Initialized = true;
|
_Initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void Update(SScreenSongOptions songOptions);
|
public virtual void Update(SScreenSongOptions songOptions)
|
||||||
|
{
|
||||||
|
if (_AutoplayPending)
|
||||||
|
{
|
||||||
|
_AutoplayPending = false;
|
||||||
|
_PreviewSelectedSong();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void OnShow();
|
public abstract void OnShow();
|
||||||
|
|
||||||
public virtual void OnHide()
|
public virtual void OnHide()
|
||||||
{
|
{
|
||||||
|
_AutoplayTimer.Stop();
|
||||||
|
_AutoplayPending = false;
|
||||||
|
|
||||||
var check = CBase.Graphics.GetNextScreenType();
|
var check = CBase.Graphics.GetNextScreenType();
|
||||||
if (CBase.Graphics.GetNextScreenType() == EScreen.Sing)
|
if (CBase.Graphics.GetNextScreenType() == EScreen.Sing)
|
||||||
{
|
{
|
||||||
@@ -384,6 +395,9 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
|
|
||||||
protected virtual void _EnterCategory(int categoryNr)
|
protected virtual void _EnterCategory(int categoryNr)
|
||||||
{
|
{
|
||||||
|
_AutoplayTimer.Stop();
|
||||||
|
_AutoplayPending = false;
|
||||||
|
|
||||||
if (!_Initialized)
|
if (!_Initialized)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -400,6 +414,9 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
|
|
||||||
protected virtual void _LeaveCategory()
|
protected virtual void _LeaveCategory()
|
||||||
{
|
{
|
||||||
|
_AutoplayTimer.Stop();
|
||||||
|
_AutoplayPending = false;
|
||||||
|
|
||||||
if (!_Initialized)
|
if (!_Initialized)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -429,6 +446,9 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
|
|
||||||
protected void _ResetPreview(bool playBGagain = true)
|
protected void _ResetPreview(bool playBGagain = true)
|
||||||
{
|
{
|
||||||
|
_AutoplayTimer.Stop();
|
||||||
|
_AutoplayPending = false;
|
||||||
|
|
||||||
if (_PreviewNrInternal == -1)
|
if (_PreviewNrInternal == -1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -454,11 +474,19 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
|
|
||||||
protected void _InitializeAutoplayTimer()
|
protected void _InitializeAutoplayTimer()
|
||||||
{
|
{
|
||||||
|
_AutoplayTimer.Stop();
|
||||||
|
_AutoplayPending = false;
|
||||||
_AutoplayTimer.Interval = _AutoplayDelayinMs;
|
_AutoplayTimer.Interval = _AutoplayDelayinMs;
|
||||||
_AutoplayTimer.AutoReset = false;
|
_AutoplayTimer.AutoReset = false;
|
||||||
_AutoplayTimer.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => { _PreviewSelectedSong(); };
|
_AutoplayTimer.Elapsed -= _OnAutoplayTimerElapsed;
|
||||||
|
_AutoplayTimer.Elapsed += _OnAutoplayTimerElapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void _OnAutoplayTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
_AutoplayPending = true;
|
||||||
|
}
|
||||||
|
|
||||||
protected void _AutoplayPreviewIfEnabled()
|
protected void _AutoplayPreviewIfEnabled()
|
||||||
{
|
{
|
||||||
if (CBase.Config.GetAutoplayPreviews() == EOffOn.TR_CONFIG_ON)
|
if (CBase.Config.GetAutoplayPreviews() == EOffOn.TR_CONFIG_ON)
|
||||||
@@ -469,15 +497,9 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
|
|
||||||
protected void _PlayPreviewAfterDelay()
|
protected void _PlayPreviewAfterDelay()
|
||||||
{
|
{
|
||||||
if (!_AutoplayTimer.Enabled)
|
_AutoplayPending = false;
|
||||||
{
|
_AutoplayTimer.Stop();
|
||||||
_AutoplayTimer.Start();
|
_AutoplayTimer.Start();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_AutoplayTimer.Stop();
|
|
||||||
_AutoplayTimer.Start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region ThemeEdit
|
#region ThemeEdit
|
||||||
@@ -506,4 +528,4 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
}
|
}
|
||||||
#endregion ThemeEdit
|
#endregion ThemeEdit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,6 +246,8 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
|
|
||||||
public override void Update(SScreenSongOptions songOptions)
|
public override void Update(SScreenSongOptions songOptions)
|
||||||
{
|
{
|
||||||
|
base.Update(songOptions);
|
||||||
|
|
||||||
if (songOptions.Selection.RandomOnly)
|
if (songOptions.Selection.RandomOnly)
|
||||||
{
|
{
|
||||||
_PreviewSelectedSong();
|
_PreviewSelectedSong();
|
||||||
@@ -888,4 +890,4 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
base.LoadSkin();
|
base.LoadSkin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,6 +220,8 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
|
|
||||||
public override void Update(SScreenSongOptions songOptions)
|
public override void Update(SScreenSongOptions songOptions)
|
||||||
{
|
{
|
||||||
|
base.Update(songOptions);
|
||||||
|
|
||||||
if (songOptions.Selection.RandomOnly)
|
if (songOptions.Selection.RandomOnly)
|
||||||
{
|
{
|
||||||
_PreviewSelectedSong();
|
_PreviewSelectedSong();
|
||||||
@@ -783,4 +785,4 @@ namespace VocaluxeLib.Menu.SongMenu
|
|||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#region license
|
#region license
|
||||||
// This file is part of Vocaluxe.
|
// This file is part of Vocaluxe.
|
||||||
//
|
//
|
||||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||||
@@ -24,6 +24,7 @@ namespace VocaluxeLib.Utils.Player
|
|||||||
{
|
{
|
||||||
public class CSongPlayer : CSoundPlayer
|
public class CSongPlayer : CSoundPlayer
|
||||||
{
|
{
|
||||||
|
private readonly object _lock = new object();
|
||||||
private CSong _Song;
|
private CSong _Song;
|
||||||
private bool _VideoEnabled;
|
private bool _VideoEnabled;
|
||||||
private CVideoStream _Video;
|
private CVideoStream _Video;
|
||||||
@@ -31,37 +32,51 @@ namespace VocaluxeLib.Utils.Player
|
|||||||
|
|
||||||
public bool VideoEnabled
|
public bool VideoEnabled
|
||||||
{
|
{
|
||||||
get { return _VideoEnabled; }
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _VideoEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (_VideoEnabled == value)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
return;
|
if (_VideoEnabled == value)
|
||||||
}
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_VideoEnabled = value;
|
_VideoEnabled = value;
|
||||||
if (_VideoEnabled)
|
if (_VideoEnabled)
|
||||||
{
|
{
|
||||||
_LoadVideo();
|
_LoadVideo();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_CloseVideo();
|
_CloseVideo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int SongId
|
public int SongId
|
||||||
{
|
{
|
||||||
get { return _Song == null ? -1 : _Song.Id; }
|
get
|
||||||
|
{
|
||||||
|
var song = _Song;
|
||||||
|
return song == null ? -1 : song.Id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SongHasVideo
|
public bool SongHasVideo
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _Song != null && !string.IsNullOrEmpty(_Song.Folder) && !string.IsNullOrEmpty(_Song.Video) &&
|
var song = _Song;
|
||||||
File.Exists(Path.Combine(_Song.Folder, _Song.Video));
|
return song != null && !string.IsNullOrEmpty(song.Folder) && !string.IsNullOrEmpty(song.Video) &&
|
||||||
|
File.Exists(Path.Combine(song.Folder, song.Video));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +84,10 @@ namespace VocaluxeLib.Utils.Player
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_Song != null && !string.IsNullOrEmpty(_Song.Artist) && !string.IsNullOrEmpty(_Song.Title))
|
var song = _Song;
|
||||||
|
if (song != null && !string.IsNullOrEmpty(song.Artist) && !string.IsNullOrEmpty(song.Title))
|
||||||
{
|
{
|
||||||
return _Song.Artist + " - " + _Song.Title;
|
return song.Artist + " - " + song.Title;
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ArtistAndTitle;
|
return base.ArtistAndTitle;
|
||||||
@@ -80,34 +96,42 @@ namespace VocaluxeLib.Utils.Player
|
|||||||
|
|
||||||
public CTextureRef Cover
|
public CTextureRef Cover
|
||||||
{
|
{
|
||||||
get { return _Song == null ? CBase.Cover.GetNoCover() : _Song.CoverTextureBig; }
|
get
|
||||||
|
{
|
||||||
|
var song = _Song;
|
||||||
|
return song == null ? CBase.Cover.GetNoCover() : song.CoverTextureBig;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CSongPlayer(bool loop = false) : base(loop) { }
|
public CSongPlayer(bool loop = false) : base(loop) { }
|
||||||
|
|
||||||
public CTextureRef GetVideoTexture()
|
public CTextureRef GetVideoTexture()
|
||||||
{
|
{
|
||||||
if (_Video == null || _Song == null)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
return null;
|
var video = _Video;
|
||||||
}
|
var song = _Song;
|
||||||
|
if (video == null || video.IsClosed() || song == null || CBase.Video == null || CBase.Sound == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (CBase.Video.GetFrame(_Video, CBase.Sound.GetPosition(_StreamId)))
|
if (CBase.Video.GetFrame(video, CBase.Sound.GetPosition(_StreamId)))
|
||||||
{
|
|
||||||
if (_VideoFading != null)
|
|
||||||
{
|
{
|
||||||
bool finished;
|
var texture = video.Texture;
|
||||||
_Video.Texture.Color.A = _VideoFading.GetValue(out finished);
|
if (texture != null)
|
||||||
if (finished)
|
|
||||||
{
|
{
|
||||||
_VideoFading = null;
|
if (_VideoFading != null)
|
||||||
|
{
|
||||||
|
bool finished;
|
||||||
|
texture.Color.A = _VideoFading.GetValue(out finished);
|
||||||
|
if (finished)
|
||||||
|
_VideoFading = null;
|
||||||
|
}
|
||||||
|
return texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _Video.Texture;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Load(CSong song, float position = 0f, bool autoplay = false)
|
public void Load(CSong song, float position = 0f, bool autoplay = false)
|
||||||
@@ -117,104 +141,136 @@ namespace VocaluxeLib.Utils.Player
|
|||||||
throw new ArgumentNullException("song");
|
throw new ArgumentNullException("song");
|
||||||
}
|
}
|
||||||
|
|
||||||
Load(song.GetMP3(), position, autoplay);
|
lock (_lock)
|
||||||
_Song = song;
|
{
|
||||||
_LoadVideo();
|
Load(song.GetMP3(), position, autoplay);
|
||||||
|
_Song = song;
|
||||||
|
_LoadVideo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _LoadVideo()
|
private void _LoadVideo()
|
||||||
{
|
{
|
||||||
if (_Song == null)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
return;
|
var song = _Song;
|
||||||
}
|
if (song == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_Video != null || !SongHasVideo)
|
if (_Video != null || !SongHasVideo)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoFilePath = Path.Combine(_Song.Folder, _Song.Video);
|
var videoFilePath = Path.Combine(song.Folder, song.Video);
|
||||||
_Video = CBase.Video.Load(videoFilePath);
|
var video = CBase.Video?.Load(videoFilePath);
|
||||||
if (_Video == null)
|
if (video == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_VideoFading = new CFading(0f, 1f, 3f);
|
_Video = video;
|
||||||
|
_VideoFading = new CFading(0f, 1f, 3f);
|
||||||
|
|
||||||
if (IsPlaying)
|
if (IsPlaying)
|
||||||
{
|
{
|
||||||
CBase.Video.Skip(_Video, Position, _Song.VideoGap);
|
CBase.Video?.Skip(video, Position, song.VideoGap);
|
||||||
CBase.Video.Resume(_Video);
|
CBase.Video?.Resume(video);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CBase.Video.Skip(_Video, 0f, _Song.VideoGap);
|
CBase.Video?.Skip(video, 0f, song.VideoGap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Play()
|
public override bool Play()
|
||||||
{
|
{
|
||||||
if (!base.Play())
|
lock (_lock)
|
||||||
{
|
{
|
||||||
return false;
|
if (!base.Play())
|
||||||
}
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (_Video != null)
|
var video = _Video;
|
||||||
{
|
var song = _Song;
|
||||||
CBase.Video.Skip(_Video, Position, _Song.VideoGap);
|
if (video != null && !video.IsClosed() && song != null)
|
||||||
CBase.Video.Resume(_Video);
|
{
|
||||||
}
|
CBase.Video?.Skip(video, Position, song.VideoGap);
|
||||||
|
CBase.Video?.Resume(video);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Pause()
|
public override bool Pause()
|
||||||
{
|
{
|
||||||
if (!base.Pause())
|
lock (_lock)
|
||||||
{
|
{
|
||||||
return false;
|
if (!base.Pause())
|
||||||
}
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (_Video != null)
|
var video = _Video;
|
||||||
{
|
if (video != null && !video.IsClosed())
|
||||||
CBase.Video.Pause(_Video);
|
{
|
||||||
}
|
CBase.Video?.Pause(video);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Stop()
|
public override bool Stop()
|
||||||
{
|
{
|
||||||
if (!base.Stop())
|
lock (_lock)
|
||||||
{
|
{
|
||||||
return false;
|
if (!base.Stop())
|
||||||
}
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (_Video != null)
|
var video = _Video;
|
||||||
{
|
var song = _Song;
|
||||||
CBase.Video.Pause(_Video);
|
if (video != null && !video.IsClosed())
|
||||||
CBase.Video.Skip(_Video, 0f, _Song.VideoGap);
|
{
|
||||||
}
|
CBase.Video?.Pause(video);
|
||||||
|
if (song != null)
|
||||||
|
{
|
||||||
|
CBase.Video?.Skip(video, 0f, song.VideoGap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _CloseVideo()
|
private void _CloseVideo()
|
||||||
{
|
{
|
||||||
if (_Video != null)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
CBase.Video.Close(ref _Video);
|
if (_Video != null)
|
||||||
|
{
|
||||||
|
CBase.Video?.Close(ref _Video);
|
||||||
|
_Video = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Close()
|
public override void Close()
|
||||||
{
|
{
|
||||||
base.Close();
|
lock (_lock)
|
||||||
|
{
|
||||||
|
base.Close();
|
||||||
|
|
||||||
_Song = null;
|
_Song = null;
|
||||||
_CloseVideo();
|
_CloseVideo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user