Migrate aurora-sharp-desktop
This commit is contained in:
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Generic;
|
||||
using Aurora.Proto.Party;
|
||||
using Aurora.Services.Library;
|
||||
using Aurora.Services.Settings;
|
||||
using Aurora.Models.Media;
|
||||
using Aurora.Services.EventManager;
|
||||
using Autofac;
|
||||
|
||||
namespace Aurora.Services.Server.Controllers
|
||||
{
|
||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||
{
|
||||
private ILibraryService _libraryService;
|
||||
private ISettingsService _settingsService;
|
||||
private IEventManager _eventManager;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for partial class
|
||||
/// </summary>
|
||||
public RemotePartyController(string partyName, string description, ILibraryService libraryService, ISettingsService settingsService, IEventManager eventManager)
|
||||
{
|
||||
this._startDateTime = DateTime.UtcNow;
|
||||
this._displayName = partyName;
|
||||
this._description = description;
|
||||
this._memberList = new SortedList<string, Member>();
|
||||
this._mediaList = new SortedList<string, Media>();
|
||||
|
||||
_libraryService = libraryService;
|
||||
this._settingsService = settingsService;
|
||||
|
||||
string userName = _settingsService.Username;
|
||||
|
||||
this._eventManager = eventManager;
|
||||
|
||||
this._hostMember = new Member()
|
||||
{
|
||||
Name = GetNewMemberResourceName(_partyResourceName, ServerService.GetLocalIPAddress(), userName),
|
||||
UserName = userName,
|
||||
IpAddress = ServerService.GetLocalIPAddress(),
|
||||
};
|
||||
|
||||
//Add media from library
|
||||
//This will change as queuing operation gets solidified
|
||||
//Simply return the hosts library
|
||||
ObservableCollection<BaseMedia> queue = _libraryService.GetLibrary();
|
||||
|
||||
|
||||
foreach (BaseMedia media in queue)
|
||||
{
|
||||
AudioMetadata metadata = new AudioMetadata();
|
||||
try
|
||||
{
|
||||
if (media.Metadata is AudioMetadata)
|
||||
{
|
||||
metadata = media.Metadata as AudioMetadata;
|
||||
|
||||
Media data = new Media();
|
||||
data.Name = string.Format("{0}/{1}", partyName, media.Id);
|
||||
if (metadata.Title != null)
|
||||
{
|
||||
data.Title = metadata.Title;
|
||||
}
|
||||
if (metadata.Artist != null)
|
||||
{
|
||||
data.Artist = metadata.Artist;
|
||||
}
|
||||
if (metadata.Album != null)
|
||||
{
|
||||
data.Album = metadata.Album;
|
||||
}
|
||||
if (metadata.Duration != null)
|
||||
{
|
||||
data.Duration = metadata.Duration;
|
||||
}
|
||||
|
||||
_mediaList.Add(data.Name, data);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(string.Format("Error preparing queue: {0}", ex.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using Aurora.Proto.Party;
|
||||
using Aurora.Utils;
|
||||
|
||||
namespace Aurora.Services.Server.Controllers
|
||||
{
|
||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||
{
|
||||
public override Task GetEvents(GetEventsRequest request, Grpc.Core.IServerStreamWriter<BaseEvent> responseStream, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
string peerId = Misc.Combine(new string[] { context.Peer, request.Parent });
|
||||
Console.WriteLine(string.Format("SERVER - Events request received from peer: {0}", peerId));
|
||||
|
||||
AutoResetEvent are = new AutoResetEvent(false);
|
||||
Action<BaseEvent> callback = (BaseEvent bEvent) =>
|
||||
{
|
||||
Console.WriteLine(string.Format("SERVER - Event fired for peer: {0}", peerId));
|
||||
//TODO need to remove callback if stream no longer exists IE. Client crashed or stopped
|
||||
responseStream.WriteAsync(bEvent);
|
||||
|
||||
};
|
||||
|
||||
Action cancelled = () =>
|
||||
{
|
||||
are.Set();
|
||||
};
|
||||
|
||||
this._eventManager.AddEventHandler(callback, cancelled, Misc.Combine(new string[] { context.Peer, request.Parent }));
|
||||
are.WaitOne();
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Aurora.Proto.Party;
|
||||
using Aurora.Proto.General;
|
||||
using Aurora.Utils;
|
||||
|
||||
namespace Aurora.Services.Server.Controllers
|
||||
{
|
||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||
{
|
||||
public override Task<ListEventSubscriptionsResponse> ListEventSubscriptions(
|
||||
ListEventSubscriptionsRequest request,
|
||||
Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<EventSubscription> CreateEventSubscription(
|
||||
CreateEventSubscriptionRequest request,
|
||||
Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
Console.WriteLine(string.Format("SERVER - Subscription from client with id: {0}", request.Parent));
|
||||
this._eventManager.AddSubscription(Misc.Combine(new string[] { context.Peer, request.Parent }), request.EventSubscription.Type);
|
||||
|
||||
return Task.FromResult(request.EventSubscription);
|
||||
}
|
||||
|
||||
public override Task<CreateEventSubscriptionListResponse> CreateEventSubscriptionList(
|
||||
CreateEventSubscriptionListRequest request,
|
||||
Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
Console.WriteLine(string.Format("SERVER - Subscription from client with id: {0}", request.Parent));
|
||||
|
||||
List<EventType> eventTypes = new List<EventType>();
|
||||
foreach (EventSubscription subscription in request.EventSubscriptions)
|
||||
{
|
||||
eventTypes.Add(subscription.Type);
|
||||
}
|
||||
|
||||
this._eventManager.AddSubscriptionList(Misc.Combine(new string[] { context.Peer, request.Parent }), eventTypes);
|
||||
|
||||
CreateEventSubscriptionListResponse resp = new CreateEventSubscriptionListResponse();
|
||||
resp.EventSubscriptions.AddRange(request.EventSubscriptions);
|
||||
return Task.FromResult(resp);
|
||||
}
|
||||
|
||||
public override Task<Empty> DeleteEventSubscription(
|
||||
DeleteEventSubscriptionRequest request,
|
||||
Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
this._eventManager.RemoveSubscription(Misc.Combine(new string[] { context.Peer, request.Parent }), request.Type);
|
||||
|
||||
return Task.FromResult(new Empty());
|
||||
}
|
||||
|
||||
public override Task<Empty> DeleteAllEventSubscriptions(
|
||||
DeleteAllEventSubscriptionsRequest request,
|
||||
Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
this._eventManager.RemoveAllSubscriptions(Misc.Combine(new string[] { context.Peer, request.Parent }));
|
||||
|
||||
return Task.FromResult(new Empty());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Aurora.Proto.Party;
|
||||
using Aurora.Models.Media;
|
||||
using Aurora.Proto.General;
|
||||
using Aurora.Services.Library;
|
||||
using Aurora.Services.Player;
|
||||
using Autofac;
|
||||
|
||||
namespace Aurora.Services.Server.Controllers
|
||||
{
|
||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||
{
|
||||
private SortedList<string, Media> _mediaList;
|
||||
|
||||
public override Task<ListMediaResponse> ListMedia(ListMediaRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
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<Media> mediaList = new List<Media>(_mediaList.Values);
|
||||
resp.Media.AddRange(mediaList.GetRange(startIdx, pageSize));
|
||||
|
||||
resp.NextPageToken = resp.Media[resp.Media.Count - 1].Name;
|
||||
return Task.FromResult(resp);
|
||||
}
|
||||
|
||||
public override Task<Media> GetMedia(GetMediaRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
_mediaList.TryGetValue(request.Name, out Media baseMedia);
|
||||
|
||||
if (baseMedia == null)
|
||||
{
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
|
||||
return Task.FromResult(baseMedia);
|
||||
}
|
||||
|
||||
public override Task<Media> CreateMedia(CreateMediaRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<Empty> DeleteMedia(DeleteMediaRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task StreamMedia(StreamMediaRequest request, Grpc.Core.IServerStreamWriter<Proto.General.Chunk> responseStream, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
using (var scope = App.Container.BeginLifetimeScope())
|
||||
{
|
||||
ILibraryService library = scope.Resolve<ILibraryService>();
|
||||
|
||||
string mediaName = request.Name.Split('/')[1];
|
||||
|
||||
BaseMedia originalSong = library.GetSong(mediaName);
|
||||
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())
|
||||
{
|
||||
try
|
||||
{
|
||||
IPlayer player = scope.Resolve<IPlayer>();
|
||||
|
||||
string currentId = player.CurrentMedia.Id;
|
||||
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);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error sending sync: " + ex.Message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Aurora.Proto.Party;
|
||||
using Aurora.Proto.General;
|
||||
using Aurora.Utils;
|
||||
using Grpc.Core;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace Aurora.Services.Server.Controllers
|
||||
{
|
||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||
{
|
||||
private SortedList<string, Member> _memberList;
|
||||
|
||||
public override Task<ListMembersResponse> ListMembers(ListMembersRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
//Ignoring parent field because there is only one instance of the party
|
||||
ListMembersResponse resp = new ListMembersResponse();
|
||||
|
||||
//Determine start idx
|
||||
int startIdx = 0;
|
||||
if (!string.IsNullOrEmpty(request.PageToken))
|
||||
{
|
||||
startIdx = _memberList.IndexOfKey(request.PageToken) + 1;
|
||||
}
|
||||
|
||||
int pageSize = request.PageSize;
|
||||
|
||||
//Assign pageSize
|
||||
if (pageSize > _memberList.Count)
|
||||
{
|
||||
pageSize = _memberList.Count;
|
||||
}
|
||||
|
||||
|
||||
//Gather page
|
||||
List<Member> members = new List<Member>(_memberList.Values);
|
||||
resp.Members.AddRange(members.GetRange(startIdx, pageSize));
|
||||
|
||||
//Set next page token
|
||||
resp.NextPageToken = resp.Members[resp.Members.Count - 1].Name;
|
||||
|
||||
return Task.FromResult(resp);
|
||||
}
|
||||
|
||||
public override Task<Member> GetMember(GetMemberRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
_memberList.TryGetValue(request.Name, out Member member);
|
||||
|
||||
if (member == null)
|
||||
{
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
|
||||
return Task.FromResult(member);
|
||||
}
|
||||
|
||||
public override Task<Member> UpdateMember(UpdateMemberRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<Member> CreateMember(CreateMemberRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
//Generate Guid
|
||||
string resourceName = GetNewMemberResourceName(request.Parent, context.Peer, request.Member.UserName);
|
||||
|
||||
//Check if already added
|
||||
if (_memberList.ContainsKey(resourceName))
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.AlreadyExists, "Member already exists"));
|
||||
}
|
||||
|
||||
request.Member.Name = resourceName;
|
||||
request.Member.AddedOn = Timestamp.FromDateTime(DateTime.UtcNow);
|
||||
request.Member.IpAddress = context.Host;
|
||||
|
||||
_memberList.Add(resourceName, request.Member);
|
||||
|
||||
BaseEvent @event = new BaseEvent
|
||||
{
|
||||
EventType = EventType.MemberCreated,
|
||||
MemberCreatedEvent = new MemberCreatedEvent
|
||||
{
|
||||
Member = request.Member,
|
||||
}
|
||||
};
|
||||
|
||||
//Fire event manager event
|
||||
this._eventManager.FireEvent(@event);
|
||||
|
||||
return Task.FromResult(request.Member);
|
||||
}
|
||||
|
||||
public override Task<Aurora.Proto.General.Empty> DeleteMember(DeleteMemberRequest request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
string memberResourceName = request.Name;
|
||||
//Check if member exists
|
||||
if (!_memberList.ContainsKey(request.Name))
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "Member not found"));
|
||||
}
|
||||
|
||||
_memberList.Remove(memberResourceName);
|
||||
|
||||
BaseEvent @event = new BaseEvent
|
||||
{
|
||||
EventType = EventType.MemberDeleted,
|
||||
MemberDeletedEvent = new MemberDeletedEvent
|
||||
{
|
||||
MemberName = memberResourceName,
|
||||
}
|
||||
};
|
||||
|
||||
_eventManager.FireEvent(@event);
|
||||
_eventManager.RemoveAllSubscriptions(memberResourceName);
|
||||
_eventManager.CancelEventStream(memberResourceName);
|
||||
|
||||
return Task.FromResult(new Aurora.Proto.General.Empty());
|
||||
}
|
||||
|
||||
private string GetNewMemberResourceName(string parent, string contextPeer, string userName)
|
||||
{
|
||||
string memberNameGuid = HashUtil.GetHash(new string[] { contextPeer, userName }).ToString();
|
||||
return string.Format("{0}/members/{1}", parent, memberNameGuid);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Aurora.Proto.Party;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
|
||||
namespace Aurora.Services.Server.Controllers
|
||||
{
|
||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||
{
|
||||
private string _partyResourceName = "party/party1";
|
||||
private string _displayName;
|
||||
private string _description;
|
||||
private Member _hostMember;
|
||||
private DateTime _startDateTime;
|
||||
|
||||
public override Task<Party> GetParty(Proto.General.Empty request, Grpc.Core.ServerCallContext context)
|
||||
{
|
||||
Party party = new Party()
|
||||
{
|
||||
Name = _partyResourceName,
|
||||
DisplayName = this._displayName,
|
||||
Description = this._description,
|
||||
HostIp = ServerService.GetLocalIPAddress(),
|
||||
HostMember = this._hostMember,
|
||||
CreatedOn = Timestamp.FromDateTime(_startDateTime)
|
||||
};
|
||||
|
||||
return Task.FromResult(party);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user