Adding dependency injection

This commit is contained in:
watsonb8
2020-01-31 20:41:45 -05:00
parent f8ad2f459e
commit 48d0ffa77d
27 changed files with 550 additions and 114 deletions

View File

@ -8,11 +8,12 @@ using Aurora.Proto.Playback;
using Aurora.Proto.Sync;
using Aurora.Services.ClientService.Events;
using System.Collections.Generic;
using Aurora.Services.Settings;
namespace Aurora.Services.ClientService
{
public class ClientService : BaseService<ClientService>
public class ClientService : IClientService
{
private RemotePartyService.RemotePartyServiceClient _remotePartyClient;
private RemoteEventService.RemoteEventServiceClient _remoteEventsClient;
@ -20,17 +21,19 @@ namespace Aurora.Services.ClientService
private RemoteSyncService.RemoteSyncServiceClient _remoteSyncClient;
private Channel _channel;
CancellationTokenSource _eventCancellationTokenSource;
private CancellationTokenSource _eventCancellationTokenSource;
private ISettingsService _settingsService;
public ClientService()
public ClientService(ISettingsService settingsService)
{
this._settingsService = settingsService;
}
public MediaPausedEventHandler OnMediaPaused;
public NewMediaPlayingEventHandler OnNewMediaPlaying;
public PartyMemberJoinedEventHandler OnPartyMemberJoined;
public PartyMemberLeftEventHandler OnPartyMemberLeft;
public MediaResumedEventHandler OnMediaResumed;
public MediaPausedEventHandler OnMediaPaused { get; set; }
public NewMediaPlayingEventHandler OnNewMediaPlaying { get; set; }
public PartyMemberJoinedEventHandler OnPartyMemberJoined { get; set; }
public PartyMemberLeftEventHandler OnPartyMemberLeft { get; set; }
public MediaResumedEventHandler OnMediaResumed { get; set; }
public RemotePartyService.RemotePartyServiceClient RemotePartyClient
{
@ -94,10 +97,10 @@ namespace Aurora.Services.ClientService
public async Task GetEvents()
{
_eventCancellationTokenSource = new CancellationTokenSource();
string clientId = SettingsService.Instance.ClientId;
string clientId = this._settingsService.ClientId;
Console.WriteLine(string.Format("CLIENT {0} - GetEvents called from client with id", clientId));
using (AsyncServerStreamingCall<BaseEvent> eventStream = _remoteEventsClient
.GetEvents(new EventsRequest { ClientId = SettingsService.Instance.ClientId }))
.GetEvents(new EventsRequest { ClientId = this._settingsService.ClientId }))
{
try
{

View File

@ -0,0 +1,42 @@
using Aurora.Services.ClientService.Events;
using Aurora.Proto.Events;
using Aurora.Proto.Party;
using Aurora.Proto.Playback;
using Aurora.Proto.Sync;
using System.Threading.Tasks;
namespace Aurora.Services.ClientService
{
public interface IClientService
{
MediaPausedEventHandler OnMediaPaused { get; set; }
NewMediaPlayingEventHandler OnNewMediaPlaying { get; set; }
PartyMemberJoinedEventHandler OnPartyMemberJoined { get; set; }
PartyMemberLeftEventHandler OnPartyMemberLeft { get; set; }
MediaResumedEventHandler OnMediaResumed { get; set; }
RemotePartyService.RemotePartyServiceClient RemotePartyClient { get; }
RemoteEventService.RemoteEventServiceClient RemoteEventClient { get; }
RemotePlaybackService.RemotePlaybackServiceClient RemotePlaybackClient { get; }
RemoteSyncService.RemoteSyncServiceClient RemoteSyncClient { get; }
bool IsStarted { get; }
bool IsHost { get; set; }
void Start(string hostname, string port);
void Close();
/// <summary>
/// Asynchronous function for processing events off of the event stream.
/// </summary>
/// <returns></returns>
Task GetEvents();
void StopEvents();
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Threading.Tasks;
using System.Threading;
using Grpc.Core;
using Aurora.Models.Media;
using Aurora.Proto.Sync;
using LibVLCSharp.Shared;
namespace Aurora.Services.Player
{
public interface IPlayer
{
/// <summary>
/// Event handler for changing playback states.
/// </summary>
event PlaybackStateChangedEventHandler PlaybackStateChanged;
event MediaChangedEventHandler MediaChanged;
/// <summary>
/// The state of playback
/// </summary>
/// <value></value>
PlaybackState PlaybackState { get; }
bool IsLoaded { get; }
bool IsMediaLoaded(BaseMedia media);
BaseMedia CurrentMedia { get; }
float CurrentMediaPosition { get; }
long CurrentMediaLength { get; }
/// <summary>
/// Load media into the media player.
/// </summary>
/// <param name="media">Media to load</param>
Task LoadMedia(BaseMedia media);
/// <summary>
/// Play currently loaded media.
/// </summary>
void Play();
/// <summary>
/// Pause currently loaded media.
/// </summary>
void Pause();
/// <summary>
/// Stop currently loaded media.
/// </summary>
void Stop();
void Enqueue(BaseMedia song);
void Dequeue(BaseMedia song);
}
}

View File

@ -1,7 +1,7 @@
using System;
using Aurora.Models.Media;
namespace Aurora.Services.PlayerService
namespace Aurora.Services.Player
{
public delegate void MediaChangedEventHandler(object source, MediaChangedEventArgs e);

View File

@ -0,0 +1,12 @@
using System;
namespace Aurora.Services.Player
{
public enum PlaybackState
{
Playing,
Stopped,
Buffering,
}
}

View File

@ -1,7 +1,7 @@
using System;
using Aurora.Models.Media;
namespace Aurora.Services.PlayerService
namespace Aurora.Services.Player
{
public delegate void PlaybackStateChangedEventHandler(object source, PlaybackStateChangedEventArgs e);

View File

@ -6,10 +6,10 @@ using Aurora.Models.Media;
using Aurora.Proto.Sync;
using LibVLCSharp.Shared;
namespace Aurora.Services.PlayerService
namespace Aurora.Services.Player
{
public class PlayerService : BaseService<PlayerService>
public class PlayerService : BaseService<PlayerService>, IPlayer
{
private const long _ticksPerMillisecond = 10000;
private BaseMedia _currentMedia;

View File

@ -1,9 +0,0 @@
using System;
public enum PlaybackState
{
Playing,
Stopped,
Buffering,
}

View File

@ -0,0 +1,38 @@
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Aurora.Proto.PartyV2;
namespace Aurora.Services.Server.Controllers
{
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
{
/// <summary>
/// Constructor for partial class
/// </summary>
public RemotePartyController(string partyName, string description)
{
this._startDateTime = DateTime.UtcNow;
this._displayName = partyName;
this._description = description;
this._memberList = new SortedList<string, Member>();
this._mediaList = new SortedList<string, Models.Media.BaseMedia>();
string userName = "testUser";
this._eventManager = new EventManager.EventManager();
this._hostMember = new Member()
{
Name = GetNewMemberResourceName(_partyResourceName, ServerService.GetLocalIPAddress(), userName),
UserName = userName,
IpAddress = ServerService.GetLocalIPAddress(),
};
this._memberList.Add(_hostMember.Name, _hostMember);
//Add media from library
}
}
}

View File

@ -1,29 +1,158 @@
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Aurora.Proto.PartyV2;
using Aurora.Models.Media;
using Aurora.Proto.General;
using Aurora.Services.Player;
using Autofac;
namespace Aurora.Services.Server.Controllers
{
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
{
private SortedList<string, BaseMedia> _mediaList;
public override Task<ListMediaResponse> ListMedia(ListMediaRequest request, Grpc.Core.ServerCallContext context)
{
throw new NotImplementedException();
ListMediaResponse resp = new ListMediaResponse();
int startIdx = 0;
if (!string.IsNullOrEmpty(request.PageToken))
{
startIdx = _memberList.IndexOfKey(request.PageToken) + 1;
}
int pageSize = request.PageSize;
if (pageSize > _mediaList.Count)
{
pageSize = _mediaList.Count;
}
//Gather page
List<BaseMedia> baseMedia = new List<BaseMedia>(_mediaList.Values);
foreach (BaseMedia media in baseMedia)
{
if (media.Metadata is AudioMetadata)
{
AudioMetadata meta = media.Metadata as AudioMetadata;
resp.Media.Add(new Media()
{
Name = media.Id,
Title = meta.Title,
Album = meta.Album,
Artist = meta.Artist,
Duration = meta.Duration
});
}
}
resp.NextPageToken = resp.Media[resp.Media.Count - 1].Name;
return Task.FromResult(resp);
}
public override Task<RemoteMedia> GetMedia(GetMediaRequest request, Grpc.Core.ServerCallContext context)
public override Task<Media> GetMedia(GetMediaRequest request, Grpc.Core.ServerCallContext context)
{
_mediaList.TryGetValue(request.Name, out BaseMedia baseMedia);
if (baseMedia == null)
{
throw new KeyNotFoundException();
}
Media media = new Media();
if (baseMedia.Metadata != null && baseMedia.Metadata is AudioMetadata)
{
AudioMetadata metadata = baseMedia.Metadata as AudioMetadata;
media.Name = baseMedia.Id;
media.Title = metadata.Title;
media.Artist = metadata.Artist;
media.Album = metadata.Album;
}
return Task.FromResult(media);
}
public override Task<Media> CreateMedia(CreateMediaRequest request, Grpc.Core.ServerCallContext context)
{
throw new NotImplementedException();
}
public override Task StreamMedia(StreamMediaRequest request, Grpc.Core.IServerStreamWriter<Proto.General.Chunk> responseStream, Grpc.Core.ServerCallContext context)
public override Task<Empty> DeleteMedia(DeleteMediaRequest request, Grpc.Core.ServerCallContext context)
{
throw new NotImplementedException();
}
public override Task SyncMedia(SyncMediaRequest request, Grpc.Core.IServerStreamWriter<Sync> responseStream, Grpc.Core.ServerCallContext context)
public override async Task StreamMedia(StreamMediaRequest request, Grpc.Core.IServerStreamWriter<Proto.General.Chunk> responseStream, Grpc.Core.ServerCallContext context)
{
throw new NotImplementedException();
BaseMedia originalSong = LibraryService.Instance.GetSong(request.Name);
if (!(originalSong is LocalAudio))
{
return;
}
//Copy media object to not interfere with other threads
LocalAudio songCopy = new LocalAudio((LocalAudio)originalSong);
try
{
//Load only if not already loaded. (Multiple clients may be requesting media)
if (!songCopy.IsLoaded)
{
await songCopy.Load();
}
//Send stream
Console.WriteLine("Begin sending file");
byte[] buffer = new byte[2048]; // read in chunks of 2KB
int bytesRead;
while ((bytesRead = songCopy.DataStream.Read(buffer, 0, buffer.Length)) > 0)
{
Google.Protobuf.ByteString bufferByteString = Google.Protobuf.ByteString.CopyFrom(buffer);
await responseStream.WriteAsync(new Chunk { Content = bufferByteString });
}
Console.WriteLine("Done sending file");
}
catch (Exception ex)
{
Console.WriteLine("Exception caught while sending audio file: " + ex.Message);
}
}
public override async Task SyncMedia(SyncMediaRequest request, Grpc.Core.IServerStreamWriter<Sync> responseStream, Grpc.Core.ServerCallContext context)
{
bool continueSync = true;
using (var scope = App.Container.BeginLifetimeScope())
{
IPlayer player = scope.Resolve<IPlayer>();
string currentId = player.CurrentMedia.Id;
MediaChangedEventHandler mediaChanged = (sender, e) =>
{
if (e.NewId != currentId)
{
continueSync = false;
}
};
player.MediaChanged += mediaChanged;
while (continueSync)
{
float length = player.CurrentMediaLength;
Sync sync = new Sync()
{
TrackPosition = player.CurrentMediaPosition,
ServerTimeTicks = Utils.TimeUtils.GetNetworkTime().DateTime.Ticks
};
await responseStream.WriteAsync(sync);
Console.WriteLine("Sent Sync");
await Task.Delay(5000);
}
}
}
}
}

View File

@ -25,19 +25,21 @@ namespace Aurora.Services.Server.Controllers
startIdx = _memberList.IndexOfKey(request.PageToken) + 1;
}
int pageSize = request.PageSize;
//Assign pageSize
if (request.PageSize > _memberList.Count)
if (pageSize > _memberList.Count)
{
request.PageSize = _memberList.Count;
pageSize = _memberList.Count;
}
//Gather page
List<Member> members = new List<Member>(_memberList.Values);
resp.Members.AddRange(members.GetRange(startIdx, request.PageSize));
resp.Members.AddRange(members.GetRange(startIdx, pageSize));
//Set next page token
resp.NextPageToken = resp.Members[(startIdx + request.PageSize) - 1].Name;
resp.NextPageToken = resp.Members[resp.Members.Count - 1].Name;
return Task.FromResult(resp);
}

View File

@ -17,30 +17,6 @@ namespace Aurora.Services.Server.Controllers
private EventManager.EventManager _eventManager;
/// <summary>
/// Constructor for partial class
/// </summary>
public RemotePartyController(string partyName, string description)
{
this._startDateTime = DateTime.UtcNow;
this._displayName = partyName;
this._description = description;
this._memberList = new SortedList<string, Member>();
string userName = "testUser";
this._eventManager = new EventManager.EventManager();
this._hostMember = new Member()
{
Name = GetNewMemberResourceName(_partyResourceName, ServerService.GetLocalIPAddress(), userName),
UserName = userName,
IpAddress = ServerService.GetLocalIPAddress(),
};
this._memberList.Add(_hostMember.Name, _hostMember);
}
public override Task<Party> GetParty(Proto.General.Empty request, Grpc.Core.ServerCallContext context)
{
Party party = new Party()

View File

@ -8,13 +8,14 @@ using Aurora.Proto.Events;
using Aurora.Proto.Party;
using Aurora.Proto.Playback;
using Aurora.Proto.Sync;
using Aurora.Services.Settings;
using Autofac;
namespace Aurora.Services
{
public class ServerService : BaseService<ServerService>
{
private int _port = SettingsService.Instance.DefaultPort;
private int _port;
private string _hostname;
private Grpc.Core.Server _server;
@ -30,6 +31,11 @@ namespace Aurora.Services
public ServerService()
{
string host = GetLocalIPAddress();
using (var scope = App.Container.BeginLifetimeScope())
{
var service = scope.Resolve<ISettingsService>();
this._port = service.DefaultPort;
}
if (string.IsNullOrWhiteSpace(host))
{

View File

@ -0,0 +1,27 @@
using Plugin.Settings.Abstractions;
namespace Aurora.Services.Settings
{
public interface ISettingsService
{
ISettings AppSettings { get; set; }
/// <summary>
/// The user's username. This is persisted.
/// </summary>
/// <value></value>
string Username { get; set; }
/// <summary>
/// The default port to use. This is persisted.
/// </summary>
/// <value></value>
int DefaultPort { get; set; }
/// <summary>
/// The current sessions clientId. This is assigned by the server. This is not persisted.
/// </summary>
/// <value></value>
string ClientId { get; set; }
}
}

View File

@ -3,9 +3,9 @@ using System.Threading;
using Plugin.Settings;
using Plugin.Settings.Abstractions;
namespace Aurora.Services
namespace Aurora.Services.Settings
{
public class SettingsService : BaseService<SettingsService>
public class SettingsService : ISettingsService
{
private Lazy<ISettings> _appSettings;
private string _usernameKey = "username";