More resilient handle of disconnection and reconnection
This commit is contained in:
parent
3b59e51368
commit
0ab1afc2f8
@ -65,12 +65,10 @@ namespace unison
|
||||
private MpcConnection _connection;
|
||||
private MpcConnection _commandConnection;
|
||||
private IPEndPoint _mpdEndpoint;
|
||||
private CancellationTokenSource cancelToken;
|
||||
private CancellationTokenSource _cancelToken;
|
||||
|
||||
public MPDHandler()
|
||||
{
|
||||
cancelToken = new CancellationTokenSource();
|
||||
|
||||
Initialize(null, null);
|
||||
|
||||
_stats = new Statistics();
|
||||
@ -161,7 +159,7 @@ namespace unison
|
||||
IMpdMessage<T> response = await _commandConnection.SendAsync(command);
|
||||
if (!response.IsResponseValid)
|
||||
{
|
||||
var mpdError = response.Response?.Result?.MpdError;
|
||||
string mpdError = response.Response?.Result?.MpdError;
|
||||
if (mpdError != null && mpdError != "")
|
||||
throw new Exception(mpdError);
|
||||
else
|
||||
@ -186,7 +184,9 @@ namespace unison
|
||||
|
||||
public async void Connect()
|
||||
{
|
||||
CancellationToken token = cancelToken.Token;
|
||||
_cancelToken = new CancellationTokenSource();
|
||||
CancellationToken token = _cancelToken.Token;
|
||||
|
||||
try
|
||||
{
|
||||
_connection = await ConnectInternal(token);
|
||||
@ -194,8 +194,10 @@ namespace unison
|
||||
}
|
||||
catch (MpcNET.Exceptions.MpcConnectException e)
|
||||
{
|
||||
_connected = false;
|
||||
_invalidIp = true;
|
||||
Trace.WriteLine($"Error in connect: {e.Message}");
|
||||
ConnectionChanged?.Invoke(this, EventArgs.Empty);
|
||||
return;
|
||||
}
|
||||
if (_connection != null && _commandConnection != null)
|
||||
@ -210,6 +212,7 @@ namespace unison
|
||||
}
|
||||
else
|
||||
{
|
||||
_connected = false;
|
||||
ConnectionChanged?.Invoke(this, EventArgs.Empty);
|
||||
return;
|
||||
}
|
||||
@ -261,12 +264,16 @@ namespace unison
|
||||
return connection;
|
||||
}
|
||||
|
||||
private void Disconnected()
|
||||
public void Disconnected()
|
||||
{
|
||||
_connected = false;
|
||||
_connection = null;
|
||||
_commandConnection = null;
|
||||
ConnectionChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
if (_connection != null)
|
||||
_connection = null;
|
||||
|
||||
if (_commandConnection != null)
|
||||
_commandConnection = null;
|
||||
}
|
||||
|
||||
private void Loop(CancellationToken token)
|
||||
@ -277,27 +284,29 @@ namespace unison
|
||||
{
|
||||
try
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
if (token.IsCancellationRequested || _connection == null)
|
||||
break;
|
||||
|
||||
var idleChanges = await _connection.SendAsync(new IdleCommand("stored_playlist playlist player mixer output options"));
|
||||
IMpdMessage<string> idleChanges = await _connection.SendAsync(new IdleCommand("stored_playlist playlist player mixer output options update"));
|
||||
|
||||
if (idleChanges.IsResponseValid)
|
||||
await HandleIdleResponseAsync(idleChanges.Response.Content);
|
||||
else
|
||||
{
|
||||
Trace.WriteLine($"Error in Idle connection thread: {idleChanges.Response?.Content}");
|
||||
//throw new Exception(idleChanges.Response?.Content);
|
||||
throw new Exception(idleChanges.Response?.Content);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Trace.WriteLine($"Error in Idle connection thread: {e.Message}");
|
||||
Disconnected();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
}, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task HandleIdleResponseAsync(string subsystems)
|
||||
@ -383,12 +392,12 @@ namespace unison
|
||||
if (_connection == null)
|
||||
return;
|
||||
|
||||
var albumReq = await _connection.SendAsync(new AlbumArtCommand(path, currentSize));
|
||||
IMpdMessage<MpdBinaryData> albumReq = await _connection.SendAsync(new AlbumArtCommand(path, currentSize));
|
||||
if (!albumReq.IsResponseValid)
|
||||
break;
|
||||
|
||||
var response = albumReq.Response.Content;
|
||||
if (response.Binary == 0)
|
||||
MpdBinaryData response = albumReq.Response.Content;
|
||||
if (response == null || response.Binary == 0)
|
||||
break;
|
||||
|
||||
totalBinarySize = response.Size;
|
||||
@ -512,7 +521,6 @@ namespace unison
|
||||
|
||||
public void AddSong(string Uri)
|
||||
{
|
||||
Debug.WriteLine("AddCommand path: " + Uri);
|
||||
SendCommand(new AddCommand(Uri));
|
||||
}
|
||||
|
||||
@ -526,20 +534,23 @@ namespace unison
|
||||
{
|
||||
Dictionary<string, string> response = await SafelySendCommandAsync(new StatsCommand());
|
||||
|
||||
_stats.Songs = int.Parse(response["songs"]);
|
||||
_stats.Albums = int.Parse(response["albums"]);
|
||||
_stats.Artists = int.Parse(response["artists"]);
|
||||
if (response != null)
|
||||
{
|
||||
_stats.Songs = int.Parse(response["songs"]);
|
||||
_stats.Albums = int.Parse(response["albums"]);
|
||||
_stats.Artists = int.Parse(response["artists"]);
|
||||
|
||||
TimeSpan time;
|
||||
time = TimeSpan.FromSeconds(int.Parse(response["uptime"]));
|
||||
_stats.Uptime = time.ToString(@"dd\:hh\:mm\:ss");
|
||||
time = TimeSpan.FromSeconds(int.Parse(response["db_playtime"]));
|
||||
_stats.TotalPlaytime = time.ToString(@"dd\:hh\:mm\:ss");
|
||||
time = TimeSpan.FromSeconds(int.Parse(response["playtime"]));
|
||||
_stats.TotalTimePlayed = time.ToString(@"dd\:hh\:mm\:ss");
|
||||
TimeSpan time;
|
||||
time = TimeSpan.FromSeconds(int.Parse(response["uptime"]));
|
||||
_stats.Uptime = time.ToString(@"dd\:hh\:mm\:ss");
|
||||
time = TimeSpan.FromSeconds(int.Parse(response["db_playtime"]));
|
||||
_stats.TotalPlaytime = time.ToString(@"dd\:hh\:mm\:ss");
|
||||
time = TimeSpan.FromSeconds(int.Parse(response["playtime"]));
|
||||
_stats.TotalTimePlayed = time.ToString(@"dd\:hh\:mm\:ss");
|
||||
|
||||
DateTime date = new DateTime(1970, 1, 1).AddSeconds(int.Parse(response["db_update"])).ToLocalTime();
|
||||
_stats.DatabaseUpdate = date.ToString("dd/MM/yyyy @ HH:mm");
|
||||
DateTime date = new DateTime(1970, 1, 1).AddSeconds(int.Parse(response["db_update"])).ToLocalTime();
|
||||
_stats.DatabaseUpdate = date.ToString("dd/MM/yyyy @ HH:mm");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -33,12 +33,12 @@
|
||||
<StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Text="{x:Static properties:Resources.Settings_Host}" TextWrapping="Wrap" Margin="5,0,0,0"/>
|
||||
<TextBox x:Name="MpdHost" KeyDown="ConnectHandler" TextWrapping="Wrap" Width="250" Margin="10,2,0,0"/>
|
||||
<TextBox x:Name="MpdHost" KeyDown="ConnectHandler" TextChanged="MpdConnectTextBox" TextWrapping="Wrap" Width="250" Margin="10,2,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,5,0,0">
|
||||
<TextBlock Text="{x:Static properties:Resources.Settings_Port}" TextWrapping="Wrap" Margin="5,0,0,0"/>
|
||||
<TextBox x:Name="MpdPort" KeyDown="ConnectHandler" MaxLength="5" PreviewTextInput="NumberValidationTextBox" TextWrapping="Wrap" Width="250" Margin="10,2,0,0"/>
|
||||
<TextBox x:Name="MpdPort" KeyDown="ConnectHandler" PreviewTextInput="NumberValidationTextBox" MaxLength="5" TextWrapping="Wrap" Width="250" Margin="10,2,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!--<StackPanel Margin="0,5,0,0">
|
||||
|
@ -37,6 +37,7 @@ namespace unison
|
||||
|
||||
HotkeyHandler _hotkeys = (HotkeyHandler)Application.Current.Properties["hotkeys"];
|
||||
|
||||
|
||||
public Settings()
|
||||
{
|
||||
InitHwnd();
|
||||
@ -62,6 +63,134 @@ namespace unison
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public void UpdateConnectionStatus()
|
||||
{
|
||||
MPDHandler mpd = (MPDHandler)Application.Current.Properties["mpd"];
|
||||
if (mpd.IsConnected())
|
||||
{
|
||||
ConnectionStatus.Text = $"{unison.Resources.Resources.Settings_ConnectionStatusConnected} {mpd.GetVersion()}.";
|
||||
ConnectButton.IsEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConnectionStatus.Text = unison.Resources.Resources.Settings_ConnectionStatusOffline;
|
||||
ConnectButton.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
|
||||
{
|
||||
Regex regex = new Regex("[^0-9]+");
|
||||
e.Handled = regex.IsMatch(e.Text);
|
||||
}
|
||||
|
||||
private void MpdConnectTextBox(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
TextBox textBox = (TextBox)sender;
|
||||
|
||||
if (textBox.Text == Properties.Settings.Default.mpd_host)
|
||||
ConnectButton.IsEnabled = false;
|
||||
else
|
||||
ConnectButton.IsEnabled = true;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||
{
|
||||
ProcessStartInfo psi = new(e.Uri.AbsoluteUri);
|
||||
psi.UseShellExecute = true;
|
||||
Process.Start(psi);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void MPDConnect_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!ConnectButton.IsEnabled)
|
||||
return;
|
||||
|
||||
SaveSettings();
|
||||
|
||||
MPDHandler mpd = (MPDHandler)Application.Current.Properties["mpd"];
|
||||
if (mpd.IsConnected())
|
||||
mpd = new MPDHandler();
|
||||
|
||||
ConnectButton.IsEnabled = false;
|
||||
ConnectionStatus.Text = unison.Resources.Resources.Settings_ConnectionStatusConnecting;
|
||||
|
||||
System.Threading.Tasks.Task.Run(() => { mpd.Connect(); });
|
||||
}
|
||||
|
||||
private void SnapcastReset_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SnapcastPath.Text = (string)Application.Current.FindResource("snapcastPath");
|
||||
SnapcastPort.Text = (string)Application.Current.FindResource("snapcastPort");
|
||||
}
|
||||
|
||||
public void UpdateStats()
|
||||
{
|
||||
MPDHandler mpd = (MPDHandler)Application.Current.Properties["mpd"];
|
||||
StatSong.Text = mpd.GetStats().Songs.ToString();
|
||||
StatAlbum.Text = mpd.GetStats().Albums.ToString();
|
||||
StatArtist.Text = mpd.GetStats().Artists.ToString();
|
||||
StatTotalPlaytime.Text = mpd.GetStats().TotalPlaytime.ToString();
|
||||
StatUptime.Text = mpd.GetStats().Uptime.ToString();
|
||||
StatTotalTimePlayed.Text = mpd.GetStats().TotalTimePlayed.ToString();
|
||||
StatDatabaseUpdate.Text = mpd.GetStats().DatabaseUpdate.ToString();
|
||||
}
|
||||
|
||||
private void ConnectHandler(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Return)
|
||||
MPDConnect_Clicked(null, null);
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
SaveSettings();
|
||||
WindowState = WindowState.Minimized;
|
||||
Hide();
|
||||
}
|
||||
|
||||
public void InitHwnd()
|
||||
{
|
||||
WindowInteropHelper helper = new(this);
|
||||
helper.EnsureHandle();
|
||||
}
|
||||
|
||||
public void SaveSettings()
|
||||
{
|
||||
Properties.Settings.Default.mpd_host = MpdHost.Text;
|
||||
Properties.Settings.Default.mpd_port = int.Parse(MpdPort.Text, CultureInfo.InvariantCulture);
|
||||
//Properties.Settings.Default.mpd_password = MpdPassword.Text;
|
||||
Properties.Settings.Default.snapcast_startup = (bool)SnapcastStartup.IsChecked;
|
||||
Properties.Settings.Default.snapcast_window = (bool)SnapcastWindow.IsChecked;
|
||||
Properties.Settings.Default.snapcast_path = SnapcastPath.Text;
|
||||
Properties.Settings.Default.snapcast_port = int.Parse(SnapcastPort.Text, CultureInfo.InvariantCulture);
|
||||
Properties.Settings.Default.volume_offset = int.Parse(VolumeOffset.Text, CultureInfo.InvariantCulture);
|
||||
|
||||
Properties.Settings.Default.nextTrack_mod = GetMod(Shortcut_NextTrack);
|
||||
Properties.Settings.Default.nextTrack_vk = GetVk(Shortcut_NextTrack);
|
||||
Properties.Settings.Default.previousTrack_mod = GetMod(Shortcut_PreviousTrack);
|
||||
Properties.Settings.Default.previousTrack_vk = GetVk(Shortcut_PreviousTrack);
|
||||
Properties.Settings.Default.playPause_mod = GetMod(Shortcut_PlayPause);
|
||||
Properties.Settings.Default.playPause_vk = GetVk(Shortcut_PlayPause);
|
||||
Properties.Settings.Default.volumeUp_mod = GetMod(Shortcut_VolumeUp);
|
||||
Properties.Settings.Default.volumeUp_vk = GetVk(Shortcut_VolumeUp);
|
||||
Properties.Settings.Default.volumeDown_mod = GetMod(Shortcut_VolumeDown);
|
||||
Properties.Settings.Default.volumeDown_vk = GetVk(Shortcut_VolumeDown);
|
||||
Properties.Settings.Default.volumeMute_mod = GetMod(Shortcut_VolumeMute);
|
||||
Properties.Settings.Default.volumeMute_vk = GetVk(Shortcut_VolumeMute);
|
||||
Properties.Settings.Default.showWindow_mod = GetMod(Shortcut_ShowWindow);
|
||||
Properties.Settings.Default.showWindow_vk = GetVk(Shortcut_ShowWindow);
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
|
||||
// Hotkeys
|
||||
|
||||
void InitializeShortcuts()
|
||||
{
|
||||
System.Collections.Generic.IEnumerable<StackPanel> stackPanelCollection = RebindKeyWrapper.Children.OfType<StackPanel>();
|
||||
@ -108,55 +237,6 @@ namespace unison
|
||||
}
|
||||
}
|
||||
|
||||
private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
|
||||
{
|
||||
Regex regex = new Regex("[^0-9]+");
|
||||
e.Handled = regex.IsMatch(e.Text);
|
||||
}
|
||||
|
||||
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||
{
|
||||
ProcessStartInfo psi = new(e.Uri.AbsoluteUri);
|
||||
psi.UseShellExecute = true;
|
||||
Process.Start(psi);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
public void UpdateConnectionStatus()
|
||||
{
|
||||
MPDHandler mpd = (MPDHandler)Application.Current.Properties["mpd"];
|
||||
if (mpd.IsConnected())
|
||||
ConnectionStatus.Text = $"{unison.Resources.Resources.Settings_ConnectionStatusConnected} {mpd.GetVersion()}.";
|
||||
else
|
||||
ConnectionStatus.Text = unison.Resources.Resources.Settings_ConnectionStatusOffline;
|
||||
}
|
||||
|
||||
private void MPDConnect_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveSettings();
|
||||
ConnectionStatus.Text = unison.Resources.Resources.Settings_ConnectionStatusConnecting;
|
||||
MPDHandler mpd = (MPDHandler)Application.Current.Properties["mpd"];
|
||||
mpd.Connect();
|
||||
}
|
||||
|
||||
private void SnapcastReset_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SnapcastPath.Text = (string)Application.Current.FindResource("snapcastPath");
|
||||
SnapcastPort.Text = (string)Application.Current.FindResource("snapcastPort");
|
||||
}
|
||||
|
||||
public void UpdateStats()
|
||||
{
|
||||
MPDHandler mpd = (MPDHandler)Application.Current.Properties["mpd"];
|
||||
StatSong.Text = mpd.GetStats().Songs.ToString();
|
||||
StatAlbum.Text = mpd.GetStats().Albums.ToString();
|
||||
StatArtist.Text = mpd.GetStats().Artists.ToString();
|
||||
StatTotalPlaytime.Text = mpd.GetStats().TotalPlaytime.ToString();
|
||||
StatUptime.Text = mpd.GetStats().Uptime.ToString();
|
||||
StatTotalTimePlayed.Text = mpd.GetStats().TotalTimePlayed.ToString();
|
||||
StatDatabaseUpdate.Text = mpd.GetStats().DatabaseUpdate.ToString();
|
||||
}
|
||||
|
||||
private void HotkeyChanged()
|
||||
{
|
||||
_hotkeys.RemoveHotkeys();
|
||||
@ -307,54 +387,5 @@ namespace unison
|
||||
TextBlock textBlock = (TextBlock)button.Content;
|
||||
return (uint)(HotkeyHandler.VK)System.Enum.Parse(typeof(HotkeyHandler.VK), textBlock.Text, true);
|
||||
}
|
||||
|
||||
public void SaveSettings()
|
||||
{
|
||||
Properties.Settings.Default.mpd_host = MpdHost.Text;
|
||||
Properties.Settings.Default.mpd_port = int.Parse(MpdPort.Text, CultureInfo.InvariantCulture);
|
||||
//Properties.Settings.Default.mpd_password = MpdPassword.Text;
|
||||
Properties.Settings.Default.snapcast_startup = (bool)SnapcastStartup.IsChecked;
|
||||
Properties.Settings.Default.snapcast_window = (bool)SnapcastWindow.IsChecked;
|
||||
Properties.Settings.Default.snapcast_path = SnapcastPath.Text;
|
||||
Properties.Settings.Default.snapcast_port = int.Parse(SnapcastPort.Text, CultureInfo.InvariantCulture);
|
||||
Properties.Settings.Default.volume_offset = int.Parse(VolumeOffset.Text, CultureInfo.InvariantCulture);
|
||||
|
||||
Properties.Settings.Default.nextTrack_mod = GetMod(Shortcut_NextTrack);
|
||||
Properties.Settings.Default.nextTrack_vk = GetVk(Shortcut_NextTrack);
|
||||
Properties.Settings.Default.previousTrack_mod = GetMod(Shortcut_PreviousTrack);
|
||||
Properties.Settings.Default.previousTrack_vk = GetVk(Shortcut_PreviousTrack);
|
||||
Properties.Settings.Default.playPause_mod = GetMod(Shortcut_PlayPause);
|
||||
Properties.Settings.Default.playPause_vk = GetVk(Shortcut_PlayPause);
|
||||
Properties.Settings.Default.volumeUp_mod = GetMod(Shortcut_VolumeUp);
|
||||
Properties.Settings.Default.volumeUp_vk = GetVk(Shortcut_VolumeUp);
|
||||
Properties.Settings.Default.volumeDown_mod = GetMod(Shortcut_VolumeDown);
|
||||
Properties.Settings.Default.volumeDown_vk = GetVk(Shortcut_VolumeDown);
|
||||
Properties.Settings.Default.volumeMute_mod = GetMod(Shortcut_VolumeMute);
|
||||
Properties.Settings.Default.volumeMute_vk = GetVk(Shortcut_VolumeMute);
|
||||
Properties.Settings.Default.showWindow_mod = GetMod(Shortcut_ShowWindow);
|
||||
Properties.Settings.Default.showWindow_vk = GetVk(Shortcut_ShowWindow);
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
private void ConnectHandler(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Return)
|
||||
MPDConnect_Clicked(null, null);
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
SaveSettings();
|
||||
WindowState = WindowState.Minimized;
|
||||
Hide();
|
||||
}
|
||||
|
||||
public void InitHwnd()
|
||||
{
|
||||
WindowInteropHelper helper = new(this);
|
||||
helper.EnsureHandle();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user