diff --git a/App.xaml.cs b/App.xaml.cs index 49a5de9..53df18f 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -9,6 +9,7 @@ namespace unison private TaskbarIcon _systray; private HotkeyHandler _hotkeys; private SnapcastHandler _snapcast; + private ShuffleHandler _shuffle; private MPDHandler _mpd; protected override void OnStartup(StartupEventArgs e) @@ -29,6 +30,9 @@ namespace unison _snapcast = new SnapcastHandler(); Current.Properties["snapcast"] = _snapcast; + _shuffle = new ShuffleHandler(); + Current.Properties["shuffle"] = _shuffle; + Current.MainWindow = new MainWindow(); _systray = (TaskbarIcon)FindResource("SystrayTaskbar"); diff --git a/Handlers/MPDHandler.cs b/Handlers/MPDHandler.cs index 6f39980..a4b649d 100644 --- a/Handlers/MPDHandler.cs +++ b/Handlers/MPDHandler.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Net; using System.Text.RegularExpressions; using System.Threading; @@ -34,7 +35,7 @@ namespace unison public class MPDHandler { private bool _connected; - public string _version; + private string _version; private int _currentVolume; private int _previousVolume; private bool _currentRandom; @@ -43,6 +44,7 @@ namespace unison private bool _currentConsume; private double _currentTime; private double _totalTime; + private IEnumerable _Playlist; private MpdStatus _currentStatus; private IMpdFile _currentSong; @@ -155,9 +157,7 @@ namespace unison try { - Debug.WriteLine("SafelySendCommandAsync => before command"); IMpdMessage response = await _commandConnection.SendAsync(command); - Debug.WriteLine("SafelySendCommandAsync => after command"); if (!response.IsResponseValid) { string mpdError = response.Response?.Result?.MpdError; @@ -492,14 +492,26 @@ namespace unison public string GetVersion() => _version; public Statistics GetStats() => _stats; public double GetCurrentTime() => _currentTime; + public IEnumerable GetPlaylist() => _Playlist; public bool IsConnected() => _connected; public bool IsPlaying() => _currentStatus?.State == MpdState.Play; - public void Prev() => SendCommand(new PreviousCommand()); - public void Next() => SendCommand(new NextCommand()); - public void PlayPause() => SendCommand(new PauseResumeCommand()); + public bool CanPrevNext = true; + public void Prev() + { + if (CanPrevNext) + SendCommand(new PreviousCommand()); + } + + public void Next() + { + if (CanPrevNext) + SendCommand(new NextCommand()); + } + + public void PlayPause() => SendCommand(new PauseResumeCommand()); public void Play(int pos) => SendCommand(new PlayCommand(pos)); public void Random() => SendCommand(new RandomCommand(!_currentRandom)); @@ -555,6 +567,15 @@ namespace unison SendCommand(commandList); } + public async Task QueryPlaylist() => _Playlist = await SafelySendCommandAsync(new PlaylistCommand()); + + public int GetPlaylistCount() + { + if (_Playlist == null) + return 0; + return _Playlist.ToArray().Count(); + } + public async void QueryStats() { Dictionary Response = await SafelySendCommandAsync(new StatsCommand()); diff --git a/Handlers/ShuffleHandler.cs b/Handlers/ShuffleHandler.cs new file mode 100644 index 0000000..d73ebb0 --- /dev/null +++ b/Handlers/ShuffleHandler.cs @@ -0,0 +1,134 @@ +using MpcNET.Commands.Database; +using MpcNET.Commands.Queue; +using MpcNET.Tags; +using MpcNET.Types; +using MpcNET.Types.Filters; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace unison +{ + class ShuffleHandler + { + private MPDHandler _mpd; + public List _songList { get; } + public int AddedSongs = 0; + + public ShuffleHandler() + { + _songList = new(); + _mpd = (MPDHandler)Application.Current.Properties["mpd"]; + } + + private bool IsOnMainThread() + { + return Application.Current.Dispatcher.Thread == System.Threading.Thread.CurrentThread; + } + + public async Task GetSongsFromFilter(List filter) + { + Debug.WriteLine("[GetSongsFromFilterBefore] is on main thread => " + IsOnMainThread()); + await Task.Run(async() => + { + Debug.WriteLine("[GetSongsFromFilterAfter] is on main thread => " + IsOnMainThread()); + + _songList.Clear(); + int song = _mpd.GetStats().Songs; + + IEnumerable response = await _mpd.SafelySendCommandAsync(new SearchCommand(filter, 0, song + 1)); + + Debug.WriteLine("got response => " + response.Count()); + + foreach (IMpdFile file in response) + { + _songList.Add(file.Path); + Debug.WriteLine(file.Path); + } + }); + } + + public async Task AddToQueueRandom(int SongNumber) + { + Debug.WriteLine("Add To Queue Random"); + + await Task.Run(async () => + { + int AddedSongs = 0; + + Debug.WriteLine("song to add => " + SongNumber); + for (int i = 0; i < SongNumber; i++) + { + // generate random number + int song = new Random().Next(0, _mpd.GetStats().Songs - 1); + Debug.WriteLine("song " + song + " - song total " + _mpd.GetStats().Songs); + IEnumerable Response = await _mpd.SafelySendCommandAsync(new SearchCommand(new FilterTag(MpdTags.Title, "", FilterOperator.Contains), song, song + 1)); + + Debug.WriteLine("got response"); + + await Task.Delay(1); + if (Response.Count() > 0) + { + string filePath = Response.First().Path; + _mpd.AddSong(filePath); + Debug.WriteLine("song path => " + filePath); + + if (i == 0) + { + if (!_mpd.IsPlaying()) + _mpd.Play(0); + } + + AddedSongs++; + } + } + }); + + Debug.WriteLine("Add To Queue Random - finished"); + } + + public async Task AddToQueueFilter(int SongNumber) + { + Debug.WriteLine("Add To Queue Filter"); + + await Task.Run(async () => + { + int AddedSongs = 0; + + Debug.WriteLine("song to add => " + SongNumber); + // more requested songs than available => add everything + if (SongNumber > _songList.Count) + { + foreach (string path in _songList) + { + await Task.Delay(1); + _mpd.AddSong(path); + Debug.WriteLine("song path => " + path); + AddedSongs++; + } + } + // more available songs than requested => + // we add unique indexes until we reach the requested amount + else + { + HashSet SongIndex = new(); + Debug.WriteLine("while - before"); + while (SongIndex.Count < SongNumber) + { + int MaxIndex = new Random().Next(0, _songList.Count - 1); + SongIndex.Add(MaxIndex); + } + + foreach (int index in SongIndex) + _mpd.AddSong(_songList[index]); + Debug.WriteLine("while - after"); + } + }); + + Debug.WriteLine("Add To Queue Filter - finished"); + } + } +} \ No newline at end of file diff --git a/Views/MainWindow.xaml.cs b/Views/MainWindow.xaml.cs index 0faecd4..d443139 100644 --- a/Views/MainWindow.xaml.cs +++ b/Views/MainWindow.xaml.cs @@ -6,8 +6,9 @@ using System.Windows.Threading; using System.Windows.Interop; using System.Windows.Input; using System.Windows.Controls.Primitives; -using MpcNET.Commands.Queue; using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; namespace unison { @@ -53,6 +54,8 @@ namespace unison _mpd.QueryStats(); _settingsWin.UpdateStats(); + _mpd.QueryPlaylist().ConfigureAwait(false); + Snapcast.IsEnabled = true; ConnectionOkIcon.Visibility = Visibility.Visible; ConnectionFailIcon.Visibility = Visibility.Collapsed; @@ -121,11 +124,21 @@ namespace unison if (!_shuffleWin.GetContinuous()) return; - NextTrack.IsEnabled = false; - PreviousTrack.IsEnabled = false; + await Task.Run(async () => + { + Debug.WriteLine("start continuous"); + + await _mpd.QueryPlaylist(); + + Debug.WriteLine("queried playlist"); + }); + + if (_mpd.GetPlaylistCount() > 5) + return; + + _mpd.CanPrevNext = false; await _shuffleWin.HandleContinuous(); - NextTrack.IsEnabled = true; - PreviousTrack.IsEnabled = true; + _mpd.CanPrevNext = true; Debug.WriteLine("finished continuous"); } @@ -227,19 +240,8 @@ namespace unison } public void Pause_Clicked(object sender, RoutedEventArgs e) => _mpd.PlayPause(); - - public void Previous_Clicked(object sender, RoutedEventArgs e) - { - if (PreviousTrack.IsEnabled) - _mpd.Prev(); - } - - public void Next_Clicked(object sender, RoutedEventArgs e) - { - if (NextTrack.IsEnabled) - _mpd.Next(); - } - + public void Previous_Clicked(object sender, RoutedEventArgs e) => _mpd.Prev(); + public void Next_Clicked(object sender, RoutedEventArgs e) => _mpd.Next(); public void Random_Clicked(object sender, RoutedEventArgs e) => _mpd.Random(); public void Repeat_Clicked(object sender, RoutedEventArgs e) => _mpd.Repeat(); public void Single_Clicked(object sender, RoutedEventArgs e) => _mpd.Single(); diff --git a/Views/Shuffle.xaml b/Views/Shuffle.xaml index 0c99c00..af3a9bc 100644 --- a/Views/Shuffle.xaml +++ b/Views/Shuffle.xaml @@ -68,6 +68,7 @@