Damn garbage collector
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public record Backward : INotification;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public record Foward : INotification;
|
||||
@@ -0,0 +1,92 @@
|
||||
using Windows.Media.Control;
|
||||
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public class MediaController :
|
||||
INotificationHandler<Play>,
|
||||
INotificationHandler<Pause>,
|
||||
INotificationHandler<Request<Playback>>,
|
||||
INotificationHandler<Request<MediaInformation>>,
|
||||
IDisposable
|
||||
{
|
||||
private readonly IMediator mediator;
|
||||
private readonly IDisposer disposer;
|
||||
private readonly GlobalSystemMediaTransportControlsSession session;
|
||||
private readonly AsyncLock asyncLock = new();
|
||||
|
||||
public MediaController(IMediator mediator,
|
||||
IDisposer disposer,
|
||||
GlobalSystemMediaTransportControlsSession session)
|
||||
{
|
||||
this.mediator = mediator;
|
||||
this.disposer = disposer;
|
||||
this.session = session;
|
||||
|
||||
disposer.Add(this);
|
||||
mediator.Subscribe(this);
|
||||
|
||||
session.MediaPropertiesChanged += OnMediaPropertiesChanged;
|
||||
session.PlaybackInfoChanged += OnPlaybackInfoChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
disposer.Dispose(this);
|
||||
}
|
||||
|
||||
public async ValueTask Handle(Play notification,
|
||||
CancellationToken cancellationToken) =>
|
||||
await session.TryPlayAsync();
|
||||
|
||||
public async ValueTask Handle(Pause notification,
|
||||
CancellationToken cancellationToken) =>
|
||||
await session.TryPauseAsync();
|
||||
|
||||
public async ValueTask Handle(Request<Playback> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await mediator.PublishAsync(new Changed<Playback>(), cancellationToken);
|
||||
}
|
||||
|
||||
public async ValueTask Handle(Request<MediaInformation> _,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
using (await asyncLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties = await session.TryGetMediaPropertiesAsync();
|
||||
await mediator.PublishAsync(new Changed<MediaInformation>(new MediaInformation(mediaProperties.Title,
|
||||
mediaProperties.Subtitle)), cancellationToken);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnMediaPropertiesChanged(GlobalSystemMediaTransportControlsSession sender,
|
||||
MediaPropertiesChangedEventArgs args)
|
||||
{
|
||||
using (await asyncLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties = await session.TryGetMediaPropertiesAsync();
|
||||
await mediator.PublishAsync(new Changed<MediaInformation>(new MediaInformation(mediaProperties.Title,
|
||||
mediaProperties.Artist)));
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnPlaybackInfoChanged(GlobalSystemMediaTransportControlsSession sender,
|
||||
PlaybackInfoChangedEventArgs args)
|
||||
{
|
||||
await mediator.PublishAsync(new Changed<Playback>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Windows.Media.Control;
|
||||
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public class MediaControllerFactory(IServiceScopeFactory<MediaController> serviceScopeFactory) :
|
||||
IFactory<GlobalSystemMediaTransportControlsSession, MediaController?>
|
||||
{
|
||||
public MediaController? Create(GlobalSystemMediaTransportControlsSession value)
|
||||
{
|
||||
if (serviceScopeFactory.Create(value) is MediaController mediaController)
|
||||
{
|
||||
return mediaController;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public class MediaControllerHandler(IMediator mediator,
|
||||
IServiceScopeProvider<MediaController> scopeProvider,
|
||||
ICache<MediaController, MediaControllerViewModel> cache) :
|
||||
INotificationHandler<Created<MediaController>>
|
||||
{
|
||||
public async ValueTask Handle(Created<MediaController> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (notification.Value is MediaController mediaController)
|
||||
{
|
||||
if (scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope))
|
||||
{
|
||||
if (serviceScope is not null)
|
||||
{
|
||||
if (serviceScope.ServiceProvider.GetService<IFactory<MediaController, MediaControllerViewModel?>>()
|
||||
is IFactory<MediaController, MediaControllerViewModel?> factory)
|
||||
{
|
||||
if (factory.Create(mediaController) is MediaControllerViewModel mediaControllerViewModel)
|
||||
{
|
||||
cache.Add(mediaController, mediaControllerViewModel);
|
||||
await mediator.PublishAsync(new Created<MediaControllerViewModel>(mediaControllerViewModel),
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Diagnostics;
|
||||
using Windows.Media.Control;
|
||||
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
public class MediaControllerManager(IMediator mediator,
|
||||
IFactory<GlobalSystemMediaTransportControlsSession, MediaController> factory,
|
||||
IDispatcher dispatcher,
|
||||
IDisposer disposer) :
|
||||
IInitializer
|
||||
{
|
||||
private readonly AsyncLock asyncLock = new();
|
||||
private readonly List<KeyValuePair<GlobalSystemMediaTransportControlsSession, MediaController>> cache = [];
|
||||
private GlobalSystemMediaTransportControlsSessionManager? mediaTransportControlsSessionManager;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
mediaTransportControlsSessionManager = await GlobalSystemMediaTransportControlsSessionManager.RequestAsync();
|
||||
mediaTransportControlsSessionManager.SessionsChanged += OnSessionsChanged;
|
||||
|
||||
IReadOnlyList<GlobalSystemMediaTransportControlsSession> sessions =
|
||||
mediaTransportControlsSessionManager.GetSessions();
|
||||
|
||||
foreach (GlobalSystemMediaTransportControlsSession session in sessions)
|
||||
{
|
||||
await InitializeSessionAsync(session);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InitializeSessionAsync(GlobalSystemMediaTransportControlsSession session)
|
||||
{
|
||||
if (factory.Create(session) is MediaController mediaController)
|
||||
{
|
||||
await mediator.PublishAsync(new Created<MediaController>(mediaController));
|
||||
Debug.WriteLine("Added " + session.SourceAppUserModelId + " " + session);
|
||||
|
||||
cache.Add(new KeyValuePair<GlobalSystemMediaTransportControlsSession, MediaController>(session, mediaController));
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnSessionsChanged(GlobalSystemMediaTransportControlsSessionManager sender,
|
||||
SessionsChangedEventArgs args)
|
||||
{
|
||||
IReadOnlyList<GlobalSystemMediaTransportControlsSession> sessions =
|
||||
sender.GetSessions();
|
||||
|
||||
using (await asyncLock)
|
||||
{
|
||||
foreach (KeyValuePair<GlobalSystemMediaTransportControlsSession, MediaController> session in
|
||||
cache.ToList())
|
||||
{
|
||||
if (!sessions.Any(x => x.SourceAppUserModelId == session.Key.SourceAppUserModelId))
|
||||
{
|
||||
await dispatcher.InvokeAsync(() => disposer.Dispose(session.Value));
|
||||
cache.Remove(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (await asyncLock)
|
||||
{
|
||||
foreach (GlobalSystemMediaTransportControlsSession session in sessions)
|
||||
{
|
||||
if (!cache.Any(x => x.Key.SourceAppUserModelId == session.SourceAppUserModelId))
|
||||
{
|
||||
await InitializeSessionAsync(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public class MediaControllerViewModelFactory(IServiceFactory service) :
|
||||
IFactory<MediaController, MediaControllerViewModel?>
|
||||
{
|
||||
public MediaControllerViewModel? Create(MediaController value)
|
||||
{
|
||||
if (service.Create<MediaControllerViewModel>()
|
||||
is MediaControllerViewModel widgetComponentViewModel)
|
||||
{
|
||||
return widgetComponentViewModel;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Windows.Media.Control;
|
||||
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public class MediaControllerWidgetProvider :
|
||||
IWidgetProvider
|
||||
{
|
||||
public void Create(HostBuilderContext comtext, IServiceCollection services) =>
|
||||
services.AddWidgetTemplate<MediaControllerWidgetViewModel, MediaControllerWidgetView>()
|
||||
.AddSingleton<IInitializer, MediaControllerManager>()
|
||||
.AddTransient<IServiceScopeFactory<MediaController>, ServiceScopeFactory<MediaController>>()
|
||||
.AddTransient<IServiceScopeProvider<MediaController>, ServiceScopeProvider<MediaController>>()
|
||||
.AddCache<MediaController, IServiceScope>()
|
||||
.AddTransient<IFactory<GlobalSystemMediaTransportControlsSession, MediaController?>, MediaControllerFactory>()
|
||||
.AddHandler<MediaControllerHandler>()
|
||||
.AddTransient<IFactory<MediaController, MediaControllerViewModel?>, MediaControllerViewModelFactory>()
|
||||
.AddCache<MediaController, MediaControllerViewModel>()
|
||||
.AddContentTemplate<MediaControllerViewModel, MediaControllerView>()
|
||||
.AddContentTemplate<MediaInformationViewModel, MediaInformationView>()
|
||||
.AddContentTemplate<MediaButtonViewModel, MediaButtonView>();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public record MediaInformation(string Title, string Description);
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public record Pause : INotification;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public record Play : INotification;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public record Playback : INotification;
|
||||
Reference in New Issue
Block a user