adding manager functionality
This commit is contained in:
parent
28b7b954c1
commit
7d5ab4477d
@ -63,7 +63,7 @@ namespace Selector.Tests
|
|||||||
public void TrackEquality(FullTrack track1, FullTrack track2, bool shouldEqual)
|
public void TrackEquality(FullTrack track1, FullTrack track2, bool shouldEqual)
|
||||||
{
|
{
|
||||||
var eq = Equal.String();
|
var eq = Equal.String();
|
||||||
eq.IsEqual<FullTrack>(track1, track2).Should().Be(shouldEqual);
|
eq.IsEqual(track1, track2).Should().Be(shouldEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> AlbumData =>
|
public static IEnumerable<object[]> AlbumData =>
|
||||||
@ -106,7 +106,7 @@ namespace Selector.Tests
|
|||||||
public void AlbumEquality(SimpleAlbum album1, SimpleAlbum album2, bool shouldEqual)
|
public void AlbumEquality(SimpleAlbum album1, SimpleAlbum album2, bool shouldEqual)
|
||||||
{
|
{
|
||||||
var eq = Equal.String();
|
var eq = Equal.String();
|
||||||
eq.IsEqual<SimpleAlbum>(album1, album2).Should().Be(shouldEqual);
|
eq.IsEqual(album1, album2).Should().Be(shouldEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> ArtistData =>
|
public static IEnumerable<object[]> ArtistData =>
|
||||||
@ -131,7 +131,7 @@ namespace Selector.Tests
|
|||||||
public void ArtistEquality(SimpleArtist artist1, SimpleArtist artist2, bool shouldEqual)
|
public void ArtistEquality(SimpleArtist artist1, SimpleArtist artist2, bool shouldEqual)
|
||||||
{
|
{
|
||||||
var eq = Equal.String();
|
var eq = Equal.String();
|
||||||
eq.IsEqual<SimpleArtist>(artist1, artist2).Should().Be(shouldEqual);
|
eq.IsEqual(artist1, artist2).Should().Be(shouldEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> EpisodeData =>
|
public static IEnumerable<object[]> EpisodeData =>
|
||||||
@ -156,7 +156,7 @@ namespace Selector.Tests
|
|||||||
public void EpisodeEquality(FullEpisode episode1, FullEpisode episode2, bool shouldEqual)
|
public void EpisodeEquality(FullEpisode episode1, FullEpisode episode2, bool shouldEqual)
|
||||||
{
|
{
|
||||||
var eq = Equal.String();
|
var eq = Equal.String();
|
||||||
eq.IsEqual<FullEpisode>(episode1, episode2).Should().Be(shouldEqual);
|
eq.IsEqual(episode1, episode2).Should().Be(shouldEqual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
56
Selector.Tests/Manager.cs
Normal file
56
Selector.Tests/Manager.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Xunit;
|
||||||
|
using Moq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using SpotifyAPI.Web;
|
||||||
|
|
||||||
|
using Selector;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Selector.Tests
|
||||||
|
{
|
||||||
|
public class ManagerTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Count()
|
||||||
|
{
|
||||||
|
var manager = new Manager();
|
||||||
|
|
||||||
|
var watcherMock = new Mock<IWatcher>();
|
||||||
|
|
||||||
|
manager.Add(watcherMock.Object);
|
||||||
|
manager.Add(watcherMock.Object);
|
||||||
|
manager.Add(watcherMock.Object);
|
||||||
|
|
||||||
|
manager.Count.Should().Be(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StartAndStop()
|
||||||
|
{
|
||||||
|
var manager = new Manager();
|
||||||
|
|
||||||
|
var watcherMock = new Mock<IWatcher>();
|
||||||
|
|
||||||
|
manager.Add(watcherMock.Object);
|
||||||
|
manager.Count.Should().Be(1);
|
||||||
|
|
||||||
|
manager.Start();
|
||||||
|
|
||||||
|
manager.IsRunning.Should().BeTrue();
|
||||||
|
manager.Running.Count().Should().Be(1);
|
||||||
|
|
||||||
|
var context = manager.Running.First();
|
||||||
|
|
||||||
|
manager.Stop();
|
||||||
|
|
||||||
|
manager.IsRunning.Should().BeFalse();
|
||||||
|
context.IsRunning.Should().BeFalse();
|
||||||
|
|
||||||
|
manager.Running.Count().Should().Be(0);
|
||||||
|
manager.TokenSources.First().IsCancellationRequested.Should().BeTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,8 @@ using FluentAssertions;
|
|||||||
using SpotifyAPI.Web;
|
using SpotifyAPI.Web;
|
||||||
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
namespace Selector.Tests
|
namespace Selector.Tests
|
||||||
{
|
{
|
||||||
@ -203,11 +205,32 @@ namespace Selector.Tests
|
|||||||
toNotRaise.ForEach(r => monitoredWatcher.Should().NotRaise(r));
|
toNotRaise.ForEach(r => monitoredWatcher.Should().NotRaise(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(1000, 3500, 4)]
|
||||||
|
[InlineData(500, 3800, 8)]
|
||||||
|
public async void Watch(int pollPeriod, int execTime, int numberOfCalls)
|
||||||
|
{
|
||||||
|
var spotMock = new Mock<IPlayerClient>();
|
||||||
|
var eq = new UriEqual();
|
||||||
|
var watch = new PlayerWatcher(spotMock.Object, eq)
|
||||||
|
{
|
||||||
|
PollPeriod = pollPeriod
|
||||||
|
};
|
||||||
|
|
||||||
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
var task = watch.Watch(tokenSource.Token);
|
||||||
|
|
||||||
|
await Task.Delay(execTime);
|
||||||
|
tokenSource.Cancel();
|
||||||
|
|
||||||
|
spotMock.Verify(s => s.GetCurrentPlayback(), Times.Exactly(numberOfCalls));
|
||||||
|
}
|
||||||
|
|
||||||
// [Fact]
|
// [Fact]
|
||||||
// public async void Auth()
|
// public async void Auth()
|
||||||
// {
|
// {
|
||||||
// var spot = new SpotifyClient("");
|
// var spot = new SpotifyClient("");
|
||||||
// var eq = new UriEquality();
|
// var eq = new UriEqual();
|
||||||
// var watch = new PlayerWatcher(spot.Player, eq);
|
// var watch = new PlayerWatcher(spot.Player, eq);
|
||||||
|
|
||||||
// var token = new CancellationTokenSource();
|
// var token = new CancellationTokenSource();
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Selector
|
|
||||||
{
|
|
||||||
class Playable
|
|
||||||
{
|
|
||||||
public Type Type;
|
|
||||||
public object Obj;
|
|
||||||
}
|
|
||||||
}
|
|
@ -34,10 +34,7 @@ namespace Selector
|
|||||||
public void Add(CurrentlyPlayingContext item) => Add(item, DateHelper.FromUnixMilli(item.Timestamp));
|
public void Add(CurrentlyPlayingContext item) => Add(item, DateHelper.FromUnixMilli(item.Timestamp));
|
||||||
public void Add(CurrentlyPlayingContext item, DateTime timestamp)
|
public void Add(CurrentlyPlayingContext item, DateTime timestamp)
|
||||||
{
|
{
|
||||||
recentlyPlayed.Add(new TimelineItem<CurrentlyPlayingContext>(){
|
recentlyPlayed.Add(TimelineItem<CurrentlyPlayingContext>.From(item, timestamp));
|
||||||
Item = item,
|
|
||||||
Time = timestamp
|
|
||||||
});
|
|
||||||
|
|
||||||
if (timestamp < recentlyPlayed.Last().Time && SortOnBackDate)
|
if (timestamp < recentlyPlayed.Last().Time && SortOnBackDate)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -8,13 +9,13 @@ namespace Selector
|
|||||||
{
|
{
|
||||||
public abstract class BaseWatcher: IWatcher
|
public abstract class BaseWatcher: IWatcher
|
||||||
{
|
{
|
||||||
public abstract Task WatchOne();
|
public abstract Task WatchOne(CancellationToken token);
|
||||||
|
|
||||||
public async Task Watch(CancellationToken cancelToken)
|
public async Task Watch(CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
while (!cancelToken.IsCancellationRequested)
|
while (true) {
|
||||||
{
|
cancelToken.ThrowIfCancellationRequested();
|
||||||
await WatchOne();
|
await WatchOne(cancelToken);
|
||||||
await Task.Delay(PollPeriod);
|
await Task.Delay(PollPeriod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using SpotifyAPI.Web;
|
using SpotifyAPI.Web;
|
||||||
|
|
||||||
namespace Selector
|
namespace Selector
|
||||||
@ -15,5 +14,8 @@ namespace Selector
|
|||||||
public event EventHandler<ListeningChangeEventArgs> VolumeChange;
|
public event EventHandler<ListeningChangeEventArgs> VolumeChange;
|
||||||
public event EventHandler<ListeningChangeEventArgs> DeviceChange;
|
public event EventHandler<ListeningChangeEventArgs> DeviceChange;
|
||||||
public event EventHandler<ListeningChangeEventArgs> PlayingChange;
|
public event EventHandler<ListeningChangeEventArgs> PlayingChange;
|
||||||
|
|
||||||
|
public CurrentlyPlayingContext Live { get; }
|
||||||
|
public PlayerTimeline Past { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using SpotifyAPI.Web;
|
|
||||||
|
|
||||||
namespace Selector
|
namespace Selector
|
||||||
{
|
{
|
||||||
public interface IWatcher
|
public interface IWatcher
|
||||||
{
|
{
|
||||||
public Task WatchOne();
|
public Task WatchOne(CancellationToken cancelToken);
|
||||||
public Task Watch(CancellationToken cancelToken);
|
public Task Watch(CancellationToken cancelToken);
|
||||||
|
|
||||||
public int PollPeriod { get; set; }
|
public int PollPeriod { get; set; }
|
||||||
|
@ -6,9 +6,10 @@ namespace Selector
|
|||||||
{
|
{
|
||||||
interface IManager
|
interface IManager
|
||||||
{
|
{
|
||||||
|
public bool IsRunning { get; }
|
||||||
public void Add(IWatcher watcher);
|
public void Add(IWatcher watcher);
|
||||||
|
|
||||||
public bool Start();
|
public void Start();
|
||||||
public bool Stop();
|
public void Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
63
Selector/Watcher/Manager/Manager.cs
Normal file
63
Selector/Watcher/Manager/Manager.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Selector
|
||||||
|
{
|
||||||
|
public class Manager: IManager, IDisposable
|
||||||
|
{
|
||||||
|
public bool IsRunning { get; private set; } = true;
|
||||||
|
private List<WatcherContext> Watchers { get; set; } = new();
|
||||||
|
public int Count => Watchers.Count;
|
||||||
|
public IEnumerable<Task> Tasks
|
||||||
|
=> Watchers
|
||||||
|
.Select(w => w.Task)
|
||||||
|
.Where(t => t is not null);
|
||||||
|
|
||||||
|
public IEnumerable<CancellationTokenSource> TokenSources
|
||||||
|
=> Watchers
|
||||||
|
.Select(w => w.TokenSource)
|
||||||
|
.Where(t => t is not null);
|
||||||
|
|
||||||
|
public void Add(IWatcher watcher)
|
||||||
|
{
|
||||||
|
var context = WatcherContext.From(watcher);
|
||||||
|
if (IsRunning) context.Start();
|
||||||
|
|
||||||
|
Watchers.Add(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<WatcherContext> Running
|
||||||
|
=> Watchers.Where(w => w.IsRunning);
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
foreach(var watcher in Watchers)
|
||||||
|
{
|
||||||
|
watcher.Start();
|
||||||
|
}
|
||||||
|
IsRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
foreach(var watcher in Watchers)
|
||||||
|
{
|
||||||
|
watcher.Stop();
|
||||||
|
}
|
||||||
|
Task.WaitAll(Tasks.ToArray());
|
||||||
|
IsRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach(var watcher in Watchers)
|
||||||
|
{
|
||||||
|
watcher.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
Selector/Watcher/Manager/WatcherContext.cs
Normal file
61
Selector/Watcher/Manager/WatcherContext.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Selector
|
||||||
|
{
|
||||||
|
public class WatcherContext: IDisposable
|
||||||
|
{
|
||||||
|
public IWatcher Watcher { get; set; }
|
||||||
|
public bool IsRunning { get; private set; }
|
||||||
|
public Task Task { get; set; }
|
||||||
|
public CancellationTokenSource TokenSource { get; set; }
|
||||||
|
|
||||||
|
public WatcherContext(IWatcher watcher)
|
||||||
|
{
|
||||||
|
Watcher = watcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WatcherContext From(IWatcher watcher)
|
||||||
|
{
|
||||||
|
return new(watcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
if (IsRunning)
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
IsRunning = true;
|
||||||
|
TokenSource = new();
|
||||||
|
Task = Watcher.Watch(TokenSource.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
TokenSource.Cancel();
|
||||||
|
IsRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Clear()
|
||||||
|
{
|
||||||
|
if(IsRunning
|
||||||
|
|| Task.Status == TaskStatus.Running
|
||||||
|
|| Task.Status == TaskStatus.WaitingToRun)
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task = null;
|
||||||
|
TokenSource = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -33,8 +33,10 @@ namespace Selector
|
|||||||
PollPeriod = pollPeriod;
|
PollPeriod = pollPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task WatchOne()
|
public override async Task WatchOne(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
try{
|
try{
|
||||||
var polledCurrent = await spotifyClient.GetCurrentPlayback();
|
var polledCurrent = await spotifyClient.GetCurrentPlayback();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user