adding player watcher

This commit is contained in:
andy 2021-10-03 23:37:50 +01:00
parent 918ebbb238
commit 02af7a5e21
6 changed files with 138 additions and 92 deletions

View File

@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using SpotifyAPI.Web;
namespace Selector namespace Selector
{ {

View File

@ -1,6 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace Selector namespace Selector
{ {

View File

@ -4,7 +4,7 @@ namespace Selector
{ {
public interface ITimeline<T> public interface ITimeline<T>
{ {
public int Count { get; set; } public int Count { get; }
public T Get(DateTime at); public T Get(DateTime at);
public T Get(); public T Get();
public void Add(T item, DateTime timestamp); public void Add(T item, DateTime timestamp);

View File

@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SpotifyAPI.Web;
namespace Selector
{
public class PlayerTimeline : ITimeline<CurrentlyPlayingContext>
{
private List<TimelineItem<CurrentlyPlayingContext>> recentlyPlayed = new List<TimelineItem<CurrentlyPlayingContext>>();
public IEqual EqualityChecker { get; set; }
public bool SortOnBackDate { get; set; }
public int Count { get => recentlyPlayed.Count; }
public void Add(CurrentlyPlayingContext item) => Add(item, DateHelper.FromUnixMilli(item.Timestamp));
public void Add(CurrentlyPlayingContext item, DateTime timestamp)
{
recentlyPlayed.Add(new TimelineItem<CurrentlyPlayingContext>(){
Item = item,
Time = timestamp
});
if (timestamp < recentlyPlayed.Last().Time && SortOnBackDate)
{
Sort();
}
}
public void Sort()
{
recentlyPlayed = recentlyPlayed
.OrderBy(i => i.Time)
.ToList();
}
public void Clear() => recentlyPlayed.Clear();
public CurrentlyPlayingContext Get()
=> recentlyPlayed.Last().Item;
public CurrentlyPlayingContext Get(DateTime at)
=> GetTimelineItem(at)?.Item;
public TimelineItem<CurrentlyPlayingContext> GetTimelineItem(DateTime at)
=> recentlyPlayed.Where(i => i.Time <= at).LastOrDefault();
public CurrentlyPlayingContext Get(FullTrack track)
=> GetAll(track)
.LastOrDefault();
public IEnumerable<CurrentlyPlayingContext> GetAll(FullTrack track)
=> GetAllTimelineItems(track)
.Select(t => t.Item);
private IEnumerable<TimelineItem<CurrentlyPlayingContext>> GetAllTimelineItems(FullTrack track)
=> recentlyPlayed
.Where(i => i.Item.Item is FullTrack iterTrack
&& EqualityChecker.IsEqual(iterTrack, track));
public CurrentlyPlayingContext Get(FullEpisode ep)
=> GetAll(ep)
.LastOrDefault();
public IEnumerable<CurrentlyPlayingContext> GetAll(FullEpisode ep)
=> GetAllTimelineItems(ep)
.Select(t => t.Item);
private IEnumerable<TimelineItem<CurrentlyPlayingContext>> GetAllTimelineItems(FullEpisode ep)
=> recentlyPlayed
.Where(i => i.Item.Item is FullEpisode iterEp
&& EqualityChecker.IsEqual(iterEp, ep));
public CurrentlyPlayingContext Get(SimpleAlbum album)
=> GetAll(album)
.LastOrDefault();
public IEnumerable<CurrentlyPlayingContext> GetAll(SimpleAlbum album)
=> GetAllTimelineItems(album)
.Select(t => t.Item);
private IEnumerable<TimelineItem<CurrentlyPlayingContext>> GetAllTimelineItems(SimpleAlbum album)
=> recentlyPlayed
.Where(i => i.Item.Item is FullTrack iterTrack
&& EqualityChecker.IsEqual(iterTrack.Album, album));
public CurrentlyPlayingContext Get(SimpleArtist artist)
=> GetAll(artist)
.LastOrDefault();
public IEnumerable<CurrentlyPlayingContext> GetAll(SimpleArtist artist)
=> GetAllTimelineItems(artist)
.Select(t => t.Item);
private IEnumerable<TimelineItem<CurrentlyPlayingContext>> GetAllTimelineItems(SimpleArtist artist)
=> recentlyPlayed
.Where(i => i.Item.Item is FullTrack iterTrack
&& EqualityChecker.IsEqual(iterTrack.Artists[0], artist));
public CurrentlyPlayingContext Get(Device device)
=> GetAll(device)
.LastOrDefault();
public IEnumerable<CurrentlyPlayingContext> GetAll(Device device)
=> GetAllTimelineItems(device)
.Select(t => t.Item);
private IEnumerable<TimelineItem<CurrentlyPlayingContext>> GetAllTimelineItems(Device device)
=> recentlyPlayed.Where(i => EqualityChecker.IsEqual(i.Item.Device, device));
public CurrentlyPlayingContext Get(Context context)
=> GetAll(context)
.LastOrDefault();
public IEnumerable<CurrentlyPlayingContext> GetAll(Context context)
=> GetAllTimelineItems(context)
.Select(t => t.Item);
private IEnumerable<TimelineItem<CurrentlyPlayingContext>> GetAllTimelineItems(Context context)
=> recentlyPlayed.Where(i => EqualityChecker.IsEqual(i.Item.Context, context));
}
}

View File

@ -1,29 +0,0 @@
using System;
namespace Selector
{
public class Timeline<T> : ITimeline<T>
{
public int Count { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public void Add(T item, DateTime timestamp)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public T Get(DateTime at)
{
throw new NotImplementedException();
}
public T Get()
{
throw new NotImplementedException();
}
}
}

View File

@ -22,18 +22,15 @@ namespace Selector
public event EventHandler<ListeningChangeEventArgs> PlayingChange; public event EventHandler<ListeningChangeEventArgs> PlayingChange;
public CurrentlyPlayingContext Live { get; private set; } public CurrentlyPlayingContext Live { get; private set; }
public ITimeline<CurrentlyPlayingContext> Past { get; private set; } public PlayerTimeline Past { get; private set; }
private List<List<CurrentlyPlayingContext>> lastPlays { get; set; }
public PlayerWatcher(IPlayerClient spotifyClient, public PlayerWatcher(IPlayerClient spotifyClient,
IEqual equalityChecker, IEqual equalityChecker,
int pollPeriod = 3000) { int pollPeriod = 3000) {
this.spotifyClient = spotifyClient; this.spotifyClient = spotifyClient;
this.eq = equalityChecker; eq = equalityChecker;
this.PollPeriod = pollPeriod; PollPeriod = pollPeriod;
lastPlays = new List<List<CurrentlyPlayingContext>>();
} }
public override async Task WatchOne() public override async Task WatchOne()
@ -41,7 +38,7 @@ namespace Selector
try{ try{
var polledCurrent = await spotifyClient.GetCurrentPlayback(); var polledCurrent = await spotifyClient.GetCurrentPlayback();
if (polledCurrent != null) StoreCurrentPlaying(Live, polledCurrent); if (polledCurrent != null) StoreCurrentPlaying(polledCurrent);
// swap new item into live and bump existing down to previous // swap new item into live and bump existing down to previous
CurrentlyPlayingContext previous; CurrentlyPlayingContext previous;
@ -78,15 +75,15 @@ namespace Selector
if(previous.Item is FullTrack previousTrack && Live.Item is FullTrack currentTrack) if(previous.Item is FullTrack previousTrack && Live.Item is FullTrack currentTrack)
{ {
if(!eq.IsEqual<FullTrack>(previousTrack, currentTrack)) { if(!eq.IsEqual(previousTrack, currentTrack)) {
OnItemChange(ListeningChangeEventArgs.From(previous, Live)); OnItemChange(ListeningChangeEventArgs.From(previous, Live));
} }
if(!eq.IsEqual<SimpleAlbum>(previousTrack.Album, currentTrack.Album)) { if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) {
OnAlbumChange(ListeningChangeEventArgs.From(previous, Live)); OnAlbumChange(ListeningChangeEventArgs.From(previous, Live));
} }
if(!eq.IsEqual<SimpleArtist>(previousTrack.Artists[0], currentTrack.Artists[0])) { if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) {
OnArtistChange(ListeningChangeEventArgs.From(previous, Live)); OnArtistChange(ListeningChangeEventArgs.From(previous, Live));
} }
} }
@ -100,7 +97,7 @@ namespace Selector
// PODCASTS // PODCASTS
else if(previous.Item is FullEpisode previousEp && Live.Item is FullEpisode currentEp) else if(previous.Item is FullEpisode previousEp && Live.Item is FullEpisode currentEp)
{ {
if(!eq.IsEqual<FullEpisode>(previousEp, currentEp)) { if(!eq.IsEqual(previousEp, currentEp)) {
OnItemChange(ListeningChangeEventArgs.From(previous, Live)); OnItemChange(ListeningChangeEventArgs.From(previous, Live));
} }
} }
@ -109,12 +106,12 @@ namespace Selector
} }
// CONTEXT // CONTEXT
if(!eq.IsEqual<Context>(previous.Context, Live.Context)) { if(!eq.IsEqual(previous.Context, Live.Context)) {
OnContextChange(ListeningChangeEventArgs.From(previous, Live)); OnContextChange(ListeningChangeEventArgs.From(previous, Live));
} }
// DEVICE // DEVICE
if(!eq.IsEqual<Device>(previous?.Device, Live?.Device)) { if(!eq.IsEqual(previous?.Device, Live?.Device)) {
OnDeviceChange(ListeningChangeEventArgs.From(previous, Live)); OnDeviceChange(ListeningChangeEventArgs.From(previous, Live));
} }
@ -148,53 +145,12 @@ namespace Selector
/// Store currently playing in last plays. Determine whether new list or appending required /// Store currently playing in last plays. Determine whether new list or appending required
/// </summary> /// </summary>
/// <param name="current">New currently playing to store</param> /// <param name="current">New currently playing to store</param>
private void StoreCurrentPlaying(CurrentlyPlayingContext previous, CurrentlyPlayingContext current) private void StoreCurrentPlaying(CurrentlyPlayingContext current)
{ {
if(lastPlays.Count > 0) Past?.Add(current);
{
bool matchesMostRecent;
try {
var castItem = (FullTrack) current.Item;
var castStoredItem = (FullTrack) lastPlays[0][0].Item;
matchesMostRecent = eq.IsEqual<FullTrack>(castItem, castStoredItem);
}
catch(InvalidCastException)
{
var castItem = (FullEpisode) current.Item;
var castStoredItem = (FullEpisode) lastPlays[0][0].Item;
matchesMostRecent = eq.IsEqual<FullEpisode>(castItem, castStoredItem);
}
if (matchesMostRecent)
{
lastPlays[0].Add(current);
}
else
{
StoreNewTrack(previous, current);
}
}
else {
StoreNewTrack(previous, current);
}
}
/// <summary>
/// Store currently playing at front of last plays list. Pushes new list to hold same track
/// </summary>
/// <param name="current">New currently playing to store</param>
private void StoreNewTrack(CurrentlyPlayingContext previous, CurrentlyPlayingContext current)
{
if (previous != null) {
var newPlayingList = new List<CurrentlyPlayingContext>();
newPlayingList.Add(previous);
lastPlays.Insert(0, newPlayingList);
}
} }
#region Event Firers
protected virtual void OnItemChange(ListeningChangeEventArgs args) protected virtual void OnItemChange(ListeningChangeEventArgs args)
{ {
ItemChange?.Invoke(this, args); ItemChange?.Invoke(this, args);
@ -234,5 +190,7 @@ namespace Selector
{ {
PlayingChange?.Invoke(this, args); PlayingChange?.Invoke(this, args);
} }
#endregion
} }
} }