Skip to content

Commit

Permalink
refactor media watch code
Browse files Browse the repository at this point in the history
revert button detections to older, non-focused session behavior
  • Loading branch information
Aytackydln committed Feb 23, 2023
1 parent 0f6254d commit cf74ec8
Show file tree
Hide file tree
Showing 8 changed files with 298 additions and 161 deletions.
1 change: 1 addition & 0 deletions Artemis.MediaInfo/Artemis.MediaInfo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<Platforms>x64</Platforms>
<PlatformTarget>x64</PlatformTarget>
<IncludeBuildOutput>false</IncludeBuildOutput>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
Expand Down
12 changes: 0 additions & 12 deletions Artemis.MediaInfo/DataModels/MediaInfoDataModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Collections.Generic;
using Windows.Media;
using Windows.Media.Control;
using Artemis.Core;
using Artemis.Core.ColorScience;
using Artemis.Core.Modules;
using WindowsMediaController;
Expand Down Expand Up @@ -36,16 +34,6 @@ public class MediaInfoDataModel : DataModel

public string SessionName { get; set; }

public DataModelEvent<MediaChangedEventArgs> MediaChanged { get; } = new();
public ISet<MediaManager.MediaSession> MediaSessions { get; set; }
public ISet<MediaManager.MediaSession> ArtMediaSessions { get; set; }
}

public class MediaChangedEventArgs : DataModelEventArgs
{
public string SessionId { get; set; }
public string Title { get; set; }
public string Artist { get; set; }
public MediaPlaybackType MediaType { get; set; }
public bool HasArt { get; set; }
}
195 changes: 63 additions & 132 deletions Artemis.MediaInfo/MediaInfoModule.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using Artemis.Core;
using System;
using Artemis.Core;
using Artemis.Core.Modules;
using System.Collections.Generic;
using System.Linq;
using Artemis.MediaInfo.DataModels;
using WindowsMediaController;
using Windows.Media;
using Windows.Media.Control;
using Artemis.Core.Properties;
using Artemis.MediaInfo.MediaWatch;
using static WindowsMediaController.MediaManager;
using static Artemis.MediaInfo.MediaInfoHelper;

