381 lines
11 KiB
C#
381 lines
11 KiB
C#
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Threading.Tasks;
|
|
using System.Linq;
|
|
using Xamarin.Forms;
|
|
using Aurora.Services;
|
|
using Aurora.Proto.General;
|
|
using Aurora.Proto.Party;
|
|
using Aurora.Proto.Events;
|
|
using Aurora.Services.ClientService;
|
|
using Aurora.Services.PlayerService;
|
|
using Aurora.Models.Media;
|
|
|
|
namespace Aurora.Design.Views.Party
|
|
{
|
|
enum PartyState
|
|
{
|
|
SelectingHost,
|
|
InParty,
|
|
Hosting,
|
|
Connecting,
|
|
}
|
|
|
|
public class PartyViewModel : BaseViewModel
|
|
{
|
|
private PartyState _state;
|
|
private string _hostname;
|
|
private ObservableCollection<PartyMember> _members;
|
|
private ObservableCollection<BaseMedia> _queue;
|
|
private BaseMedia _selectedMedia;
|
|
private PlayerService _player;
|
|
|
|
public PartyViewModel()
|
|
{
|
|
this.JoinCommand = new Command(OnJoinExecute, CanJoinExecute);
|
|
this.HostCommand = new Command(OnHostExecute, CanHostExecute);
|
|
|
|
_members = new ObservableCollection<PartyMember>();
|
|
_queue = new ObservableCollection<BaseMedia>();
|
|
|
|
SetState(PartyState.SelectingHost);
|
|
this._player = PlayerService.Instance;
|
|
|
|
PlayCommand = new Command(OnPlayExecute);
|
|
|
|
//Hook up event handler
|
|
ClientService.Instance.EventReceived += this.OnEventReceived;
|
|
}
|
|
|
|
~PartyViewModel()
|
|
{
|
|
//Task.Run(ServerService.Instance.Stop);
|
|
}
|
|
|
|
#region Properties
|
|
|
|
/// <summary>
|
|
/// Publc property for the members list
|
|
/// </summary>
|
|
/// <value></value>
|
|
public ObservableCollection<PartyMember> Members
|
|
{
|
|
get
|
|
{
|
|
return _members;
|
|
}
|
|
set
|
|
{
|
|
SetProperty(ref _members, value);
|
|
}
|
|
}
|
|
|
|
public bool IsSelectingHost
|
|
{
|
|
get { return _state == PartyState.SelectingHost; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Public property indicating the state.
|
|
/// </summary>
|
|
/// <value></value>
|
|
public bool IsNotSelectingHost
|
|
{
|
|
get { return _state != PartyState.SelectingHost; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Public property for queue item source
|
|
/// </summary>
|
|
/// <value></value>
|
|
public ObservableCollection<BaseMedia> Queue
|
|
{
|
|
get
|
|
{
|
|
return _queue;
|
|
}
|
|
set
|
|
{
|
|
if (value != _queue)
|
|
{
|
|
SetProperty(ref _queue, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Public property for the hostname bindable field
|
|
/// </summary>
|
|
/// <value></value>
|
|
public string Hostname
|
|
{
|
|
get { return _hostname; }
|
|
set { SetProperty(ref _hostname, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Public property for the currently selected song.
|
|
/// </summary>
|
|
/// <value></value>
|
|
public BaseMedia SelectedSong
|
|
{
|
|
get { return _selectedMedia; }
|
|
set { SetProperty(ref _selectedMedia, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Public property for playing media
|
|
/// </summary>
|
|
/// <value></value>
|
|
public Command PlayCommand { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Public property for join command
|
|
/// </summary>
|
|
/// <value></value>
|
|
public Command JoinCommand { get; set; }
|
|
|
|
/// <summary>
|
|
/// Pubic property for host command
|
|
/// </summary>
|
|
/// <value></value>
|
|
public Command HostCommand { get; set; }
|
|
|
|
#endregion Properties
|
|
|
|
#region Events
|
|
public override void OnActive()
|
|
{
|
|
//TODO
|
|
//If in party subscribe to events
|
|
//If in party get events
|
|
}
|
|
|
|
public override void OnInactive()
|
|
{
|
|
//TODO
|
|
//unsubscribe
|
|
//stop getting events
|
|
}
|
|
|
|
/// <summary>
|
|
/// An event handler for the client receiving update events
|
|
/// </summary>
|
|
/// <param name="sender">The object that sent the event</param>
|
|
/// <param name="eventArgs">The event arguments</param>
|
|
public void OnEventReceived(object sender, EventReceivedEventArgs eventArgs)
|
|
{
|
|
switch (eventArgs.BaseEvent.DerivedEventCase)
|
|
{
|
|
case BaseEvent.DerivedEventOneofCase.None:
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
case BaseEvent.DerivedEventOneofCase.PartyMemberJoinedEvent:
|
|
{
|
|
PartyMemberJoinedEvent derivedEvent = eventArgs.BaseEvent.PartyMemberJoinedEvent;
|
|
PartyMember member = new PartyMember
|
|
{
|
|
UserName = derivedEvent.Member.UserName,
|
|
Id = derivedEvent.Member.Id,
|
|
IpAddress = derivedEvent.Member.IpAddress,
|
|
Port = derivedEvent.Member.Port
|
|
};
|
|
|
|
Members.Add(member);
|
|
|
|
break;
|
|
}
|
|
case BaseEvent.DerivedEventOneofCase.PartyMemberLeftEvent:
|
|
{
|
|
PartyMemberJoinedEvent derivedEvent = eventArgs.BaseEvent.PartyMemberJoinedEvent;
|
|
var found = Members.Where(x => x.Id == derivedEvent.Member.Id);
|
|
foreach (PartyMember member in found)
|
|
{
|
|
_members.Remove(member);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Events
|
|
|
|
#region Commands
|
|
private async void OnJoinExecute()
|
|
{
|
|
SetState(PartyState.Connecting);
|
|
ClientService.Instance.Start(Hostname, SettingsService.Instance.DefaultPort.ToString());
|
|
await JoinParty();
|
|
|
|
SetState(PartyState.InParty);
|
|
}
|
|
|
|
private bool CanJoinExecute()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
private async void OnHostExecute()
|
|
{
|
|
//Change state
|
|
SetState(PartyState.Connecting);
|
|
ServerService.Instance.Start();
|
|
string localHost = ServerService.GetLocalIPAddress();
|
|
ClientService.Instance.Start(localHost, SettingsService.Instance.DefaultPort.ToString());
|
|
await JoinParty();
|
|
|
|
try
|
|
{
|
|
SetState(PartyState.Hosting);
|
|
await ClientService.Instance.GetEvents().ConfigureAwait(true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine("Exception occurred while receiviing events: ", ex.Message);
|
|
}
|
|
}
|
|
|
|
private bool CanHostExecute()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
#endregion Commands
|
|
|
|
#region Private Methods
|
|
/// <summary>
|
|
/// Join the remote party.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task JoinParty()
|
|
{
|
|
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)
|
|
{
|
|
case PlaybackState.Buffering:
|
|
{
|
|
_player.Play();
|
|
break;
|
|
}
|
|
case PlaybackState.Playing:
|
|
{
|
|
_player.Pause();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override bool CanPlayExecute()
|
|
{
|
|
return this._state == PartyState.Hosting;
|
|
}
|
|
|
|
public override bool CanNextExecute()
|
|
{
|
|
return this._state == PartyState.Hosting;
|
|
}
|
|
|
|
public override bool CanPreviousExecute()
|
|
{
|
|
return this._state == PartyState.Hosting;
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |