Compare commits
	
		
			5 Commits
		
	
	
		
			v1.3.1
			...
			c93a9a326e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c93a9a326e | |||
| c055c59de7 | |||
| 4c71d6a6e0 | |||
| 3685c369b4 | |||
| e0d640532c | 
@@ -497,21 +497,23 @@ namespace unison
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public async void QueryStats()
 | 
					        public async void QueryStats()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Dictionary<string, string> response = await SafelySendCommandAsync(new StatsCommand());
 | 
					            Dictionary<string, string> Response = await SafelySendCommandAsync(new StatsCommand());
 | 
				
			||||||
 | 
					            if (Response == null)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _stats.Songs = int.Parse(response["songs"]);
 | 
					            _stats.Songs = int.Parse(Response["songs"]);
 | 
				
			||||||
            _stats.Albums = int.Parse(response["albums"]);
 | 
					            _stats.Albums = int.Parse(Response["albums"]);
 | 
				
			||||||
            _stats.Artists = int.Parse(response["artists"]);
 | 
					            _stats.Artists = int.Parse(Response["artists"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            TimeSpan time;
 | 
					            TimeSpan time;
 | 
				
			||||||
            time = TimeSpan.FromSeconds(int.Parse(response["uptime"]));
 | 
					            time = TimeSpan.FromSeconds(int.Parse(Response["uptime"]));
 | 
				
			||||||
            _stats.Uptime = time.ToString(@"dd\:hh\:mm\:ss");
 | 
					            _stats.Uptime = time.ToString(@"dd\:hh\:mm\:ss");
 | 
				
			||||||
            time = TimeSpan.FromSeconds(int.Parse(response["db_playtime"]));
 | 
					            time = TimeSpan.FromSeconds(int.Parse(Response["db_playtime"]));
 | 
				
			||||||
            _stats.TotalPlaytime = time.ToString(@"dd\:hh\:mm\:ss");
 | 
					            _stats.TotalPlaytime = time.ToString(@"dd\:hh\:mm\:ss");
 | 
				
			||||||
            time = TimeSpan.FromSeconds(int.Parse(response["playtime"]));
 | 
					            time = TimeSpan.FromSeconds(int.Parse(Response["playtime"]));
 | 
				
			||||||
            _stats.TotalTimePlayed = time.ToString(@"dd\:hh\:mm\:ss");
 | 
					            _stats.TotalTimePlayed = time.ToString(@"dd\:hh\:mm\:ss");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            DateTime date = new DateTime(1970, 1, 1).AddSeconds(int.Parse(response["db_update"])).ToLocalTime();
 | 
					            DateTime date = new DateTime(1970, 1, 1).AddSeconds(int.Parse(Response["db_update"])).ToLocalTime();
 | 
				
			||||||
            _stats.DatabaseUpdate = date.ToString("dd/MM/yyyy @ HH:mm");
 | 
					            _stats.DatabaseUpdate = date.ToString("dd/MM/yyyy @ HH:mm");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -135,12 +135,12 @@
 | 
				
			|||||||
                <TextBlock x:Name="Connection" HorizontalAlignment="Center" Text="Not connected" TextWrapping="Wrap" VerticalAlignment="Top" TextAlignment="Center" Foreground="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}" Margin="5,0,0,0" />
 | 
					                <TextBlock x:Name="Connection" HorizontalAlignment="Center" Text="Not connected" TextWrapping="Wrap" VerticalAlignment="Top" TextAlignment="Center" Foreground="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}" Margin="5,0,0,0" />
 | 
				
			||||||
            </StackPanel>
 | 
					            </StackPanel>
 | 
				
			||||||
            <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0,10,0">
 | 
					            <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" VerticalAlignment="Center" Margin="0,0,10,0">
 | 
				
			||||||
                <!--<Button x:Name="Shuffle" Padding="5, 2" HorizontalAlignment="Right" Margin="0,0,10,0" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
 | 
					                <Button x:Name="Shuffle" Padding="5, 2" Click="Shuffle_Clicked" Margin="0,0,10,0" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" FocusVisualStyle="{x:Null}">
 | 
				
			||||||
                    <StackPanel Orientation="Horizontal">
 | 
					                    <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                        <emoji:TextBlock Text="🔁" Padding="0,0,0,2"/>
 | 
					                        <emoji:TextBlock Text="🔁" Padding="0,0,0,2"/>
 | 
				
			||||||
                        <TextBlock Text="Shuffle" Margin="5, 0, 0, 0"/>
 | 
					                        <TextBlock Text="Shuffle" Margin="5, 0, 0, 0"/>
 | 
				
			||||||
                    </StackPanel>
 | 
					                    </StackPanel>
 | 
				
			||||||
                </Button>-->
 | 
					                </Button>
 | 
				
			||||||
                <Button x:Name="Settings" Padding="5, 2" Click="Settings_Clicked" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" FocusVisualStyle="{x:Null}">
 | 
					                <Button x:Name="Settings" Padding="5, 2" Click="Settings_Clicked" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" FocusVisualStyle="{x:Null}">
 | 
				
			||||||
                    <StackPanel Orientation="Horizontal">
 | 
					                    <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                        <emoji:TextBlock Text="🛠️"  Padding="0,0,0,2"/>
 | 
					                        <emoji:TextBlock Text="🛠️"  Padding="0,0,0,2"/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,8 @@ using System.Windows.Threading;
 | 
				
			|||||||
using System.Windows.Interop;
 | 
					using System.Windows.Interop;
 | 
				
			||||||
using System.Windows.Input;
 | 
					using System.Windows.Input;
 | 
				
			||||||
using System.Windows.Controls.Primitives;
 | 
					using System.Windows.Controls.Primitives;
 | 
				
			||||||
 | 
					using MpcNET.Commands.Queue;
 | 
				
			||||||
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace unison
 | 
					namespace unison
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -13,6 +15,7 @@ namespace unison
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly Settings _settingsWin;
 | 
					        private readonly Settings _settingsWin;
 | 
				
			||||||
        private readonly Radios _radiosWin;
 | 
					        private readonly Radios _radiosWin;
 | 
				
			||||||
 | 
					        private readonly Shuffle _shuffleWin;
 | 
				
			||||||
        private readonly DispatcherTimer _timer;
 | 
					        private readonly DispatcherTimer _timer;
 | 
				
			||||||
        private readonly MPDHandler _mpd;
 | 
					        private readonly MPDHandler _mpd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,6 +28,7 @@ namespace unison
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            _settingsWin = new Settings();
 | 
					            _settingsWin = new Settings();
 | 
				
			||||||
            _radiosWin = new Radios();
 | 
					            _radiosWin = new Radios();
 | 
				
			||||||
 | 
					            _shuffleWin = new Shuffle();
 | 
				
			||||||
            _timer = new DispatcherTimer();
 | 
					            _timer = new DispatcherTimer();
 | 
				
			||||||
            _mpd = (MPDHandler)Application.Current.Properties["mpd"];
 | 
					            _mpd = (MPDHandler)Application.Current.Properties["mpd"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,9 +63,12 @@ namespace unison
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            _settingsWin.UpdateConnectionStatus();
 | 
					            _settingsWin.UpdateConnectionStatus();
 | 
				
			||||||
            Connection.Text = $"{Properties.Settings.Default.mpd_host}:{Properties.Settings.Default.mpd_port}";
 | 
					            Connection.Text = $"{Properties.Settings.Default.mpd_host}:{Properties.Settings.Default.mpd_port}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _shuffleWin.ListGenre();
 | 
				
			||||||
 | 
					            _shuffleWin.ListFolder();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void OnSongChanged(object sender, EventArgs e)
 | 
					        public async void OnSongChanged(object sender, EventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (_mpd.GetCurrentSong() == null)
 | 
					            if (_mpd.GetCurrentSong() == null)
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
@@ -107,6 +114,32 @@ namespace unison
 | 
				
			|||||||
                    _timer.Start();
 | 
					                    _timer.Start();
 | 
				
			||||||
                EndTime.Text = FormatSeconds(_mpd.GetCurrentSong().Time);
 | 
					                EndTime.Text = FormatSeconds(_mpd.GetCurrentSong().Time);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Debug.WriteLine("Song changed called!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // handle continuous shuffle
 | 
				
			||||||
 | 
					            if (_shuffleWin.GetContinuous())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                System.Collections.Generic.IEnumerable<MpcNET.Types.IMpdFile> a = await _mpd.SafelySendCommandAsync(new PlaylistCommand());
 | 
				
			||||||
 | 
					                int queueSize = 0;
 | 
				
			||||||
 | 
					                foreach (var i in a)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Debug.WriteLine(i.Path);
 | 
				
			||||||
 | 
					                    queueSize++;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Debug.WriteLine("queue size is: " + queueSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (queueSize < 5)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    _shuffleWin.AddContinuousSongs();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // query queue
 | 
				
			||||||
 | 
					                // if (queue.SongRemaining < 5)
 | 
				
			||||||
 | 
					                //{
 | 
				
			||||||
 | 
					                //    // query shuffle songs
 | 
				
			||||||
 | 
					                //}
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void OnStatusChanged(object sender, EventArgs e)
 | 
					        public void OnStatusChanged(object sender, EventArgs e)
 | 
				
			||||||
@@ -229,6 +262,15 @@ namespace unison
 | 
				
			|||||||
                _radiosWin.WindowState = WindowState.Normal;
 | 
					                _radiosWin.WindowState = WindowState.Normal;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Shuffle_Clicked(object sender, RoutedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _shuffleWin.Show();
 | 
				
			||||||
 | 
					            _shuffleWin.Activate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (_shuffleWin.WindowState == WindowState.Minimized)
 | 
				
			||||||
 | 
					                _shuffleWin.WindowState = WindowState.Normal;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void Settings_Clicked(object sender, RoutedEventArgs e)
 | 
					        public void Settings_Clicked(object sender, RoutedEventArgs e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _settingsWin.Show();
 | 
					            _settingsWin.Show();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,25 +44,53 @@
 | 
				
			|||||||
                    </DockPanel>
 | 
					                    </DockPanel>
 | 
				
			||||||
                </TabItem>
 | 
					                </TabItem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <TabItem Header="{x:Static properties:Resources.Stats}">
 | 
					
 | 
				
			||||||
 | 
					                <TabItem Header="{x:Static properties:Resources.Settings_Shortcuts}">
 | 
				
			||||||
                    <DockPanel Margin="8">
 | 
					                    <DockPanel Margin="8">
 | 
				
			||||||
                        <GroupBox DockPanel.Dock="Top" Padding="0,4,0,0">
 | 
					                        <GroupBox DockPanel.Dock="Top" Padding="0,4,0,0">
 | 
				
			||||||
                            <GroupBox.Header>
 | 
					                            <GroupBox.Header>
 | 
				
			||||||
                                <TextBlock>
 | 
					                                <TextBlock>
 | 
				
			||||||
                                    <emoji:EmojiInline Text="📊"/>
 | 
					                                    <emoji:EmojiInline Text="⌨️ "/>
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Stats}"/>
 | 
					                                    <Run Text="{x:Static properties:Resources.Settings_Shortcuts}"></Run>
 | 
				
			||||||
                                </TextBlock>
 | 
					                                </TextBlock>
 | 
				
			||||||
                            </GroupBox.Header>
 | 
					                            </GroupBox.Header>
 | 
				
			||||||
                            <Grid VerticalAlignment="Top">
 | 
					                            <Grid>
 | 
				
			||||||
                                <TextBlock>
 | 
					                                <StackPanel>
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Stats_Songs}"/><Run Text=" "/><Run x:Name="StatSong"/><LineBreak/>
 | 
					                                    <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Stats_Albums}"/><Run Text=" "/><Run x:Name="StatAlbum"/><LineBreak/>
 | 
					                                        <TextBox x:Name="VolumeOffset" TextWrapping="Wrap" Width="25" PreviewTextInput="NumberValidationTextBox" Margin="0,2,0,0"/>
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Stats_Artists}"/><Run Text=" "/><Run x:Name="StatArtist"/><LineBreak/>
 | 
					                                        <TextBlock Text="{x:Static properties:Resources.Settings_VolumeOffset}" TextWrapping="Wrap" Margin="5,2,0,0"/>
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Stats_TotalPlaytime}"/><Run Text=" "/><Run x:Name="StatTotalPlaytime"/><LineBreak/><LineBreak/>
 | 
					                                    </StackPanel>
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Stats_Uptime}"/><Run Text=" "/><Run x:Name="StatUptime"/><LineBreak/>
 | 
					                                    <Grid MinWidth="300" Margin="0,5,0,0">
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Stats_TotalTimePlayed}"/><Run Text=" "/><Run x:Name="StatTotalTimePlayed"/><LineBreak/>
 | 
					                                        <Grid.ColumnDefinitions>
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Stats_LastDatabaseUpdate}"/><Run Text=" "/><Run x:Name="StatDatabaseUpdate"/>
 | 
					                                            <ColumnDefinition/>
 | 
				
			||||||
                                </TextBlock>
 | 
					                                            <ColumnDefinition/>
 | 
				
			||||||
 | 
					                                        </Grid.ColumnDefinitions>
 | 
				
			||||||
 | 
					                                        <Grid.RowDefinitions>
 | 
				
			||||||
 | 
					                                            <RowDefinition/>
 | 
				
			||||||
 | 
					                                            <RowDefinition/>
 | 
				
			||||||
 | 
					                                            <RowDefinition/>
 | 
				
			||||||
 | 
					                                            <RowDefinition/>
 | 
				
			||||||
 | 
					                                            <RowDefinition/>
 | 
				
			||||||
 | 
					                                            <RowDefinition/>
 | 
				
			||||||
 | 
					                                            <RowDefinition/>
 | 
				
			||||||
 | 
					                                        </Grid.RowDefinitions>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="{x:Static properties:Resources.Settings_NextTrack}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="0" Margin="1"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="{x:Static properties:Resources.Settings_PreviousTrack}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="1" Margin="1"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="{x:Static properties:Resources.Settings_PlayPause}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="2" Margin="1"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="{x:Static properties:Resources.Settings_VolumeUp}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="3" Margin="1"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="{x:Static properties:Resources.Settings_VolumeDown}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="4" Margin="1"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="{x:Static properties:Resources.Settings_VolumeMute}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="5" Margin="1"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="{x:Static properties:Resources.Settings_ShowWindow}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="6" Margin="1"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        <TextBlock Text="ctrl + media_next" TextWrapping="Wrap" Grid.Column="1" Grid.Row="0" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="ctrl + media_prev" TextWrapping="Wrap" Grid.Column="1" Grid.Row="1" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="ctrl + media_play" TextWrapping="Wrap" Grid.Column="1" Grid.Row="2" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="ctrl + volume_up" TextWrapping="Wrap" Grid.Column="1" Grid.Row="3" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="ctrl + volume_down" TextWrapping="Wrap" Grid.Column="1" Grid.Row="4" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="ctrl + volume_mute" TextWrapping="Wrap" Grid.Column="1" Grid.Row="5" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
				
			||||||
 | 
					                                        <TextBlock Text="ctrl + alt + enter" TextWrapping="Wrap" Grid.Column="1" Grid.Row="6" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
				
			||||||
 | 
					                                    </Grid>
 | 
				
			||||||
 | 
					                                </StackPanel>
 | 
				
			||||||
                            </Grid>
 | 
					                            </Grid>
 | 
				
			||||||
                        </GroupBox>
 | 
					                        </GroupBox>
 | 
				
			||||||
                    </DockPanel>
 | 
					                    </DockPanel>
 | 
				
			||||||