Expand All @@ -15,186 +14,118 @@ namespace Artemis.MediaInfo;
[PluginFeature(Name = "MediaInfo")]
public class MediaInfoModule : Module<MediaInfoDataModel>
{
private MediaManager _mediaManager;
private static readonly bool FocusedUpdate = false; //because window's focus events don't work well for everyone :/

public override List<IModuleActivationRequirement> ActivationRequirements { get; } = new();

private readonly ISet<MediaSession> _mediaSessions = new HashSet<MediaSession>(new MediaSessionComparer());
private readonly ISet<MediaSession> _albumArtSessions = new HashSet<MediaSession>(new MediaSessionComparer());

[CanBeNull]
private MediaSession _currentSession;
private readonly MediaWatcher _mediaWatcher = new();

public override void Enable()
{
_mediaSessions.Clear();
_albumArtSessions.Clear();

_mediaManager = new MediaManager();
_mediaManager.OnAnySessionOpened += MediaManager_OnSessionOpened;
_mediaManager.OnAnySessionClosed += MediaManager_OnAnySessionClosed;
_mediaManager.OnFocusedSessionChanged += MediaManagerOnOnFocusedSessionChanged;
_mediaManager.OnAnyMediaPropertyChanged += MediaManager_OnAnyMediaPropertyChanged; //listen for media arts

_mediaManager.Start();

foreach (var (_, mediaSession) in _mediaManager.CurrentMediaSessions)
{
_mediaSessions.Add(mediaSession);
}
}

private void MediaManagerOnOnFocusedSessionChanged(MediaSession mediaSession)
{
if (_currentSession != null)
{
_currentSession.OnPlaybackStateChanged -= MediaSession_OnPlaybackStateChanged;
}
_mediaSessions.Add(mediaSession);
_currentSession = mediaSession;
_mediaManager.OnAnyPlaybackStateChanged += MediaSession_OnPlaybackStateChanged;
MediaSession_OnPlaybackStateChanged(mediaSession, mediaSession.ControlSession.GetPlaybackInfo());
DataModel.MediaSessions = _mediaWatcher.MediaSessions;
DataModel.ArtMediaSessions = _mediaWatcher.AlbumArtSessions;
}

public override void Disable()
{
_albumArtSessions.Clear();
_mediaSessions.Clear();

if (_currentSession != null)
{
_currentSession.OnPlaybackStateChanged -= MediaSession_OnPlaybackStateChanged;
}

_mediaManager.OnAnyMediaPropertyChanged -= MediaManager_OnAnyMediaPropertyChanged;
_mediaManager.OnFocusedSessionChanged -= MediaManagerOnOnFocusedSessionChanged;
_mediaManager.OnAnySessionClosed -= MediaManager_OnAnySessionClosed;
_mediaManager.OnAnySessionOpened -= MediaManager_OnSessionOpened;
_mediaManager.Dispose();
_mediaManager = null;
//unused
}

public override void Update(double deltaTime) {}

public override void ModuleActivated(bool isOverride)
{
DataModel.MediaSessions = _mediaSessions;
DataModel.ArtMediaSessions = _albumArtSessions;
_mediaWatcher.FocusedMediaChanged += MediaWatcherOnFocusedMediaChanged;
_mediaWatcher.ArtStateChanged += MediaWatcherOnArtStateChanged;
_mediaWatcher.StartListening().Wait();
}
public override void ModuleDeactivated(bool isOverride) {
//unused
}

private void MediaManager_OnSessionOpened(MediaSession mediaSession)
{
DataModel.HasMedia = true;
_mediaSessions.Add(mediaSession);
_mediaWatcher.StopListening();
_mediaWatcher.FocusedMediaChanged -= MediaWatcherOnFocusedMediaChanged;
_mediaWatcher.ArtStateChanged -= MediaWatcherOnArtStateChanged;
}

private void MediaManager_OnAnySessionClosed(MediaSession mediaSession)
private void MediaWatcherOnFocusedMediaChanged(object? sender, FocusedMediaChangedEventArgs e)
{
_currentSession.OnPlaybackStateChanged -= MediaSession_OnPlaybackStateChanged;
_mediaSessions.Remove(mediaSession);
_albumArtSessions.Remove(mediaSession);
if (_currentSession.Id == mediaSession.Id)
{
_currentSession = _mediaManager.GetFocusedSession();
}
UpdateButtons(_currentSession);
UpdateArtState();
var mediaSession = e.MediaSession;
UpdateButtons(mediaSession, e.PlaybackInfo);
}

private async void MediaManager_OnAnyMediaPropertyChanged(MediaSession mediaSession,
GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties)
private void UpdateButtons(MediaSession? mediaSession,
GlobalSystemMediaTransportControlsSessionPlaybackInfo? playbackInfo)
{
if (mediaSession.ControlSession == null)
if (mediaSession == null)
{
MediaManager_OnAnySessionClosed(mediaSession);
DataModel.HasMedia = false;
DataModel.HasNextMedia = false;
DataModel.HasPreviousMedia = false;
DataModel.MediaPlaying = false;
DataModel.MediaState = GlobalSystemMediaTransportControlsSessionPlaybackStatus.Closed;
DataModel.SessionName = "";
return;
}
try
{
if (mediaProperties.Thumbnail is null)
{
_albumArtSessions.Remove(mediaSession);
return;
}
DataModel.HasMedia = true;

DataModel.ArtColors = await ReadMediaColors(mediaProperties);
_albumArtSessions.Add(mediaSession);
}
catch
if (FocusedUpdate)
{
_albumArtSessions.Remove(mediaSession);
FocusedModelUpdate(mediaSession, playbackInfo);
}
finally
else
{
UpdateArtState();
DataModel.MediaChanged.Trigger(new MediaChangedEventArgs
{
SessionId = mediaSession.Id,
Title = mediaProperties.Title,
Artist = mediaProperties.Artist,
MediaType = mediaProperties.PlaybackType ?? MediaPlaybackType.Unknown,
HasArt = mediaProperties.Thumbnail is not null
});
AnySessionModelUpdate(mediaSession, playbackInfo);
}
}

private void MediaSession_OnPlaybackStateChanged(MediaSession mediaSession,
GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)
private void FocusedModelUpdate(MediaSession mediaSession,
GlobalSystemMediaTransportControlsSessionPlaybackInfo? playbackInfo)
{
if (playbackInfo == null || playbackInfo.PlaybackStatus == GlobalSystemMediaTransportControlsSessionPlaybackStatus.Closed)
if (playbackInfo == null)
{
MediaManager_OnAnySessionClosed(mediaSession);
return;
playbackInfo = mediaSession.ControlSession.GetPlaybackInfo();
}

_mediaSessions.Add(mediaSession); // Some app like chrome use same id for different tabs.
// So, closing the tab may cause all chroma sessions to be removed. This re-adds them

UpdateButtons(mediaSession);
UpdateArtState();
}

private void UpdateButtons(MediaSession mediaSession)
{
if (mediaSession == null)
{
DataModel.HasMedia = false;
DataModel.HasNextMedia = false;
DataModel.HasPreviousMedia = false;
DataModel.MediaPlaying = false;
DataModel.MediaState = GlobalSystemMediaTransportControlsSessionPlaybackStatus.Closed;
DataModel.SessionName = "";
return;
}
DataModel.HasMedia = true;

var playbackInfo = mediaSession.ControlSession.GetPlaybackInfo();
var playbackControls = playbackInfo.Controls;

DataModel.HasNextMedia = playbackControls.IsNextEnabled;
DataModel.HasPreviousMedia = playbackControls.IsPreviousEnabled;
DataModel.MediaPlaying = playbackInfo.PlaybackStatus == GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing;
DataModel.MediaPlaying =
playbackInfo.PlaybackStatus == GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing;
DataModel.MediaState = playbackInfo.PlaybackStatus;
DataModel.SessionName = mediaSession.Id;
}

private void UpdateArtState()
private void AnySessionModelUpdate(MediaSession focusedMediaSession,
GlobalSystemMediaTransportControlsSessionPlaybackInfo? playbackInfo)
{
DataModel.HasArt = _albumArtSessions.Any();
DataModel.HasPreviousMedia = false;
DataModel.MediaPlaying = false;
DataModel.HasNextMedia = false;
DataModel.MediaState = playbackInfo?.PlaybackStatus ?? GlobalSystemMediaTransportControlsSessionPlaybackStatus.Closed;
DataModel.SessionName = focusedMediaSession.Id;
foreach (var mediaSession in _mediaWatcher.MediaSessions)
{
var controls = mediaSession.ControlSession.GetPlaybackInfo().Controls;
DataModel.HasPreviousMedia |= controls.IsPreviousEnabled;
DataModel.MediaPlaying |= !controls.IsPlayEnabled;
DataModel.HasNextMedia |= controls.IsNextEnabled;
}
}

private sealed class MediaSessionComparer : IEqualityComparer<MediaSession>
private async void MediaWatcherOnArtStateChanged(object? sender, ArtStateChangedEventArgs e)
{
public bool Equals(MediaSession x, MediaSession y)
if (e.Thumbnail != null)
{
return x?.Id == y?.Id;
DataModel.ArtColors = await ReadMediaColors(e.Thumbnail);
}

public int GetHashCode(MediaSession obj)
else
{
return obj.Id.GetHashCode();
var mediaSession = _mediaWatcher.AlbumArtSessions.LastOrDefault();
if (mediaSession!= null)
{
var mediaProperties = mediaSession.ControlSession.TryGetMediaPropertiesAsync().GetAwaiter().GetResult();
DataModel.ArtColors = await ReadMediaColors(mediaProperties);
}
}
DataModel.HasArt = _mediaWatcher.AlbumArtSessions.Any();
}
}
41 changes: 41 additions & 0 deletions Artemis.MediaInfo/MediaWatch/MediaEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using Windows.Media.Control;
using Windows.Storage.Streams;
using WindowsMediaController;

namespace Artemis.MediaInfo.MediaWatch;

public class MediaAddedEventArgs : EventArgs
{
public MediaManager.MediaSession MediaSession { get; }

public MediaAddedEventArgs(MediaManager.MediaSession mediaSession)
{
MediaSession = mediaSession;
}
}

public class ArtStateChangedEventArgs : EventArgs
{
public MediaManager.MediaSession MediaSession { get; }
public IRandomAccessStreamReference? Thumbnail { get; }

public ArtStateChangedEventArgs(MediaManager.MediaSession mediaSession, IRandomAccessStreamReference? thumbnail)
{
MediaSession = mediaSession;
Thumbnail = thumbnail;
}
}

public class FocusedMediaChangedEventArgs : EventArgs
{
public MediaManager.MediaSession? MediaSession { get; }
public GlobalSystemMediaTransportControlsSessionPlaybackInfo? PlaybackInfo { get; }

public FocusedMediaChangedEventArgs(MediaManager.MediaSession? mediaSession,
GlobalSystemMediaTransportControlsSessionPlaybackInfo? playbackInfo)
{
MediaSession = mediaSession;
PlaybackInfo = playbackInfo;
}
}
Loading

0 comments on commit cf74ec8

Please sign in to comment.