Skip to content

Commit

Permalink
Merge pull request #56 from Difegue/dev
Browse files Browse the repository at this point in the history
v.2.5.4
  • Loading branch information
Difegue committed Sep 17, 2022
2 parents eb9549a + 140b799 commit 03b7fda
Show file tree
Hide file tree
Showing 33 changed files with 334 additions and 152 deletions.
38 changes: 26 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Stylophone
===========

[**Music Player Daemon**](https://www.musicpd.org/) Client for UWP.
[**Music Player Daemon**](https://www.musicpd.org/) Client for UWP and iOS/iPadOS.
Based on [MpcNET](https://github.com/Difegue/MpcNET), my own fork of the original .NET Client Library for MPD. (now on NuGet!)

<a href='//www.microsoft.com/store/apps/9NCB693428T8?cid=storebadge&ocid=badge'><img src='https://developer.microsoft.com/en-us/store/badges/images/English_get-it-from-MS.png' alt='English badge' width="142" height="52"/></a>
Expand All @@ -15,7 +15,8 @@ Based on [MpcNET](https://github.com/Difegue/MpcNET), my own fork of the origina
* Full playback control
* Playlist management (Create, Add/Remove tracks, Delete)
* Picture-in-picture mode
* Live tile
* Live tile on Windows 10
* Integration with native playback controls
* Browse library by albums, or directly by folders
* All data is pulled from your MPD Server only
* Support for both albumart and readpicture commands for maximum compatibility with your cover art library
Expand Down Expand Up @@ -53,17 +54,30 @@ You can easily contribute translations to Stylophone! To help translate, follow

## Screenshots

![Screen1](Screenshots/Screen1.jpg)
![Screen2](Screenshots/Screen2.jpg)
![Screen3](Screenshots/Screen3.jpg)
![Screen4](Screenshots/Screen4.jpg)
![Screen5](Screenshots/Screen5.jpg)
![Screen6](Screenshots/Screen6.jpg)
|Queue, UWP | Queue, iOS |
|---|---|
| ![queue_win](Screenshots/Screen1.jpg) | ![queue_ios](Screenshots/Screen5.jpg) |

## Privacy Policy
|Library, UWP | Library, iOS |
|---|---|
| ![library_win](Screenshots/Screen2.jpg) | ![library_ios](Screenshots/Screen6.jpg) |

Stylophone collects no data from your computer by default.
The Windows Store version can send anonymized error reports related to crashes of the application back to me.
|Playlist, UWP | Playlist, iOS |
|---|---|
| ![playlist_win](Screenshots/Screen3.jpg)| ![playlist_ios](Screenshots/Screen7.jpg) |

|Now Playing, UWP | Now Playing, iOS |
|---|---|
| ![nowplaying_win](Screenshots/Screen4.jpg)| ![nowplaying_ios](Screenshots/Screen8.jpg) |

|Xbox Integration | iOS Control Center Integration |
|---|---|
| ![xbox](Screenshots/ScreenXbox.jpg)| ![controlcenter](Screenshots/ScreenNowPlaying.jpg) |

If you enable Telemetry in the app's settings, the application will send detailed crash reports using App Center.
## Privacy Policy

If Telemetry is enabled in the app's settings, the application will send detailed crash reports using [App Center](https://appcenter.ms).
Those reports can contain information about your hardware. (Motherboard type, etc)

Stylophone collects no other data from your device.
The Windows Store version can send anonymized error reports related to crashes of the application back to me.
Binary file modified Screenshots/Screen3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Screenshots/Screen4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Screenshots/Screen5.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Screenshots/Screen6.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/Screen7.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/Screen8.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Screenshots/ScreenNowPlaying.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions Sources/Stylophone.Common/Services/AlbumArtService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ private async Task<SKBitmap> GetAlbumBitmap(IMpdFile f, CancellationToken token
}
catch (Exception e)
{
if (token.IsCancellationRequested)
return null;

Debug.WriteLine("Exception caught while getting albumart: " + e);
_notificationService.ShowErrorNotification(e);
return null;
Expand Down
66 changes: 51 additions & 15 deletions Sources/Stylophone.Common/Services/MPDConnectionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
using Stylophone.Common.Interfaces;
using MpcNET.Commands.Reflection;
using Stylophone.Localization.Strings;
using CommunityToolkit.Mvvm.DependencyInjection;
using Stylophone.Common.ViewModels;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter;
using System.Drawing;

namespace Stylophone.Common.Services
{
Expand All @@ -19,7 +24,7 @@ public class SongChangedEventArgs : EventArgs { public int NewSongId { get; set;
public class MPDConnectionService
{
private const int ConnectionPoolSize = 5;
public static MpdStatus BOGUS_STATUS = new MpdStatus(0, false, false, false, false, -1, -1, -1, MpdState.Unknown, -1, -1, -1, -1, TimeSpan.Zero, TimeSpan.Zero, -1, -1, -1, -1, -1, "", "");
public static MpdStatus BOGUS_STATUS = new MpdStatus(-1, false, false, false, false, -1, -1, -1, MpdState.Unknown, -1, -1, -1, -1, TimeSpan.Zero, TimeSpan.Zero, -1, -1, -1, -1, -1, "", "");

private INotificationService _notificationService;

Expand Down Expand Up @@ -70,6 +75,7 @@ public void SetServerInfo(string host, int port, string pass)
public async Task InitializeAsync(bool withRetry = false)
{
IsConnecting = true;
CurrentStatus = BOGUS_STATUS; // Reset status

if (IsConnected)
{
Expand All @@ -89,6 +95,8 @@ public async Task InitializeAsync(bool withRetry = false)
{
System.Diagnostics.Debug.WriteLine($"Error while connecting: {e.Message}");

ConnectionChanged?.Invoke(this, new EventArgs());

if (withRetry && !cancelToken.IsCancellationRequested)
{
// The RetryAttempter will call TryConnect() in five seconds.
Expand All @@ -100,7 +108,6 @@ public async Task InitializeAsync(bool withRetry = false)
}

IsConnecting = false;
ConnectionChanged?.Invoke(this, new EventArgs());
}

private void ClearResources()
Expand Down Expand Up @@ -135,7 +142,6 @@ private async Task TryConnecting(CancellationToken token)

_mpdEndpoint = new IPEndPoint(ipAddress, _port);

_idleConnection = await GetConnectionInternalAsync(token);
_statusConnection = await GetConnectionInternalAsync(token);

ConnectionPool = new ObjectPool<PooledObjectWrapper<MpcConnection>>(ConnectionPoolSize,
Expand All @@ -153,11 +159,14 @@ private async Task TryConnecting(CancellationToken token)

// Connected, initialize basic data
Version = _statusConnection.Version;

_idleConnection = await GetConnectionInternalAsync(_cancelIdle.Token);
await UpdatePlaylistsAsync();
InitializeStatusUpdater(_cancelIdle.Token);

ConnectionChanged?.Invoke(this, new EventArgs());
IsConnecting = false;
IsConnected = true;
ConnectionChanged?.Invoke(this, new EventArgs());
}

/// <summary>
Expand All @@ -176,8 +185,11 @@ public async Task<PooledObjectWrapper<MpcConnection>> GetConnectionAsync(Cancell
/// <typeparam name="T">Return type of the command</typeparam>
/// <param name="command">IMpcCommand to send</param>
/// <returns>The command results, or default value.</returns>
public async Task<T> SafelySendCommandAsync<T>(IMpcCommand<T> command)
public async Task<T> SafelySendCommandAsync<T>(IMpcCommand<T> command, bool showError = true)
{
if (!IsConnected)
return default(T);

try
{
using (var c = await GetConnectionAsync())
Expand All @@ -198,8 +210,23 @@ public async Task<T> SafelySendCommandAsync<T>(IMpcCommand<T> command)
}
catch (Exception e)
{
_notificationService.ShowInAppNotification(string.Format(Resources.ErrorSendingMPDCommand, command.GetType().Name),
e.Message, NotificationType.Error);
System.Diagnostics.Debug.WriteLine($"MPD Error: {e.Message}");

if (showError)
_notificationService.ShowInAppNotification(string.Format(Resources.ErrorSendingMPDCommand, command.GetType().Name),
e.Message, NotificationType.Error);

#if DEBUG
#else
var enableAnalytics = Ioc.Default.GetRequiredService<IApplicationStorageService>().GetValue<bool>(nameof(SettingsViewModel.EnableAnalytics), true);
if (enableAnalytics)
{
var dict = new Dictionary<string, string>();
dict.Add("command", command.Serialize());
dict.Add("exception", e.ToString());
Analytics.TrackEvent("MPDError", dict);
}
#endif
}

return default(T);
Expand All @@ -226,16 +253,21 @@ private async Task<MpcConnection> GetConnectionInternalAsync(CancellationToken t

private void InitializeStatusUpdater(CancellationToken token = default)
{
// Update status every second
_statusUpdater = new System.Timers.Timer(1000);
_statusUpdater.Elapsed += async (s, e) => await UpdateStatusAsync(_statusConnection);
_statusUpdater.Start();

// Run an idle loop in a spare thread to fire events when needed
Task.Run(async () =>
{
while (true)
{
if (_statusUpdater?.Enabled != true && _statusConnection.IsConnected)
{
// Update status every second
_statusUpdater?.Stop();
_statusUpdater?.Dispose();
_statusUpdater = new System.Timers.Timer(1000);
_statusUpdater.Elapsed += async (s, e) => await UpdateStatusAsync(_statusConnection);
_statusUpdater.Start();
}
try
{
if (token.IsCancellationRequested || _idleConnection == null || !_idleConnection.IsConnected)
Expand All @@ -250,11 +282,15 @@ private void InitializeStatusUpdater(CancellationToken token = default)
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine($"Error in Idle connection thread: {e.Message}");
await InitializeAsync(true);
if (token.IsCancellationRequested)
System.Diagnostics.Debug.WriteLine($"Idle connection cancelled.");
else
{
System.Diagnostics.Debug.WriteLine($"Error in Idle connection thread: {e.Message}");
await InitializeAsync(true);
}
}
}
}).ConfigureAwait(false);
}

Expand Down
4 changes: 4 additions & 0 deletions Sources/Stylophone.Common/Stylophone.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
<PackageReference Include="RangedObservableCollection" Version="1.0.1" />
<PackageReference Include="SkiaSharp" Version="2.88.1" />
<PackageReference Include="SkiaSharp.Views.Desktop.Common" Version="2.88.1" />
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="4.5.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Stylophone.Localization\Stylophone.Localization.csproj" />
</ItemGroup>

<ItemGroup>
<None Remove="Microsoft.AppCenter.Analytics" />
</ItemGroup>
</Project>
Loading

0 comments on commit 03b7fda

Please sign in to comment.