diff --git a/Selector.Tests/Watcher/PlayerWatcher.cs b/Selector.Tests/Watcher/PlayerWatcher.cs index c93ebf6..9a4ed7b 100644 --- a/Selector.Tests/Watcher/PlayerWatcher.cs +++ b/Selector.Tests/Watcher/PlayerWatcher.cs @@ -54,9 +54,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("nochange", "album1", "artist1"), isPlaying: true, context: "context1"), }, // to raise - new List(){ "ItemChange", "ContextChange", "PlayingChange" }, + new List(){ "ItemChange", "ContextChange", "PlayingChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "DeviceChange", "VolumeChange" } + new List(){ "AlbumChange", "ArtistChange" } }, // TRACK CHANGE new object[] { new List(){ @@ -64,9 +64,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("trackchange2", "album1", "artist1")) }, // to raise - new List(){ "ContextChange", "PlayingChange", "ItemChange" }, + new List(){ "ContextChange", "PlayingChange", "ItemChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "DeviceChange", "VolumeChange" } + new List(){ "AlbumChange", "ArtistChange" } }, // ALBUM CHANGE new object[] { new List(){ @@ -74,9 +74,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("albumchange", "album2", "artist1")) }, // to raise - new List(){ "ContextChange", "PlayingChange", "ItemChange", "AlbumChange" }, + new List(){ "ContextChange", "PlayingChange", "ItemChange", "AlbumChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "ArtistChange", "DeviceChange", "VolumeChange" } + new List(){ "ArtistChange" } }, // ARTIST CHANGE new object[] { new List(){ @@ -84,9 +84,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("artistchange", "album1", "artist2")) }, // to raise - new List(){ "ContextChange", "PlayingChange", "ItemChange", "ArtistChange" }, + new List(){ "ContextChange", "PlayingChange", "ItemChange", "ArtistChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "AlbumChange", "DeviceChange", "VolumeChange" } + new List(){ "AlbumChange" } }, // CONTEXT CHANGE new object[] { new List(){ @@ -94,9 +94,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("contextchange", "album1", "artist1"), context: "context2") }, // to raise - new List(){ "PlayingChange", "ItemChange", "ContextChange" }, + new List(){ "PlayingChange", "ItemChange", "ContextChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "DeviceChange", "VolumeChange" } + new List(){ "AlbumChange", "ArtistChange" } }, // PLAYING CHANGE new object[] { new List(){ @@ -104,9 +104,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("playingchange1", "album1", "artist1"), isPlaying: false, context: "context1") }, // to raise - new List(){ "ContextChange", "ItemChange", "PlayingChange" }, + new List(){ "ContextChange", "ItemChange", "PlayingChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "DeviceChange", "VolumeChange" } + new List(){ "AlbumChange", "ArtistChange" } }, // PLAYING CHANGE new object[] { new List(){ @@ -114,9 +114,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("playingchange2", "album1", "artist1"), isPlaying: true, context: "context1") }, // to raise - new List(){ "ContextChange", "ItemChange", "PlayingChange" }, + new List(){ "ContextChange", "ItemChange", "PlayingChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "DeviceChange", "VolumeChange" } + new List(){ "AlbumChange", "ArtistChange" } }, // CONTENT CHANGE new object[] { new List(){ @@ -124,9 +124,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullEpisode("contentchange1", "show1", "pub1"), isPlaying: true, context: "context2") }, // to raise - new List(){ "PlayingChange", "ContentChange", "ContextChange", "ItemChange" }, + new List(){ "PlayingChange", "ContentChange", "ContextChange", "ItemChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "DeviceChange", "VolumeChange" } + new List(){ "AlbumChange", "ArtistChange" } }, // CONTENT CHANGE new object[] { new List(){ @@ -134,9 +134,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("contentchange1", "album1", "artist1"), isPlaying: true, context: "context1") }, // to raise - new List(){ "PlayingChange", "ContentChange", "ContextChange", "ItemChange" }, + new List(){ "PlayingChange", "ContentChange", "ContextChange", "ItemChange", "DeviceChange", "VolumeChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "DeviceChange", "VolumeChange" } + new List(){ "AlbumChange", "ArtistChange" } }, // DEVICE CHANGE new object[] { new List(){ @@ -144,9 +144,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("devicechange", "album1", "artist1"), device: Helper.Device("dev2")) }, // to raise - new List(){ "ContextChange", "PlayingChange", "ItemChange", "DeviceChange" }, + new List(){ "ContextChange", "PlayingChange", "ItemChange", "VolumeChange", "DeviceChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "ContentChange", "VolumeChange" } + new List(){ "AlbumChange", "ArtistChange", "ContentChange" } }, // VOLUME CHANGE new object[] { new List(){ @@ -154,9 +154,9 @@ namespace Selector.Tests Helper.CurrentPlayback(Helper.FullTrack("volumechange", "album1", "artist1"), device: Helper.Device("dev1", volume: 60)) }, // to raise - new List(){ "ContextChange", "PlayingChange", "ItemChange", "VolumeChange" }, + new List(){ "ContextChange", "PlayingChange", "ItemChange", "VolumeChange", "DeviceChange" }, // to not raise - new List(){ "AlbumChange", "ArtistChange", "ContentChange", "DeviceChange" } + new List(){ "AlbumChange", "ArtistChange", "ContentChange" } }, // // STARTED PLAYBACK // new object[] { new List(){ diff --git a/Selector/Equality/Equal.cs b/Selector/Equality/Equal.cs index f886429..0678d94 100644 --- a/Selector/Equality/Equal.cs +++ b/Selector/Equality/Equal.cs @@ -11,6 +11,9 @@ namespace Selector public bool IsEqual(T item, T other) { + if (item is null && other is null) return true; + if (item is null ^ other is null) return false; + if (comps.ContainsKey(typeof(T))) { var comp = (IEqualityComparer) comps[typeof(T)]; diff --git a/Selector/Equality/UriEqual.cs b/Selector/Equality/UriEqual.cs index 98df5c8..0c5cf2b 100644 --- a/Selector/Equality/UriEqual.cs +++ b/Selector/Equality/UriEqual.cs @@ -6,6 +6,9 @@ namespace Selector { public bool IsEqual(T item, T other) { + if (item is null && other is null) return true; + if (item is null ^ other is null) return false; + var uri = typeof(T).GetProperty("Uri"); if(uri is not null) diff --git a/Selector/Watcher/PlayerWatcher.cs b/Selector/Watcher/PlayerWatcher.cs index c1eeaeb..24ac44f 100644 --- a/Selector/Watcher/PlayerWatcher.cs +++ b/Selector/Watcher/PlayerWatcher.cs @@ -68,127 +68,11 @@ namespace Selector OnNetworkPoll(GetEvent()); - // NOT PLAYING - if(Previous is null && Live is null) - { - // Console.WriteLine("not playing"); - } - else - { - // STARTED PLAYBACK - if(Previous?.Context is null && Live?.Context is not null) - { - Logger.LogDebug("Context started: {context}", Live?.Context.DisplayString()); - OnContextChange(GetEvent()); - } + CheckPlaying(); + CheckContext(); + CheckItem(); + CheckDevice(); - if(Previous?.Item is null && Live?.Item is not null) - { - if (Live.Item is FullTrack track) - { - Logger.LogDebug("Item started: {track}", track.DisplayString()); - } - else if (Live.Item is FullEpisode episode) - { - Logger.LogDebug("Item started: {episode}", episode.DisplayString()); - } - else - { - Logger.LogDebug("Item started: {item}", Live.Item); - } - OnItemChange(GetEvent()); - } - - if(Previous is null && Live is not null) - { - Logger.LogDebug("Playback started: {context}", Live.DisplayString()); - OnPlayingChange(GetEvent()); - } - // STOPPED PLAYBACK - else if(Previous is not null && Live is null) - { - Logger.LogDebug("Playback stopped: {context}", Previous.DisplayString()); - OnPlayingChange(GetEvent()); - OnItemChange(GetEvent()); - OnContextChange(GetEvent()); - } - // CONTINUING PLAYBACK - else { - - // MUSIC - if(Previous.Item is FullTrack previousTrack - && Live.Item is FullTrack currentTrack) - { - if(!eq.IsEqual(previousTrack, currentTrack)) { - Logger.LogDebug("Track changed: {prevTrack} -> {currentTrack}", previousTrack.DisplayString(), currentTrack.DisplayString()); - OnItemChange(GetEvent()); - } - - if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) { - Logger.LogDebug($"Album changed: {previousTrack.Album.DisplayString()} -> {currentTrack.Album.DisplayString()}"); - OnAlbumChange(GetEvent()); - } - - if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) { - Logger.LogDebug($"Artist changed: {previousTrack.Artists.DisplayString()} -> {currentTrack.Artists.DisplayString()}"); - OnArtistChange(GetEvent()); - } - } - // CHANGED CONTENT TYPE - else if((Previous.Item is FullTrack && Live.Item is FullEpisode) - || (Previous.Item is FullEpisode && Live.Item is FullTrack)) - { - Logger.LogDebug($"Media type changed: {Previous.Item}, {Previous.Item}"); - OnContentChange(GetEvent()); - OnItemChange(GetEvent()); - } - // PODCASTS - else if(Previous.Item is FullEpisode previousEp - && Live.Item is FullEpisode currentEp) - { - if(!eq.IsEqual(previousEp, currentEp)) { - Logger.LogDebug($"Podcast changed: {previousEp.DisplayString()} -> {currentEp.DisplayString()}"); - OnItemChange(GetEvent()); - } - } - else if (Previous.Item is null) - { - Logger.LogTrace($"Previous item was null [{Previous.DisplayString()}]"); - } - else if (Live.Item is null) - { - Logger.LogTrace($"Live item was null [{Live.DisplayString()}]"); - } - else { - Logger.LogError($"Unknown combination of previous and current playing contexts, [{Previous.DisplayString()}] [{Live.DisplayString()}]"); - throw new NotSupportedException("Unknown item combination"); - } - - // CONTEXT - if(!eq.IsEqual(Previous.Context, Live.Context)) { - Logger.LogDebug($"Context changed: {Previous.Context.DisplayString()} -> {Live.Context.DisplayString()}"); - OnContextChange(GetEvent()); - } - - // DEVICE - if(!eq.IsEqual(Previous?.Device, Live?.Device)) { - Logger.LogDebug($"Device changed: {Previous?.Device.DisplayString()} -> {Live?.Device.DisplayString()}"); - OnDeviceChange(GetEvent()); - } - - // IS PLAYING - if(Previous.IsPlaying != Live.IsPlaying) { - Logger.LogDebug($"Playing state changed: {Previous.IsPlaying} -> {Live.IsPlaying}"); - OnPlayingChange(GetEvent()); - } - - // VOLUME - if(Previous.Device.VolumePercent != Live.Device.VolumePercent) { - Logger.LogDebug($"Volume changed: {Previous.Device.VolumePercent}% -> {Live.Device.VolumePercent}%"); - OnVolumeChange(GetEvent()); - } - } - } } catch(APIUnauthorizedException e) { @@ -208,6 +92,129 @@ namespace Selector } } + private void CheckItem() + { + + switch (Previous, Live) + { + case (null or { Item: null }, { Item: FullTrack track }): + Logger.LogDebug("Item started: {track}", track.DisplayString()); + break; + case (null or { Item: null }, { Item: FullEpisode episode }): + Logger.LogDebug("Item started: {episode}", episode.DisplayString()); + break; + case (null or { Item: null }, { Item: not null }): + Logger.LogDebug("Item started: {item}", Live.Item); + break; + } + + switch (Previous, Live) + { + case (null or { Item: null }, { Item: not null }): + OnItemChange(GetEvent()); + break; + case ({ Item: not null }, null or { Item: null }): + Logger.LogDebug("Item stopped: {context}", Previous.DisplayString()); + OnItemChange(GetEvent()); + break; + } + + switch (Previous, Live) + { + case ({ Item: FullTrack previousTrack }, { Item: FullTrack currentTrack }): + if (!eq.IsEqual(previousTrack, currentTrack)) + { + Logger.LogDebug("Track changed: {prevTrack} -> {currentTrack}", previousTrack.DisplayString(), currentTrack.DisplayString()); + OnItemChange(GetEvent()); + } + + if (!eq.IsEqual(previousTrack.Album, currentTrack.Album)) + { + Logger.LogDebug("Album changed: {previous} -> {current}", previousTrack.Album.DisplayString(), currentTrack.Album.DisplayString()); + OnAlbumChange(GetEvent()); + } + + if (!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) + { + Logger.LogDebug("Artist changed: {previous} -> {current}", previousTrack.Artists.DisplayString(), currentTrack.Artists.DisplayString()); + OnArtistChange(GetEvent()); + } + break; + case ({ Item: FullTrack previousTrack }, { Item: FullEpisode currentEp }): + Logger.LogDebug("Media type changed: {previous}, {current}", previousTrack.DisplayString(), currentEp.DisplayString()); + OnContentChange(GetEvent()); + OnItemChange(GetEvent()); + break; + case ({ Item: FullEpisode previousEpisode }, { Item: FullTrack currentTrack }): + Logger.LogDebug("Media type changed: {previous}, {current}", previousEpisode.DisplayString(), currentTrack.DisplayString()); + OnContentChange(GetEvent()); + OnItemChange(GetEvent()); + break; + case ({ Item: FullEpisode previousEp }, { Item: FullEpisode currentEp }): + if (!eq.IsEqual(previousEp, currentEp)) + { + Logger.LogDebug($"Podcast changed: {previousEp.DisplayString()} -> {currentEp.DisplayString()}"); + OnItemChange(GetEvent()); + } + break; + } + } + + private void CheckContext() + { + if ((Previous, Live) + is (null or { Context: null }, { Context: not null })) + { + Logger.LogDebug("Context started: {context}", Live?.Context.DisplayString()); + OnContextChange(GetEvent()); + } + else if (!eq.IsEqual(Previous?.Context, Live?.Context)) + { + Logger.LogDebug($"Context changed: {Previous?.Context?.DisplayString() ?? "none"} -> {Live?.Context?.DisplayString() ?? "none"}"); + OnContextChange(GetEvent()); + } + } + + private void CheckPlaying() + { + switch (Previous, Live) + { + case (null, not null): + Logger.LogDebug("Playback started: {context}", Live.DisplayString()); + OnPlayingChange(GetEvent()); + break; + case (not null, null): + Logger.LogDebug("Playback stopped: {context}", Previous.DisplayString()); + OnPlayingChange(GetEvent()); + OnContextChange(GetEvent()); + break; + } + + // IS PLAYING + if (Previous?.IsPlaying != Live?.IsPlaying) + { + Logger.LogDebug($"Playing state changed: {Previous?.IsPlaying} -> {Live?.IsPlaying}"); + OnPlayingChange(GetEvent()); + } + } + + private void CheckDevice() + { + // DEVICE + if (!eq.IsEqual(Previous?.Device, Live?.Device)) + { + Logger.LogDebug($"Device changed: {Previous?.Device?.DisplayString() ?? "none"} -> {Live?.Device?.DisplayString() ?? "none"}"); + OnDeviceChange(GetEvent()); + } + + // VOLUME + if (Previous?.Device?.VolumePercent != Live?.Device?.VolumePercent) + { + Logger.LogDebug($"Volume changed: {Previous?.Device?.VolumePercent}% -> {Live?.Device?.VolumePercent}%"); + OnVolumeChange(GetEvent()); + } + } + private ListeningChangeEventArgs GetEvent() => ListeningChangeEventArgs.From(Previous, Live, Past, id: Id, username: SpotifyUsername); ///