Files
TheXamlGuy 565c6866d8 wip
2024-02-10 20:19:01 +00:00

169 lines
5.8 KiB
C#

using Windows.Media.Control;
using Windows.Storage.Streams;
namespace Hyperbar.Widget.MediaController.Windows;
public class MediaController :
INotificationHandler<Request<MediaPrevious>>,
INotificationHandler<Request<MediaPlayPause>>,
INotificationHandler<Request<MediaNext>>,
INotificationHandler<Request<MediaInformation>>,
INotificationHandler<Request<MediaPreviousButton>>,
INotificationHandler<Request<MediaPlayPauseButton>>,
INotificationHandler<Request<MediaNextButton>>,
IDisposable
{
private readonly IDisposer disposer;
private readonly IPublisher publisher;
private readonly GlobalSystemMediaTransportControlsSession session;
private bool isNextEnabled;
private bool isPreviousEnabled;
private GlobalSystemMediaTransportControlsSessionPlaybackStatus playbackStatus;
public MediaController(IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer,
GlobalSystemMediaTransportControlsSession session)
{
this.publisher = publisher;
this.disposer = disposer;
this.session = session;
disposer.Add(this);
subscriber.Add(this);
session.MediaPropertiesChanged += OnMediaPropertiesChanged;
session.PlaybackInfoChanged += OnPlaybackInfoChanged;
}
public void Dispose()
{
GC.SuppressFinalize(this);
disposer.Dispose(this);
}
public async Task Handle(Request<MediaInformation> args,
CancellationToken cancellationToken) => await UpdateMediaInformationAsync();
public async Task Handle(Request<MediaNext> args,
CancellationToken cancellationToken)
{
await session.TrySkipNextAsync();
await UpdateMediaStateAsync();
}
public async Task Handle(Request<MediaPrevious> args, CancellationToken cancellationToken)
{
await session.TrySkipPreviousAsync();
await UpdateMediaStateAsync();
}
public async Task Handle(Request<MediaPreviousButton> args,
CancellationToken cancellationToken) => await UpdateMediaStateAsync();
public async Task Handle(Request<MediaNextButton> args,
CancellationToken cancellationToken) => await UpdateMediaStateAsync();
public async Task Handle(Request<MediaPlayPause> args,
CancellationToken cancellationToken)
{
GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo =
session.GetPlaybackInfo();
if (playbackInfo.PlaybackStatus is GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing)
{
await session.TryPauseAsync();
}
if (playbackInfo.PlaybackStatus is GlobalSystemMediaTransportControlsSessionPlaybackStatus.Paused)
{
await session.TryPlayAsync();
}
await UpdateMediaStateAsync();
}
public async Task Handle(Request<MediaPlayPauseButton> args,
CancellationToken cancellationToken) => await UpdateMediaStateAsync();
private async void OnMediaPropertiesChanged(GlobalSystemMediaTransportControlsSession sender,
MediaPropertiesChangedEventArgs args)
{
await UpdateMediaInformationAsync();
await UpdateMediaStateAsync();
}
private async void OnPlaybackInfoChanged(GlobalSystemMediaTransportControlsSession sender,
PlaybackInfoChangedEventArgs args) => await UpdateMediaStateAsync();
private async Task UpdateMediaInformationAsync()
{
try
{
GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties =
await session.TryGetMediaPropertiesAsync();
byte[]? buffer = null;
if (mediaProperties.Thumbnail is not null)
{
IRandomAccessStreamWithContentType randomAccessStream =
await mediaProperties.Thumbnail.OpenReadAsync();
var stream = randomAccessStream.AsStream();
using MemoryStream memoryStream = new();
await stream.CopyToAsync(memoryStream);
buffer = memoryStream.ToArray();
}
await publisher.PublishAsync(new Changed<MediaInformation>(new MediaInformation(mediaProperties.Title,
mediaProperties.Artist, buffer)));
}
catch
{
}
}
private async Task UpdateMediaStateAsync()
{
try
{
GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo =
session.GetPlaybackInfo();
await publisher.PublishAsync(new Changed<MediaButton<MediaPlayPauseButton>>(new
MediaButton<MediaPlayPauseButton>(playbackInfo.PlaybackStatus is
GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing ?
new MediaButtonPlaying() :
new MediaButtonPaused())));
bool isPreviousEnabled = playbackInfo.Controls.IsPreviousEnabled;
if (this.isPreviousEnabled != isPreviousEnabled)
{
await publisher.PublishAsync(new Changed<MediaButton<MediaPreviousButton>>(new
MediaButton<MediaPreviousButton>(isPreviousEnabled ? new MediaButtonEnabled() :
new MediaButtonDisabled())));
this.isPreviousEnabled = isPreviousEnabled;
}
bool isNextEnabled = playbackInfo.Controls.IsNextEnabled;
if (this.isNextEnabled != isNextEnabled)
{
await publisher.PublishAsync(new Changed<MediaButton<MediaNextButton>>(new
MediaButton<MediaNextButton>(isNextEnabled ? new MediaButtonEnabled() :
new MediaButtonDisabled())));
this.isNextEnabled = isNextEnabled;
}
}
catch
{
}
}
}