Damn garbage collector

This commit is contained in:
TheXamlGuy
2024-01-15 22:02:30 +00:00
parent 2a494e1b94
commit f0ef3d1604
47 changed files with 452 additions and 257 deletions
@@ -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;