I think i've got simultaneous playback working but it is hard to test
This commit is contained in:
@ -9,10 +9,12 @@ using Aurora.Proto.Party;
|
||||
using Aurora.Proto.Events;
|
||||
using Aurora.Services.ClientService;
|
||||
using Aurora.Services.PlayerService;
|
||||
using Aurora.Services.EventManager;
|
||||
using Aurora.Models.Media;
|
||||
|
||||
namespace Aurora.Design.Views.Party
|
||||
{
|
||||
//TODO refactor
|
||||
enum PartyState
|
||||
{
|
||||
SelectingHost,
|
||||
@ -29,6 +31,7 @@ namespace Aurora.Design.Views.Party
|
||||
private ObservableCollection<BaseMedia> _queue;
|
||||
private BaseMedia _selectedMedia;
|
||||
private PlayerService _player;
|
||||
private ClientService _client;
|
||||
|
||||
public PartyViewModel()
|
||||
{
|
||||
@ -41,10 +44,12 @@ namespace Aurora.Design.Views.Party
|
||||
SetState(PartyState.SelectingHost);
|
||||
this._player = PlayerService.Instance;
|
||||
|
||||
PlayCommand = new Command(OnPlayExecute);
|
||||
PlayCommand = new Command(OnDoubleClickExecute, CanDoubleClickExecute);
|
||||
|
||||
_client = ClientService.Instance;
|
||||
|
||||
//Hook up event handler
|
||||
ClientService.Instance.EventReceived += this.OnEventReceived;
|
||||
_client.EventReceived += this.OnEventReceived;
|
||||
}
|
||||
|
||||
~PartyViewModel()
|
||||
@ -198,6 +203,18 @@ namespace Aurora.Design.Views.Party
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BaseEvent.DerivedEventOneofCase.MediaPlayingEvent:
|
||||
{
|
||||
MediaPlayingEvent derivedEvent = eventArgs.BaseEvent.MediaPlayingEvent;
|
||||
Play(derivedEvent);
|
||||
break;
|
||||
}
|
||||
case BaseEvent.DerivedEventOneofCase.MediaPausedEvent:
|
||||
{
|
||||
MediaPausedEvent derivedEvent = eventArgs.BaseEvent.MediaPausedEvent;
|
||||
StopPlaying();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,7 +224,7 @@ namespace Aurora.Design.Views.Party
|
||||
private async void OnJoinExecute()
|
||||
{
|
||||
SetState(PartyState.Connecting);
|
||||
ClientService.Instance.Start(Hostname, SettingsService.Instance.DefaultPort.ToString());
|
||||
_client.Start(Hostname, SettingsService.Instance.DefaultPort.ToString());
|
||||
await JoinParty();
|
||||
|
||||
SetState(PartyState.InParty);
|
||||
@ -224,13 +241,16 @@ namespace Aurora.Design.Views.Party
|
||||
SetState(PartyState.Connecting);
|
||||
ServerService.Instance.Start();
|
||||
string localHost = ServerService.GetLocalIPAddress();
|
||||
ClientService.Instance.Start(localHost, SettingsService.Instance.DefaultPort.ToString());
|
||||
_client.IsHost = true;
|
||||
_client.Start(localHost, SettingsService.Instance.DefaultPort.ToString());
|
||||
await JoinParty();
|
||||
|
||||
|
||||
//TODO add cancellation token
|
||||
try
|
||||
{
|
||||
SetState(PartyState.Hosting);
|
||||
await ClientService.Instance.GetEvents().ConfigureAwait(true);
|
||||
await _client.GetEvents().ConfigureAwait(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -243,108 +263,8 @@ namespace Aurora.Design.Views.Party
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endregion Commands
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Join the remote party.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task JoinParty()
|
||||
public override void OnPlayButtonExecute()
|
||||
{
|
||||
try
|
||||
{
|
||||
JoinPartyResponse resp = await ClientService.Instance.RemotePartyClient.JoinPartyAsync(new JoinPartyRequest
|
||||
{
|
||||
UserName = SettingsService.Instance.Username,
|
||||
});
|
||||
|
||||
SettingsService.Instance.ClientId = resp.ClientId;
|
||||
|
||||
RefreshMembers();
|
||||
|
||||
//Subscribe to events
|
||||
SubscribeRequest req = new SubscribeRequest();
|
||||
req.EventTypes.Add(EventType.PartyMemberJoined);
|
||||
req.EventTypes.Add(EventType.PartyMemberLeft);
|
||||
if (!string.IsNullOrWhiteSpace(SettingsService.Instance.ClientId))
|
||||
{
|
||||
req.ClientId = SettingsService.Instance.ClientId;
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine(string.Format("CLIENT {0} - SubscribeToEvents called from client with id", SettingsService.Instance.ClientId));
|
||||
ClientService.Instance.RemoteEventClient.SubscribeToEvents(req);
|
||||
|
||||
QueueResponse queueResponse = ClientService.Instance.RemotePartyClient.GetQueue(new Empty());
|
||||
|
||||
Queue.Clear();
|
||||
//Convert received data to remote audio models
|
||||
foreach (RemoteMediaData data in queueResponse.MediaList)
|
||||
{
|
||||
//Assign received metadata (since this can't be aquired from a file)
|
||||
AudioMetadata meta = new AudioMetadata();
|
||||
meta.Title = data.Title;
|
||||
meta.Album = data.Album;
|
||||
meta.Artist = data.Artist;
|
||||
meta.Duration = data.Duration;
|
||||
|
||||
RemoteAudio remote = new RemoteAudio(data.Id,
|
||||
meta,
|
||||
ClientService.Instance.RemotePartyClient);
|
||||
|
||||
Queue.Add(remote);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error subscribing to events: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LeaveParty()
|
||||
{
|
||||
//Stop receiving events
|
||||
ClientService.Instance.StopEvents();
|
||||
|
||||
//Unsubscribe
|
||||
UnsubscribeAllRequest unsubscribeReq = new UnsubscribeAllRequest();
|
||||
await ClientService.Instance.RemoteEventClient.UnsubscribeFromAllAsync(unsubscribeReq);
|
||||
|
||||
//Leave party
|
||||
LeavePartyRequest leaveReq = new LeavePartyRequest();
|
||||
await ClientService.Instance.RemotePartyClient.LeavePartyAsync(leaveReq);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh members list.
|
||||
/// </summary>
|
||||
private void RefreshMembers()
|
||||
{
|
||||
MembersResponse response = ClientService.Instance.RemotePartyClient.GetPartyMembers(new Empty());
|
||||
//Add members
|
||||
foreach (PartyMember member in response.Members)
|
||||
{
|
||||
Members.Add(member);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetState(PartyState state)
|
||||
{
|
||||
_state = state;
|
||||
OnPropertyChanged("IsSelectingHost");
|
||||
OnPropertyChanged("IsNotSelectingHost");
|
||||
}
|
||||
|
||||
public override async void OnPlayExecute()
|
||||
{
|
||||
base.Media = this._selectedMedia;
|
||||
if (!_player.IsMediaLoaded(base.Media))
|
||||
{
|
||||
await _player.LoadMedia(base.Media).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
_player.Play();
|
||||
switch (_player.PlaybackState)
|
||||
{
|
||||
@ -361,21 +281,163 @@ namespace Aurora.Design.Views.Party
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanPlayExecute()
|
||||
public override bool CanPlayButtonExecute()
|
||||
{
|
||||
return this._state == PartyState.Hosting && this._player.IsLoaded;
|
||||
}
|
||||
|
||||
public override bool CanNextButtonExecute()
|
||||
{
|
||||
return this._state == PartyState.Hosting;
|
||||
}
|
||||
|
||||
public override bool CanNextExecute()
|
||||
public override bool CanPreviousButtonExecute()
|
||||
{
|
||||
return this._state == PartyState.Hosting;
|
||||
}
|
||||
|
||||
public override bool CanPreviousExecute()
|
||||
/// <summary>
|
||||
/// On double click execute, fire media playing event
|
||||
/// </summary>
|
||||
public void OnDoubleClickExecute()
|
||||
{
|
||||
AudioMetadata meta = _selectedMedia.Metadata as AudioMetadata;
|
||||
MediaPlayingEvent mediaPlaying = new MediaPlayingEvent()
|
||||
{
|
||||
Media = new RemoteMediaData()
|
||||
{
|
||||
Id = _selectedMedia.Id,
|
||||
Title = meta.Title,
|
||||
Artist = meta.Artist,
|
||||
Album = meta.Album,
|
||||
}
|
||||
};
|
||||
|
||||
EventManager.Instance.FireEvent(new BaseEvent()
|
||||
{
|
||||
MediaPlayingEvent = mediaPlaying
|
||||
});
|
||||
}
|
||||
|
||||
public bool CanDoubleClickExecute()
|
||||
{
|
||||
return this._state == PartyState.Hosting;
|
||||
}
|
||||
|
||||
|
||||
#endregion Commands
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Join the remote party.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task JoinParty()
|
||||
{
|
||||
try
|
||||
{
|
||||
JoinPartyResponse resp = await _client.RemotePartyClient.JoinPartyAsync(new JoinPartyRequest
|
||||
{
|
||||
UserName = SettingsService.Instance.Username,
|
||||
});
|
||||
|
||||
SettingsService.Instance.ClientId = resp.ClientId;
|
||||
|
||||
RefreshMembers();
|
||||
|
||||
//Subscribe to events
|
||||
SubscribeRequest req = new SubscribeRequest();
|
||||
req.EventTypes.Add(EventType.PartyMemberJoined);
|
||||
req.EventTypes.Add(EventType.PartyMemberLeft);
|
||||
req.EventTypes.Add(EventType.MediaPlaying);
|
||||
req.EventTypes.Add(EventType.MediaStopped);
|
||||
if (!string.IsNullOrWhiteSpace(SettingsService.Instance.ClientId))
|
||||
{
|
||||
req.ClientId = SettingsService.Instance.ClientId;
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine(string.Format("CLIENT {0} - SubscribeToEvents called from client with id", SettingsService.Instance.ClientId));
|
||||
_client.RemoteEventClient.SubscribeToEvents(req);
|
||||
|
||||
QueueResponse queueResponse = _client.RemotePartyClient.GetQueue(new Empty());
|
||||
|
||||
Queue.Clear();
|
||||
//Convert received data to remote audio models
|
||||
foreach (RemoteMediaData data in queueResponse.MediaList)
|
||||
{
|
||||
//Assign received metadata (since this can't be aquired from a file)
|
||||
AudioMetadata meta = new AudioMetadata();
|
||||
meta.Title = data.Title;
|
||||
meta.Album = data.Album;
|
||||
meta.Artist = data.Artist;
|
||||
meta.Duration = data.Duration;
|
||||
|
||||
RemoteAudio remote = new RemoteAudio(data.Id,
|
||||
meta,
|
||||
_client.RemotePartyClient);
|
||||
|
||||
Queue.Add(remote);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error subscribing to events: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LeaveParty()
|
||||
{
|
||||
//Stop receiving events
|
||||
_client.StopEvents();
|
||||
|
||||
//Unsubscribe
|
||||
UnsubscribeAllRequest unsubscribeReq = new UnsubscribeAllRequest();
|
||||
await _client.RemoteEventClient.UnsubscribeFromAllAsync(unsubscribeReq);
|
||||
|
||||
//Leave party
|
||||
LeavePartyRequest leaveReq = new LeavePartyRequest();
|
||||
await _client.RemotePartyClient.LeavePartyAsync(leaveReq);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh members list.
|
||||
/// </summary>
|
||||
private void RefreshMembers()
|
||||
{
|
||||
MembersResponse response = _client.RemotePartyClient.GetPartyMembers(new Empty());
|
||||
//Add members
|
||||
foreach (PartyMember member in response.Members)
|
||||
{
|
||||
Members.Add(member);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetState(PartyState state)
|
||||
{
|
||||
_state = state;
|
||||
OnPropertyChanged("IsSelectingHost");
|
||||
OnPropertyChanged("IsNotSelectingHost");
|
||||
}
|
||||
|
||||
private async void Play(MediaPlayingEvent args)
|
||||
{
|
||||
//TODO this design assumes all played music is in a queue
|
||||
//TODO this is a slow design depending on size of queue
|
||||
if (_queue.Any((BaseMedia media) => media.Id == args.Media.Id))
|
||||
{
|
||||
BaseMedia media = _queue.First((BaseMedia med) => med.Id == args.Media.Id);
|
||||
base.Media = media;
|
||||
await _player.LoadMedia(base.Media).ConfigureAwait(true);
|
||||
_player.Play();
|
||||
}
|
||||
}
|
||||
|
||||
private void StopPlaying()
|
||||
{
|
||||
_player.Pause();
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user