unison/Views/Shuffle.xaml.cs

424 lines
13 KiB
C#
Raw Normal View History

2022-11-13 13:01:07 +00:00
using System;
2021-10-06 20:54:55 +00:00
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading.Tasks;
2021-10-05 12:23:23 +00:00
using System.Windows;
using System.Windows.Controls;
2021-10-05 12:23:23 +00:00
using System.Windows.Interop;
using System.Windows.Media;
using System.Linq;
using System.Windows.Input;
using System.Text.RegularExpressions;
using System.Threading;
2022-11-13 13:01:07 +00:00
using MpcNET.Commands.Database;
using MpcNET.Tags;
using MpcNET.Types;
using MpcNET.Types.Filters;
2021-10-05 12:23:23 +00:00
namespace unison
{
public partial class Shuffle : Window
{
2022-11-13 13:01:07 +00:00
private readonly MPDHandler _mpd;
private readonly ShuffleHandler _shuffle;
List<string> GenreList { get; }
List<string> FolderList { get; }
List<IFilter> Filters { get; }
2021-10-06 20:54:55 +00:00
bool _continuous = false;
2021-10-05 12:23:23 +00:00
public Shuffle()
{
InitializeComponent();
2022-11-13 13:01:07 +00:00
GenreList = new();
FolderList = new();
Filters = new();
SongFilterNumber.Text = "0";
2021-10-06 20:54:55 +00:00
_mpd = (MPDHandler)Application.Current.Properties["mpd"];
_shuffle = (ShuffleHandler)Application.Current.Properties["shuffle"];
}
public void Initialize()
2021-10-06 20:54:55 +00:00
{
ListGenre(_mpd._cancelCommand.Token);
ListFolder(_mpd._cancelCommand.Token);
2021-10-06 20:54:55 +00:00
}
public async void ListGenre(CancellationToken token)
2021-10-06 20:54:55 +00:00
{
2022-11-13 13:01:07 +00:00
if (GenreList.Count != 0)
2021-10-07 20:14:09 +00:00
return;
2021-10-06 20:54:55 +00:00
if (token.IsCancellationRequested)
return;
List<string> Response = await _mpd.SafelySendCommandAsync(new ListCommand(MpdTags.Genre, null, null));
2021-10-06 20:54:55 +00:00
if (Response == null)
return;
2021-10-06 20:54:55 +00:00
foreach (string genre in Response)
2022-11-13 13:01:07 +00:00
GenreList.Add(genre);
2021-10-06 20:54:55 +00:00
}
public async void ListFolder(CancellationToken token)
2021-10-06 20:54:55 +00:00
{
2022-11-13 13:01:07 +00:00
if (FolderList.Count != 0)
return;
2021-10-07 20:14:09 +00:00
if (token.IsCancellationRequested)
return;
IEnumerable<IMpdFilePath> Response = await _mpd.SafelySendCommandAsync(new LsInfoCommand(""));
if (Response == null)
return;
foreach (IMpdFilePath folder in Response)
2022-11-13 13:01:07 +00:00
FolderList.Add(folder.Name);
2021-10-06 20:54:55 +00:00
}
private bool IsFilterEmpty()
2021-10-06 20:54:55 +00:00
{
2022-11-13 13:01:07 +00:00
if (Filters.Count() == 0)
return true;
return false;
2021-10-05 12:23:23 +00:00
}
private T FindParent<T>(DependencyObject child) where T : DependencyObject
2021-10-06 20:54:55 +00:00
{
var parent = VisualTreeHelper.GetParent(child);
if (parent == null)
return null;
if (parent is T)
return parent as T;
2021-10-06 20:54:55 +00:00
else
return FindParent<T>(parent);
}
private void AddFilter_Clicked(object sender, RoutedEventArgs e)
{
FilterPanel.Children.Add(new ContentPresenter { ContentTemplate = (DataTemplate)FindResource("FilterPanel") });
SongFilterNumber.Text = "0";
2021-10-06 20:54:55 +00:00
}
private void RemoveFilter_Clicked(object sender, RoutedEventArgs e)
2021-10-07 20:14:09 +00:00
{
if (FilterPanel.Children.Count > 1)
FilterPanel.Children.Remove(FindParent<ContentPresenter>(sender as Button));
else
Reset_Clicked(null, null);
SongFilterNumber.Text = "0";
}
2021-10-07 20:14:09 +00:00
private void Reset_Clicked(object sender, RoutedEventArgs e)
{
FilterPanel.Children.RemoveRange(0, FilterPanel.Children.Count);
FilterPanel.Children.Add(new ContentPresenter { ContentTemplate = (DataTemplate)FindResource("FilterPanel") });
SongFilterNumber.Text = "0";
2022-11-13 13:01:07 +00:00
_shuffle.SongList.Clear();
}
2021-10-07 20:14:09 +00:00
private ITag FilterEquivalence_Type(string value)
{
if (value == "Song")
return MpdTags.Title;
else if (value == "Artist")
return MpdTags.Artist;
else if (value == "Album")
return MpdTags.Album;
else if (value == "Year")
return MpdTags.Date;
else if (value == "Genre")
return MpdTags.Genre;
return MpdTags.Title;
}
2021-10-07 20:14:09 +00:00
private FilterOperator FilterEquivalence_Operator(string value)
{
if (value == "contains")
return FilterOperator.Contains;
else if (value == "is")
return FilterOperator.Equal;
else if (value == "is not")
return FilterOperator.Different;
return FilterOperator.Equal;
2021-10-07 20:14:09 +00:00
}
2021-10-06 20:54:55 +00:00
private async void UpdateFilter_Clicked(object sender, RoutedEventArgs e)
2021-10-06 20:54:55 +00:00
{
2022-11-13 13:01:07 +00:00
QueryFilterText.Visibility = Visibility.Visible;
await UpdateFilter();
2022-11-13 13:01:07 +00:00
QueryFilterText.Visibility = Visibility.Collapsed;
}
private async Task UpdateFilter()
{
Debug.WriteLine("update filter => start");
2022-11-13 13:01:07 +00:00
Filters.Clear();
2021-10-06 20:54:55 +00:00
foreach (ContentPresenter superChild in FilterPanel.Children)
2021-10-06 20:54:55 +00:00
{
ITag tag = MpdTags.Title;
FilterOperator op = FilterOperator.None;
string value = "";
bool isDir = false;
2021-10-06 20:54:55 +00:00
Debug.WriteLine("update filter => part 1");
StackPanel stackPanel = VisualTreeHelper.GetChild(superChild, 0) as StackPanel;
foreach (TextBox child in stackPanel.Children.OfType<TextBox>())
{
if (child.Name == "FilterValue")
value = child.Text;
}
Debug.WriteLine("update filter => part 2");
foreach (ComboBox child in stackPanel.Children.OfType<ComboBox>())
{
if (child.Name == "FilterType")
{
if (child.SelectedItem.ToString() == "Directory")
isDir = true;
else
tag = FilterEquivalence_Type(child.SelectedItem.ToString());
}
if (child.Name == "FilterOperator")
op = FilterEquivalence_Operator(child.SelectedItem.ToString());
if (child.Name == "FilterList" && child.Visibility == Visibility.Visible)
value = child.SelectedItem.ToString();
}
2021-10-06 20:54:55 +00:00
Debug.WriteLine("update filter => part 3");
if (value != "")
2021-10-06 20:54:55 +00:00
{
if (!isDir)
2022-11-13 13:01:07 +00:00
Filters.Add(new FilterTag(tag, value, op));
else
2022-11-13 13:01:07 +00:00
Filters.Add(new FilterBase(value, FilterOperator.None));
2021-10-06 20:54:55 +00:00
await Task.Run(async () =>
{
2022-11-13 13:01:07 +00:00
await _shuffle.GetSongsFromFilter(Filters, _mpd._cancelCommand.Token);
});
SongFilterPanel.Visibility = Visibility.Visible;
2022-11-13 13:01:07 +00:00
SongFilterNumber.Text = _shuffle.SongList.Count.ToString();
2021-10-06 20:54:55 +00:00
}
Debug.WriteLine("update filter => part 4");
2021-10-06 20:54:55 +00:00
}
Debug.WriteLine("update filter => stop");
}
private void FilterType_Change(object sender, string Operator, List<string> Listing)
{
ComboBox comboBox = sender as ComboBox;
StackPanel stackPanel = comboBox.Parent as StackPanel;
foreach (ComboBox child in stackPanel.Children.OfType<ComboBox>())
{
if (child.Name == "FilterOperator")
{
child.ItemsSource = (Array)FindResource(Operator);
child.SelectedItem = child.Items[0];
}
if (child.Name == "FilterList")
{
child.Visibility = Visibility.Visible;
child.ItemsSource = Listing;
child.SelectedItem = child.Items[0];
}
}
foreach (TextBox child in stackPanel.Children.OfType<TextBox>())
{
if (child.Name == "FilterValue")
child.Visibility = Visibility.Collapsed;
}
SongFilterNumber.Text = "0";
}
private void FilterType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string item = e.AddedItems[0].ToString();
if (item == "Genre")
2022-11-13 13:01:07 +00:00
FilterType_Change(sender, "OperatorTypeB", GenreList);
else if (item == "Directory")
2022-11-13 13:01:07 +00:00
FilterType_Change(sender, "OperatorTypeC", FolderList);
else
{
ComboBox combobox = sender as ComboBox;
StackPanel stackpanel = combobox.Parent as StackPanel;
foreach (ComboBox child in stackpanel.Children.OfType<ComboBox>())
{
if (child.Name == "FilterOperator")
{
child.ItemsSource = (Array)FindResource("OperatorTypeA");
child.SelectedItem = child.Items[0];
}
if (child.Name == "FilterList")
child.Visibility = Visibility.Collapsed;
}
foreach (TextBox child in stackpanel.Children.OfType<TextBox>())
{
if (child.Name == "FilterValue")
child.Visibility = Visibility.Visible;
}
}
SongFilterNumber.Text = "0";
}
private void OperatorType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine("selection changed => operator type");
SongFilterNumber.Text = "0";
2021-10-06 20:54:55 +00:00
}
private void QueueValidationTextBox(object sender, TextCompositionEventArgs e)
2021-10-06 20:54:55 +00:00
{
Regex regex = new Regex("[^0-9]+");
e.Handled = regex.IsMatch(e.Text);
}
private void QueueValidationNumber()
{
2022-11-13 13:01:07 +00:00
int Number;
try
{
Number = int.Parse(SongNumber.Text);
}
catch (Exception)
{
return;
}
if (Number < 1)
SongNumber.Text = "1";
2022-11-13 13:01:07 +00:00
if (IsFilterEmpty())
{
if (Number > 100)
SongNumber.Text = "100";
}
else
{
if (Number > 1000)
SongNumber.Text = "1000";
}
}
2022-11-13 13:01:07 +00:00
private async void AddToQueue()
{
if (_mpd.GetStats() == null)
return;
2022-11-13 13:01:07 +00:00
await UpdateFilter();
QueueValidationNumber();
2022-11-13 13:01:07 +00:00
// TODO
// Added => Adding songs...
// to
// Added X songs! (display for 5 seconds)
2022-11-13 13:01:07 +00:00
NumberAddedSongs.Text = SongNumber.Text;
SearchStatus.Visibility = Visibility.Visible;
2022-11-13 13:01:07 +00:00
int Num = int.Parse(SongNumber.Text);
await AddToQueue_Internal(Num);
2021-10-06 20:54:55 +00:00
SearchStatus.Visibility = Visibility.Collapsed;
}
2022-11-13 13:01:07 +00:00
private async Task AddToQueue_Internal(int Num)
{
if (IsFilterEmpty())
{
await Task.Run(async () =>
{
2022-11-13 13:01:07 +00:00
await _shuffle.AddToQueueRandom(Num, _mpd._cancelCommand.Token);
});
}
2021-10-06 20:54:55 +00:00
else
{
await Task.Run(async () =>
{
2022-11-13 13:01:07 +00:00
await _shuffle.AddToQueueFilter(Num, _mpd._cancelCommand.Token);
});
2021-10-06 20:54:55 +00:00
}
2022-11-13 13:01:07 +00:00
}
private void QueryFilterHandler(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
UpdateFilter_Clicked(null, null);
}
2021-10-06 20:54:55 +00:00
2022-11-13 13:01:07 +00:00
private void AddToQueueHandler(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
AddToQueue();
}
private void AddToQueue_Clicked(object sender, RoutedEventArgs e)
{
AddToQueue();
}
public bool GetContinuous()
{
return _continuous;
2021-10-06 20:54:55 +00:00
}
public async Task HandleContinuous()
2021-10-05 12:23:23 +00:00
{
if (!_continuous)
2022-04-18 23:17:48 +00:00
{
Debug.WriteLine("continuous return nothing!");
2021-10-06 20:54:55 +00:00
return;
2022-04-18 23:17:48 +00:00
}
2021-10-05 12:23:23 +00:00
2022-04-18 23:17:48 +00:00
Debug.WriteLine("continuous __before__ add to queue");
2022-11-13 13:01:07 +00:00
await UpdateFilter();
2022-11-13 13:01:07 +00:00
int Num = 5;
await AddToQueue_Internal(Num);
2022-04-18 23:17:48 +00:00
Debug.WriteLine("continuous __after__ add to queue");
}
private async void ContinuousShuffle_Checked(object sender, RoutedEventArgs e)
{
if (ContinuousShuffle.IsChecked == true)
_continuous = true;
2021-10-06 20:54:55 +00:00
else
_continuous = false;
2022-11-13 13:01:07 +00:00
if (_mpd.GetStatus().PlaylistLength < 5)
await HandleContinuous();
2021-10-05 12:23:23 +00:00
}
2022-11-13 13:01:07 +00:00
private void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
WindowState = WindowState.Minimized;
Hide();
}
public void InitHwnd()
{
WindowInteropHelper helper = new(this);
helper.EnsureHandle();
}
2021-10-05 12:23:23 +00:00
}
}