@@ -98,57 +126,61 @@
 | 
				
			|||||||
                    </DockPanel>
 | 
					                    </DockPanel>
 | 
				
			||||||
                </TabItem>
 | 
					                </TabItem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <TabItem Header="{x:Static properties:Resources.Settings_Shortcuts}">
 | 
					                <TabItem Header="Shuffle">
 | 
				
			||||||
                    <DockPanel Margin="8">
 | 
					                    <DockPanel Margin="8">
 | 
				
			||||||
                        <GroupBox DockPanel.Dock="Top" Padding="0,4,0,0">
 | 
					                        <GroupBox DockPanel.Dock="Top" Padding="0,4,0,0">
 | 
				
			||||||
                            <GroupBox.Header>
 | 
					                            <GroupBox.Header>
 | 
				
			||||||
                                <TextBlock>
 | 
					                                <TextBlock>
 | 
				
			||||||
                                    <emoji:EmojiInline Text="⌨️ "/>
 | 
					                                    <emoji:EmojiInline Text="🔁 "/>
 | 
				
			||||||
                                    <Run Text="{x:Static properties:Resources.Settings_Shortcuts}"></Run>
 | 
					                                    <Run Text="Shuffle"></Run>
 | 
				
			||||||
                                </TextBlock>
 | 
					                                </TextBlock>
 | 
				
			||||||
                            </GroupBox.Header>
 | 
					                            </GroupBox.Header>
 | 
				
			||||||
                            <Grid>
 | 
					                            <Grid MaxWidth="500">
 | 
				
			||||||
                                <StackPanel>
 | 
					                                <StackPanel>
 | 
				
			||||||
                                    <StackPanel Orientation="Horizontal">
 | 
					                                    <StackPanel Orientation="Horizontal">
 | 
				
			||||||
                                        <TextBlock Text="{x:Static properties:Resources.Settings_VolumeOffset}" TextWrapping="Wrap" Margin="0,2,0,0"/>
 | 
					                                        <TextBox TextWrapping="Wrap" Width="25" PreviewTextInput="NumberValidationTextBox" Margin="0,2,0,0"/>
 | 
				
			||||||
                                        <TextBox x:Name="VolumeOffset" TextWrapping="Wrap" Width="25" PreviewTextInput="NumberValidationTextBox" Margin="8,2,0,0"/>
 | 
					                                        <TextBlock Text="Prevent repetition rate (0-100%)" TextWrapping="Wrap" Margin="5,2,0,0"/>
 | 
				
			||||||
                                    </StackPanel>
 | 
					                                    </StackPanel>
 | 
				
			||||||
                                    <Grid MinWidth="300" Margin="0,5,0,0">
 | 
					                                    <TextBlock TextWrapping="Wrap" Margin="0,10,0,0">
 | 
				
			||||||
                                        <Grid.ColumnDefinitions>
 | 
					                                        <Run>The shuffle window allows to add random songs to your queue. Both options take into account the filter.</Run>
 | 
				
			||||||
                                            <ColumnDefinition/>
 | 
					                                        <Run>If the filter is empty, the entire music library is taken into account.</Run><LineBreak/><LineBreak/>
 | 
				
			||||||
                                            <ColumnDefinition/>
 | 
					                                        <Run FontWeight="Bold">Continuous shuffle</Run><LineBreak/>
 | 
				
			||||||
                                        </Grid.ColumnDefinitions>
 | 
					                                        <Run>By enabling this option, unison will automatically add songs to the queue so you never run out of songs to listen to.</Run>
 | 
				
			||||||
                                        <Grid.RowDefinitions>
 | 
					                                        <LineBreak/><LineBreak/>
 | 
				
			||||||
                                            <RowDefinition/>
 | 
					                                        
 | 
				
			||||||
                                            <RowDefinition/>
 | 
					                                        <Run FontWeight="Bold">Add to queue</Run><LineBreak/>
 | 
				
			||||||
                                            <RowDefinition/>
 | 
					                                        <Run>Add a fixed number of songs to the queue. It can take a long time to add more than 100 songs, so the option is limited to 1000 songs.</Run>
 | 
				
			||||||
                                            <RowDefinition/>
 | 
					                                    </TextBlock>
 | 
				
			||||||
                                            <RowDefinition/>
 | 
					 | 
				
			||||||
                                            <RowDefinition/>
 | 
					 | 
				
			||||||
                                            <RowDefinition/>
 | 
					 | 
				
			||||||
                                        </Grid.RowDefinitions>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="{x:Static properties:Resources.Settings_NextTrack}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="0" Margin="1"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="{x:Static properties:Resources.Settings_PreviousTrack}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="1" Margin="1"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="{x:Static properties:Resources.Settings_PlayPause}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="2" Margin="1"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="{x:Static properties:Resources.Settings_VolumeUp}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="3" Margin="1"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="{x:Static properties:Resources.Settings_VolumeDown}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="4" Margin="1"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="{x:Static properties:Resources.Settings_VolumeMute}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="5" Margin="1"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="{x:Static properties:Resources.Settings_ShowWindow}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="6" Margin="1"/>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                        <TextBlock Text="ctrl + media_next" TextWrapping="Wrap" Grid.Column="1" Grid.Row="0" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="ctrl + media_prev" TextWrapping="Wrap" Grid.Column="1" Grid.Row="1" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="ctrl + media_play" TextWrapping="Wrap" Grid.Column="1" Grid.Row="2" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="ctrl + volume_up" TextWrapping="Wrap" Grid.Column="1" Grid.Row="3" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="ctrl + volume_down" TextWrapping="Wrap" Grid.Column="1" Grid.Row="4" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="ctrl + volume_mute" TextWrapping="Wrap" Grid.Column="1" Grid.Row="5" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
					 | 
				
			||||||
                                        <TextBlock Text="ctrl + alt + enter" TextWrapping="Wrap" Grid.Column="1" Grid.Row="6" Margin="1" HorizontalAlignment="Right" FontWeight="Bold"/>
 | 
					 | 
				
			||||||
                                    </Grid>
 | 
					 | 
				
			||||||
                                </StackPanel>
 | 
					                                </StackPanel>
 | 
				
			||||||
                            </Grid>
 | 
					                            </Grid>
 | 
				
			||||||
                        </GroupBox>
 | 
					                        </GroupBox>
 | 
				
			||||||
                    </DockPanel>
 | 
					                    </DockPanel>
 | 
				
			||||||
                </TabItem>
 | 
					                </TabItem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <TabItem Header="{x:Static properties:Resources.Stats}">
 | 
				
			||||||
 | 
					                    <DockPanel Margin="8">
 | 
				
			||||||
 | 
					                        <GroupBox DockPanel.Dock="Top" Padding="0,4,0,0">
 | 
				
			||||||
 | 
					                            <GroupBox.Header>
 | 
				
			||||||
 | 
					                                <TextBlock>
 | 
				
			||||||
 | 
					                                    <emoji:EmojiInline Text="📊"/>
 | 
				
			||||||
 | 
					                                    <Run Text="{x:Static properties:Resources.Stats}"/>
 | 
				
			||||||
 | 
					                                </TextBlock>
 | 
				
			||||||
 | 
					                            </GroupBox.Header>
 | 
				
			||||||
 | 
					                            <Grid VerticalAlignment="Top">
 | 
				
			||||||
 | 
					                                <TextBlock>
 | 
				
			||||||
 | 
					                                    <Run Text="{x:Static properties:Resources.Stats_Songs}"/><Run Text=" "/><Run x:Name="StatSong"/><LineBreak/>
 | 
				
			||||||
 | 
					                                    <Run Text="{x:Static properties:Resources.Stats_Albums}"/><Run Text=" "/><Run x:Name="StatAlbum"/><LineBreak/>
 | 
				
			||||||
 | 
					                                    <Run Text="{x:Static properties:Resources.Stats_Artists}"/><Run Text=" "/><Run x:Name="StatArtist"/><LineBreak/>
 | 
				
			||||||
 | 
					                                    <Run Text="{x:Static properties:Resources.Stats_TotalPlaytime}"/><Run Text=" "/><Run x:Name="StatTotalPlaytime"/><LineBreak/><LineBreak/>
 | 
				
			||||||
 | 
					                                    <Run Text="{x:Static properties:Resources.Stats_Uptime}"/><Run Text=" "/><Run x:Name="StatUptime"/><LineBreak/>
 | 
				
			||||||
 | 
					                                    <Run Text="{x:Static properties:Resources.Stats_TotalTimePlayed}"/><Run Text=" "/><Run x:Name="StatTotalTimePlayed"/><LineBreak/>
 | 
				
			||||||
 | 
					                                    <Run Text="{x:Static properties:Resources.Stats_LastDatabaseUpdate}"/><Run Text=" "/><Run x:Name="StatDatabaseUpdate"/>
 | 
				
			||||||
 | 
					                                </TextBlock>
 | 
				
			||||||
 | 
					                            </Grid>
 | 
				
			||||||
 | 
					                        </GroupBox>
 | 
				
			||||||
 | 
					                    </DockPanel>
 | 
				
			||||||
 | 
					                </TabItem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <TabItem Header="{x:Static properties:Resources.Settings_About}" Height="20" VerticalAlignment="Bottom">
 | 
					                <TabItem Header="{x:Static properties:Resources.Settings_About}" Height="20" VerticalAlignment="Bottom">
 | 
				
			||||||
                    <DockPanel Margin="8">
 | 
					                    <DockPanel Margin="8">
 | 
				
			||||||
                        <GroupBox DockPanel.Dock="Top" Padding="0,4,0,0">
 | 
					                        <GroupBox DockPanel.Dock="Top" Padding="0,4,0,0">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										102
									
								
								Views/Shuffle.xaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								Views/Shuffle.xaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
				
			|||||||
 | 
					<Window x:Class="unison.Shuffle"
 | 
				
			||||||
 | 
					        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 | 
				
			||||||
 | 
					        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 | 
				
			||||||
 | 
					        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 | 
				
			||||||
 | 
					        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 | 
				
			||||||
 | 
					        xmlns:emoji="clr-namespace:Emoji.Wpf;assembly=Emoji.Wpf"
 | 
				
			||||||
 | 
					        xmlns:local="clr-namespace:unison"
 | 
				
			||||||
 | 
					        mc:Ignorable="d"
 | 
				
			||||||
 | 
					        Title="Shuffle" Closing="Window_Closing" SizeToContent="WidthAndHeight" ResizeMode="NoResize">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <Grid>
 | 
				
			||||||
 | 
					        <StackPanel>
 | 
				
			||||||
 | 
					            <StackPanel HorizontalAlignment="Left" Orientation="Vertical" Margin="5,0,5,5">
 | 
				
			||||||
 | 
					                <GroupBox DockPanel.Dock="Top" Padding="0,4,0,0">
 | 
				
			||||||
 | 
					                    <GroupBox.Header>
 | 
				
			||||||
 | 
					                        <TextBlock>
 | 
				
			||||||
 | 
					                            <emoji:EmojiInline Text="🔡"/>
 | 
				
			||||||
 | 
					                            <Run Text="Filter"/>
 | 
				
			||||||
 | 
					                        </TextBlock>
 | 
				
			||||||
 | 
					                    </GroupBox.Header>
 | 
				
			||||||
 | 
					                    <StackPanel Orientation="Vertical" Margin="5,0,5,0">
 | 
				
			||||||
 | 
					                        <StackPanel Orientation="Horizontal">
 | 
				
			||||||
 | 
					                            <StackPanel Orientation="Vertical">
 | 
				
			||||||
 | 
					                                <TextBlock Text="Song" Margin="0,0,0,2"/>
 | 
				
			||||||
 | 
					                                <TextBox x:Name="Song" Width="240" Margin="5,0,0,0"/>
 | 
				
			||||||
 | 
					                            </StackPanel>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            <StackPanel Orientation="Vertical" Margin="20,0,0,0">
 | 
				
			||||||
 | 
					                                <TextBlock Text="Artist" Margin="0,0,0,2"/>
 | 
				
			||||||
 | 
					                                <TextBox x:Name="Artist" Width="240" Margin="5,0,0,0"/>
 | 
				
			||||||
 | 
					                            </StackPanel>
 | 
				
			||||||
 | 
					                        </StackPanel>
 | 
				
			||||||
 | 
					                        <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
 | 
				
			||||||
 | 
					                            <StackPanel Orientation="Vertical">
 | 
				
			||||||
 | 
					                                <TextBlock Text="Album" Margin="0,0,0,2"/>
 | 
				
			||||||
 | 
					                                <TextBox x:Name="Album" Width="240" Margin="5,0,0,0"/>
 | 
				
			||||||
 | 
					                            </StackPanel>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            <StackPanel Orientation="Vertical" Margin="20,0,0,0">
 | 
				
			||||||
 | 
					                                <TextBlock Text="Year" Margin="0,0,0,2"/>
 | 
				
			||||||
 | 
					                                <TextBox x:Name="Year" Width="240" Margin="5,0,0,0"/>
 | 
				
			||||||
 | 
					                            </StackPanel>
 | 
				
			||||||
 | 
					                        </StackPanel>
 | 
				
			||||||
 | 
					                        <StackPanel Orientation="Horizontal" Margin="0,5,0,5">
 | 
				
			||||||
 | 
					                            <StackPanel Orientation="Vertical">
 | 
				
			||||||
 | 
					                                <TextBlock Text="Genre" Margin="0,0,0,2"/>
 | 
				
			||||||
 | 
					                                <ComboBox x:Name="Genre" SelectedIndex="0" Width="240" ScrollViewer.CanContentScroll="False" Margin="5,0,0,0"/>
 | 
				
			||||||
 | 
					                            </StackPanel>
 | 
				
			||||||
 | 
					                            <StackPanel Orientation="Vertical" Margin="20,0,0,0">
 | 
				
			||||||
 | 
					                                <TextBlock Text="Directory" Margin="0,0,0,2" TextDecorations="{x:Null}"/>
 | 
				
			||||||
 | 
					                                <ComboBox x:Name="Directory" SelectedIndex="0" Width="240" ScrollViewer.CanContentScroll="False" Margin="5,0,0,0" IsEnabled="False"/>
 | 
				
			||||||
 | 
					                            </StackPanel>
 | 
				
			||||||
 | 
					                        </StackPanel>
 | 
				
			||||||
 | 
					                        <StackPanel Orientation="Horizontal" Margin="0,5,0,5">
 | 
				
			||||||
 | 
					                            <Button Content="Reset" Click="Reset_Clicked" Padding="5, 2" VerticalAlignment="Bottom" HorizontalAlignment="Left" FocusVisualStyle="{x:Null}"/>
 | 
				
			||||||
 | 
					                        </StackPanel>
 | 
				
			||||||
 | 
					                        <StackPanel x:Name="SongFilterPanel" Margin="0,5,0,0" Visibility="Collapsed">
 | 
				
			||||||
 | 
					                            <TextBlock>
 | 
				
			||||||
 | 
					                                <Run Text="Number of songs in filter: "/><Run x:Name="SongFilterNumber" FontWeight="Bold"/>
 | 
				
			||||||
 | 
					                            </TextBlock>
 | 
				
			||||||
 | 
					                        </StackPanel>
 | 
				
			||||||
 | 
					                    </StackPanel>
 | 
				
			||||||
 | 
					                </GroupBox>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <GroupBox Margin="0,5,0,0" HorizontalAlignment="Stretch">
 | 
				
			||||||
 | 
					                    <GroupBox.Header>
 | 
				
			||||||
 | 
					                        <TextBlock>
 | 
				
			||||||
 | 
					                            <emoji:EmojiInline Text="♾️"/>
 | 
				
			||||||
 | 
					                            <Run Text="Continuous shuffle"/>
 | 
				
			||||||
 | 
					                        </TextBlock>
 | 
				
			||||||
 | 
					                    </GroupBox.Header>
 | 
				
			||||||
 | 
					                    <StackPanel Orientation="Horizontal" Margin="5,8,0,0">
 | 
				
			||||||
 | 
					                        <CheckBox x:Name="ContinuousShuffle" Checked="ContinuousShuffle_Checked" Unchecked="ContinuousShuffle_Checked">
 | 
				
			||||||
 | 
					                            <TextBlock Text="Enable continuous shuffle" TextWrapping="Wrap"/>
 | 
				
			||||||
 | 
					                        </CheckBox>
 | 
				
			||||||
 | 
					                    </StackPanel>
 | 
				
			||||||
 | 
					                </GroupBox>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <GroupBox x:Name="AddToQueueGroup" Margin="0,5,0,0" HorizontalAlignment="Stretch">
 | 
				
			||||||
 | 
					                    <GroupBox.Header>
 | 
				
			||||||
 | 
					                        <TextBlock>
 | 
				
			||||||
 | 
					                            <emoji:EmojiInline Text="➕"/>
 | 
				
			||||||
 | 
					                            <Run Text="Add to queue"/>
 | 
				
			||||||
 | 
					                        </TextBlock>
 | 
				
			||||||
 | 
					                    </GroupBox.Header>
 | 
				
			||||||
 | 
					                    <StackPanel Margin="5,0,0,0">
 | 
				
			||||||
 | 
					                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,10,0,0">
 | 
				
			||||||
 | 
					                            <TextBox x:Name="SongNumber" Text="100" Width="35" HorizontalAlignment="Left" VerticalAlignment="Top"/>
 | 
				
			||||||
 | 
					                            <TextBlock Text="Number of songs to add" Margin="5,0,0,5"/>
 | 
				
			||||||
 | 
					                        </StackPanel>
 | 
				
			||||||
 | 
					                        <StackPanel Orientation="Horizontal" Margin="0,2,0,0">
 | 
				
			||||||
 | 
					                            <Button Content="Add to queue" Click="AddToQueue_Clicked" Padding="5, 2" HorizontalAlignment="Left" FocusVisualStyle="{x:Null}"/>
 | 
				
			||||||
 | 
					                            <TextBlock x:Name="SearchStatus" Margin="15,3,0,0" FontStyle="Italic" Visibility="Collapsed">
 | 
				
			||||||
 | 
					                                <Run Text="Added "/><Run x:Name="NumberAddedSongs"/><Run Text=" songs to the queue..."/>
 | 
				
			||||||
 | 
					                            </TextBlock>
 | 
				
			||||||
 | 
					                        </StackPanel>
 | 
				
			||||||
 | 
					                    </StackPanel>
 | 
				
			||||||
 | 
					                </GroupBox>
 | 
				
			||||||
 | 
					            </StackPanel>
 | 
				
			||||||
 | 
					        </StackPanel>
 | 
				
			||||||
 | 
					    </Grid>
 | 
				
			||||||
 | 
					</Window>
 | 
				
			||||||
							
								
								
									
										294
									
								
								Views/Shuffle.xaml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								Views/Shuffle.xaml.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,294 @@
 | 
				
			|||||||
 | 
					using MpcNET;
 | 
				
			||||||
 | 
					using MpcNET.Commands.Database;
 | 
				
			||||||
 | 
					using MpcNET.Commands.Reflection;
 | 
				
			||||||
 | 
					using MpcNET.Tags;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.ComponentModel;
 | 
				
			||||||
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using System.Windows;
 | 
				
			||||||
 | 
					using System.Windows.Interop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace unison
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public partial class Shuffle : Window
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private MPDHandler _mpd;
 | 
				
			||||||
 | 
					        bool _continuous = false;
 | 
				
			||||||
 | 
					        List<string> _songList { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Shuffle()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            InitializeComponent();
 | 
				
			||||||
 | 
					            _songList = new();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool GetContinuous()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return _continuous;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void AddContinuousSongs()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (Song.Text.Length == 0 && Artist.Text.Length == 0 && Album.Text.Length == 0 && Year.Text.Length == 0 && Genre.SelectedIndex == 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ContinuousShuffle_AddToQueueRandom();
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int AddedSongs = 0;
 | 
				
			||||||
 | 
					            NumberAddedSongs.Text = AddedSongs.ToString();
 | 
				
			||||||
 | 
					            SearchStatus.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            HashSet<int> SongIndex = new();
 | 
				
			||||||
 | 
					            while (SongIndex.Count < 2)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                int MaxIndex = new Random().Next(0, _songList.Count - 1);
 | 
				
			||||||
 | 
					                SongIndex.Add(MaxIndex);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach (int index in SongIndex)
 | 
				
			||||||
 | 
					                _mpd.AddSong(_songList[index]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SearchStatus.Visibility = Visibility.Collapsed;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async void ListGenre()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (Genre.Items.Count == 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _mpd = (MPDHandler)Application.Current.Properties["mpd"];
 | 
				
			||||||
 | 
					                List<string> Response = await _mpd.SafelySendCommandAsync(new ListCommand(MpdTags.Genre, null, null));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (Response.Count > 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Genre.Items.Add("");
 | 
				
			||||||
 | 
					                    foreach (var genre in Response)
 | 
				
			||||||
 | 
					                        Genre.Items.Add(genre);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async void ListFolder()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (Directory.Items.Count == 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _mpd = (MPDHandler)Application.Current.Properties["mpd"];
 | 
				
			||||||
 | 
					                List<string> Response = await _mpd.SafelySendCommandAsync(new ListFilesCommand());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (Response.Count > 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Directory.Items.Add("");
 | 
				
			||||||
 | 
					                    for (int i = 0; i < Response.Count; i++)
 | 
				
			||||||
 | 
					                        if (i % 2 != 1)
 | 
				
			||||||
 | 
					                            Directory.Items.Add(Response[i]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void Window_Closing(object sender, CancelEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            e.Cancel = true;
 | 
				
			||||||
 | 
					            WindowState = WindowState.Minimized;
 | 
				
			||||||
 | 
					            Hide();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void InitHwnd()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            WindowInteropHelper helper = new(this);
 | 
				
			||||||
 | 
					            helper.EnsureHandle();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void Reset_Clicked(object sender, RoutedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Song.Text = "";
 | 
				
			||||||
 | 
					            Artist.Text = "";
 | 
				
			||||||
 | 
					            Album.Text = "";
 | 
				
			||||||
 | 
					            Year.Text = "";
 | 
				
			||||||
 | 
					            Genre.SelectedIndex = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async void ContinuousShuffle_Checked(object sender, RoutedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (ContinuousShuffle.IsChecked == true)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                AddToQueueGroup.IsEnabled = false;
 | 
				
			||||||
 | 
					                _continuous = true;
 | 
				
			||||||
 | 
					                _songList.Clear();
 | 
				
			||||||
 | 
					                if (Song.Text.Length == 0 && Artist.Text.Length == 0 && Album.Text.Length == 0 && Year.Text.Length == 0 && Genre.SelectedIndex == 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    /*await*/
 | 
				
			||||||
 | 
					                    GetSongsFromFilter();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                AddToQueueGroup.IsEnabled = true;
 | 
				
			||||||
 | 
					                _continuous = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async void ContinuousShuffle_AddToQueueRandom()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            for (int i = 0; i < 2; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // generate random number
 | 
				
			||||||
 | 
					                int song = new Random().Next(0, _mpd.GetStats().Songs - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // query random song
 | 
				
			||||||
 | 
					                CommandList commandList = new CommandList(new IMpcCommand<object>[] { new SearchCommand(MpdTags.Title, "", song, song + 1) });
 | 
				
			||||||
 | 
					                string Response = await _mpd.SafelySendCommandAsync(commandList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                await Task.Delay(1);
 | 
				
			||||||
 | 
					                if (Response.Length > 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // parse song and add it to queue
 | 
				
			||||||
 | 
					                    int start = Response.IndexOf("[file, ");
 | 
				
			||||||
 | 
					                    int end = Response.IndexOf("],");
 | 
				
			||||||
 | 
					                    string filePath = Response.Substring(start + 7, end - (start + 7));
 | 
				
			||||||
 | 
					                    _mpd.AddSong(filePath);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SearchStatus.Visibility = Visibility.Collapsed;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async void AddToQueueRandom()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int AddedSongs = 0;
 | 
				
			||||||
 | 
					            NumberAddedSongs.Text = AddedSongs.ToString();
 | 
				
			||||||
 | 
					            SearchStatus.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < int.Parse(SongNumber.Text); i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // generate random number
 | 
				
			||||||
 | 
					                int song = new Random().Next(0, _mpd.GetStats().Songs - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // query random song
 | 
				
			||||||
 | 
					                CommandList commandList = new CommandList(new IMpcCommand<object>[] { new SearchCommand(MpdTags.Title, "", song, song + 1) });
 | 
				
			||||||
 | 
					                string Response = await _mpd.SafelySendCommandAsync(commandList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                await Task.Delay(1);
 | 
				
			||||||
 | 
					                if (Response.Length > 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // parse song and add it to queue
 | 
				
			||||||
 | 
					                    int start = Response.IndexOf("[file, ");
 | 
				
			||||||
 | 
					                    int end = Response.IndexOf("],");
 | 
				
			||||||
 | 
					                    string filePath = Response.Substring(start + 7, end - (start + 7));
 | 
				
			||||||
 | 
					                    _mpd.AddSong(filePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    AddedSongs++;
 | 
				
			||||||
 | 
					                    NumberAddedSongs.Text = AddedSongs.ToString();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SearchStatus.Visibility = Visibility.Collapsed;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async Task GetSongsFromFilter()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _songList.Clear();
 | 
				
			||||||
 | 
					            SongFilterPanel.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int song = _mpd.GetStats().Songs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            List<KeyValuePair<ITag, string>> filters = new();
 | 
				
			||||||
 | 
					            filters.Add(new KeyValuePair<ITag, string>(MpdTags.Title, Song.Text));
 | 
				
			||||||
 | 
					            filters.Add(new KeyValuePair<ITag, string>(MpdTags.Artist, Artist.Text));
 | 
				
			||||||
 | 
					            filters.Add(new KeyValuePair<ITag, string>(MpdTags.Album, Album.Text));
 | 
				
			||||||
 | 
					            filters.Add(new KeyValuePair<ITag, string>(MpdTags.Date, Year.Text));
 | 
				
			||||||
 | 
					            filters.Add(new KeyValuePair<ITag, string>(MpdTags.Genre, Genre.Text));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            CommandList commandList = new CommandList(new IMpcCommand<object>[] { new SearchCommand(filters, 0, song + 1) });
 | 
				
			||||||
 | 
					            string Response = await _mpd.SafelySendCommandAsync(commandList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // create a list of the file url
 | 
				
			||||||
 | 
					            string[] value = Response.Split(", [file, ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // there are no song in this filter
 | 
				
			||||||
 | 
					            if (value[0] == "")
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                SongFilterNumber.Text = _songList.Count.ToString();
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach (string file in value)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                int start = 0;
 | 
				
			||||||
 | 
					                int end = file.IndexOf("],");
 | 
				
			||||||
 | 
					                string filePath = file.Substring(start, end - start);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                _songList.Add(filePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                SongFilterNumber.Text = _songList.Count.ToString();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // remove characters from first file
 | 
				
			||||||
 | 
					            _songList[0] = _songList[0].Substring(7, _songList[0].Length - 7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SongFilterPanel.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					            SongFilterNumber.Text = _songList.Count.ToString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // DEBUG
 | 
				
			||||||
 | 
					            //foreach (var a in _songList)
 | 
				
			||||||
 | 
					            //    Debug.WriteLine(a);
 | 
				
			||||||
 | 
					            Debug.WriteLine("number of songs found: " + _songList.Count);
 | 
				
			||||||
 | 
					            Debug.WriteLine("number of songs requested: " + int.Parse(SongNumber.Text));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private async void AddToQueueFilter()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            await GetSongsFromFilter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int AddedSongs = 0;
 | 
				
			||||||
 | 
					            NumberAddedSongs.Text = AddedSongs.ToString();
 | 
				
			||||||
 | 
					            SearchStatus.Visibility = Visibility.Visible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // more requested songs than available => add everything
 | 
				
			||||||
 | 
					            if (int.Parse(SongNumber.Text) > _songList.Count)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                foreach (string path in _songList)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    await Task.Delay(1);
 | 
				
			||||||
 | 
					                    _mpd.AddSong(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    AddedSongs++;
 | 
				
			||||||
 | 
					                    NumberAddedSongs.Text = AddedSongs.ToString();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // more available songs than requested =>
 | 
				
			||||||
 | 
					            // we add unique indexes until we reach the requested amount
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                HashSet<int> SongIndex = new();
 | 
				
			||||||
 | 
					                while (SongIndex.Count < int.Parse(SongNumber.Text))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    int MaxIndex = new Random().Next(0, _songList.Count - 1);
 | 
				
			||||||
 | 
					                    SongIndex.Add(MaxIndex);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                foreach (int index in SongIndex)
 | 
				
			||||||
 | 
					                    _mpd.AddSong(_songList[index]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SearchStatus.Visibility = Visibility.Collapsed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void AddToQueue_Clicked(object sender, RoutedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _mpd = (MPDHandler)Application.Current.Properties["mpd"];
 | 
				
			||||||
 | 
					            if (_mpd.GetStats() == null)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (Song.Text.Length == 0 && Artist.Text.Length == 0 && Album.Text.Length == 0 && Year.Text.Length == 0 && Genre.SelectedIndex == 0)
 | 
				
			||||||
 | 
					                AddToQueueRandom();
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                AddToQueueFilter();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -30,11 +30,11 @@
 | 
				
			|||||||
                <Image Width="16" Height="16" emoji:Image.Source="📻" />
 | 
					                <Image Width="16" Height="16" emoji:Image.Source="📻" />
 | 
				
			||||||
            </MenuItem.Icon>
 | 
					            </MenuItem.Icon>
 | 
				
			||||||
        </MenuItem>
 | 
					        </MenuItem>
 | 
				
			||||||
        <!--<MenuItem Header="Shuffle" Command="{Binding Shuffle}">
 | 
					        <MenuItem Header="Shuffle" Command="{Binding Shuffle}">
 | 
				
			||||||
            <MenuItem.Icon>
 | 
					            <MenuItem.Icon>
 | 
				
			||||||
                <Image Width="16" Height="16" emoji:Image.Source="🔀" />
 | 
					                <Image Width="16" Height="16" emoji:Image.Source="🔀" />
 | 
				
			||||||
            </MenuItem.Icon>
 | 
					            </MenuItem.Icon>
 | 
				
			||||||
        </MenuItem>-->
 | 
					        </MenuItem>
 | 
				
			||||||
        <MenuItem Header="{x:Static properties:Resources.Settings}" Command="{Binding Settings}">
 | 
					        <MenuItem Header="{x:Static properties:Resources.Settings}" Command="{Binding Settings}">
 | 
				
			||||||
            <MenuItem.Icon>
 | 
					            <MenuItem.Icon>
 | 
				
			||||||
                <Image Width="16" Height="16" emoji:Image.Source="🛠️" />
 | 
					                <Image Width="16" Height="16" emoji:Image.Source="🛠️" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,6 +71,18 @@ namespace unison
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ICommand Shuffle
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return new DelegateCommand
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    CommandAction = () => ((MainWindow)Application.Current.MainWindow).Shuffle_Clicked(null, null),
 | 
				
			||||||
 | 
					                    CanExecuteFunc = () => true
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public ICommand Settings
 | 
					        public ICommand Settings
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
    <ApplicationIcon>Resources\icon-full.ico</ApplicationIcon>
 | 
					    <ApplicationIcon>Resources\icon-full.ico</ApplicationIcon>
 | 
				
			||||||
    <Win32Resource></Win32Resource>
 | 
					    <Win32Resource></Win32Resource>
 | 
				
			||||||
    <StartupObject>unison.App</StartupObject>
 | 
					    <StartupObject>unison.App</StartupObject>
 | 
				
			||||||
    <Version>1.1</Version>
 | 
					    <Version>1.2</Version>
 | 
				
			||||||
    <Company />
 | 
					    <Company />
 | 
				
			||||||
    <Authors>Théo Marchal</Authors>
 | 
					    <Authors>Théo Marchal</Authors>
 | 
				
			||||||
    <PackageLicenseFile>LICENSE</PackageLicenseFile>
 | 
					    <PackageLicenseFile>LICENSE</PackageLicenseFile>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user