diff --git a/aurora-sharp-desktop/Aurora/App.xaml.cs b/aurora-sharp-desktop/Aurora/App.xaml.cs index 487ba7d..aa57897 100644 --- a/aurora-sharp-desktop/Aurora/App.xaml.cs +++ b/aurora-sharp-desktop/Aurora/App.xaml.cs @@ -41,6 +41,7 @@ namespace Aurora _builder.RegisterType(); _builder.RegisterType(); _builder.RegisterType(); + _builder.RegisterType(); _builder.RegisterType(); // _builder.RegisterInstance(new SettingsService()).SingleInstance(); diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Controls/NavigationMenu/NavigationItem.cs b/aurora-sharp-desktop/Aurora/UserInterface/Controls/NavigationMenu/NavigationItem.cs index 4571caa..cd78820 100644 --- a/aurora-sharp-desktop/Aurora/UserInterface/Controls/NavigationMenu/NavigationItem.cs +++ b/aurora-sharp-desktop/Aurora/UserInterface/Controls/NavigationMenu/NavigationItem.cs @@ -12,7 +12,6 @@ namespace Aurora.Design.Components.NavigationMenu public NavigationItem() { } - public int Id { get; set; } public string Title { get; set; } public string Group { get; set; } public Type TargetType { get; set; } diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/BasePlayerViewModel.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/BasePlayerViewModel.cs new file mode 100644 index 0000000..b1f4a25 --- /dev/null +++ b/aurora-sharp-desktop/Aurora/UserInterface/Views/BasePlayerViewModel.cs @@ -0,0 +1,50 @@ +using Aurora.Models.Media; +using Aurora.Design.Views.Main; + +namespace Aurora.Design.Views +{ + public class BasePlayerViewModel : BaseViewModel + { + public BasePlayerViewModel(): base() + { + } + /// + /// Delegate for interacting with main screen player control + /// + /// + public SetPlayerDelegate ChangePlayerState { get; set; } + + /// + /// Delegate for checking if main screen player control is currently playing + /// + /// + public GetIsPlayingDelegate IsPlaying { get; set; } + + /// + /// Command event handler for player play button + /// + public virtual void OnPlayButtonCommandExecute() { } + public virtual bool CanPlayButtonCommandExecute() + { + return true; + } + + /// + /// Command event handler for player next button + /// + public virtual void OnNextButtonExecute() { } + public virtual bool CanNextButtonCommandExecute() + { + return true; + } + + /// + /// Command event handler for player previous button + /// + public virtual void OnPreviousButtonExecute() { } + public virtual bool CanPreviousButtonCommandExecute() + { + return true; + } + } +} \ No newline at end of file diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/BaseViewModel.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/BaseViewModel.cs index d9aefeb..ea9ba16 100644 --- a/aurora-sharp-desktop/Aurora/UserInterface/Views/BaseViewModel.cs +++ b/aurora-sharp-desktop/Aurora/UserInterface/Views/BaseViewModel.cs @@ -15,55 +15,14 @@ namespace Aurora.Design.Views { } - #region Player - - /// - /// Command event handler for player play button - /// - public virtual void OnPlayButtonCommandExecute() { } - public virtual bool CanPlayButtonCommandExecute() - { - return true; - } - - /// - /// Command event handler for player next button - /// - public virtual void OnNextButtonExecute() { } - public virtual bool CanNextButtonCommandExecute() - { - return true; - } - - /// - /// Command event handler for player previous button - /// - public virtual void OnPreviousButtonExecute() { } - public virtual bool CanPreviousButtonCommandExecute() - { - return true; - } - - /// - /// Delegate for interacting with main screen player control - /// - /// - public SetPlayerDelegate ChangePlayerState { get; set; } - - /// - /// Delegate for checking if main screen player control is currently playing - /// - /// - public GetIsPlayingDelegate IsPlaying { get; set; } - public ShowModalDelegate ShowModal { get; set; } public HideModalDelegate HideModal { get; set; } + public SetViewDelegate SetView { get; set; } - #endregion Player - #region Lifecycle + #region Lifecycle Callbacks /// /// Called by main screen on view appearing /// @@ -78,7 +37,7 @@ namespace Aurora.Design.Views /// public virtual Task OnInactive() { return Task.FromResult(null); } - #endregion + #endregion Lifecycle Callbacks #region INotifyPropertyChanged Implementation public bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null) diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/MainView/MainView.xaml.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/MainView/MainView.xaml.cs index 67d7f16..68fa748 100644 --- a/aurora-sharp-desktop/Aurora/UserInterface/Views/MainView/MainView.xaml.cs +++ b/aurora-sharp-desktop/Aurora/UserInterface/Views/MainView/MainView.xaml.cs @@ -31,11 +31,12 @@ namespace Aurora.Design.Views.Main public delegate void ShowModalDelegate(Type view, BaseDialogViewModel viewModel); public delegate void HideModalDelegate(); public delegate void FinishDialogDelegate(); + public delegate void SetViewDelegate(Type viewType, Type viewModelType); [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MainView : ContentPage//, IDisposable { - private Dictionary _viewModels; + private Dictionary _viewModels; private BaseViewModel _lastViewModel; private Player _playerComponent; private IPlayer _playerService; @@ -45,7 +46,7 @@ namespace Aurora.Design.Views.Main { InitializeComponent(); BindingContext = new MainViewModel(); - _viewModels = new Dictionary(); + _viewModels = new Dictionary(); _playerComponent = Player; @@ -74,29 +75,35 @@ namespace Aurora.Design.Views.Main return; var view = (View)Activator.CreateInstance(item.TargetType); + string viewModelName = item.TargetViewModelType.Name; //Check if we have an instantiated viewModel BaseViewModel vm = new BaseViewModel(); - if (_viewModels.ContainsKey(item.Id)) + if (_viewModels.ContainsKey(viewModelName)) { - _viewModels.TryGetValue(item.Id, out vm); + _viewModels.TryGetValue(viewModelName, out vm); } else { - if (item.TargetViewModelType.BaseType != typeof(BaseViewModel)) + if (item.TargetViewModelType.IsAssignableFrom(typeof(BaseViewModel))) { throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel"); } //Instantiate new view model vm = (BaseViewModel)App.Container.Resolve(item.TargetViewModelType); //Activator.CreateInstance(item.TargetViewModelType); - _viewModels.Add(item.Id, vm); + _viewModels.Add(viewModelName, vm); } //Assign player controls to viewmodel - AssignPlayerControls(vm); + if(vm is BasePlayerViewModel) + { + AssignPlayerControls(vm as BasePlayerViewModel); + } + ChangeModalVisiblity(false); + vm.SetView = this.SetView; //Activate viewmodel vm.OnActive(); @@ -104,7 +111,10 @@ namespace Aurora.Design.Views.Main //Deactivate last viewModel _lastViewModel.OnInactive(); //Unasign deactivating vm - UnassignPlayerControls(_lastViewModel); + if(_lastViewModel is BasePlayerViewModel) + { + UnassignPlayerControls(_lastViewModel as BasePlayerViewModel); + } //Assign viewModel _lastViewModel = vm; @@ -128,20 +138,26 @@ namespace Aurora.Design.Views.Main var view = (View)Activator.CreateInstance(firstNavItem.TargetType); BaseViewModel vm = new BaseViewModel(); - if (_viewModels.ContainsKey(firstNavItem.Id)) + if (_viewModels.ContainsKey(nameof(firstNavItem.TargetViewModelType))) { - _viewModels.TryGetValue(firstNavItem.Id, out vm); + _viewModels.TryGetValue(nameof(firstNavItem.TargetViewModelType), out vm); } else { //Instantiate new view model vm = (BaseViewModel)App.Container.Resolve(firstNavItem.TargetViewModelType); //(BaseViewModel)Activator.CreateInstance(firstNavItem.TargetViewModelType); - _viewModels.Add(firstNavItem.Id, vm); + _viewModels.Add(nameof(firstNavItem.TargetViewModelType), vm); } view.BindingContext = vm; _lastViewModel = vm; - AssignPlayerControls(vm); + if(vm is BasePlayerViewModel) + { + AssignPlayerControls(vm as BasePlayerViewModel); + } + + vm.SetView = this.SetView; + ChangeModalVisiblity(false); vm.OnActive(); @@ -153,7 +169,7 @@ namespace Aurora.Design.Views.Main /// Unassign setplayer delegate to prevent vms from changing player info when inactive /// /// - private void UnassignPlayerControls(BaseViewModel vm) + private void UnassignPlayerControls(BasePlayerViewModel vm) { vm.ChangePlayerState = null; vm.IsPlaying = null; @@ -164,7 +180,7 @@ namespace Aurora.Design.Views.Main /// Assign main views music player controls to a view model /// /// BaseViewModel to assign controls to - private void AssignPlayerControls(BaseViewModel vm) + private void AssignPlayerControls(BasePlayerViewModel vm) { _playerComponent.PlayButtonCommand = new Command(vm.OnPlayButtonCommandExecute, vm.CanPlayButtonCommandExecute); _playerComponent.NextButtonCommand = new Command(vm.OnNextButtonExecute, vm.CanNextButtonCommandExecute); @@ -259,5 +275,52 @@ namespace Aurora.Design.Views.Main Modal.IsVisible = isVisible; Content.IsVisible = !isVisible; } + + private void SetView(Type viewType, Type viewModelType) + { + BaseViewModel vm = new BaseViewModel(); + if(this._viewModels.ContainsKey(viewModelType.Name)) + { + this._viewModels.TryGetValue(viewModelType.Name, out vm); + } + else + { + if (viewModelType.IsAssignableFrom(typeof(BaseViewModel))) + { + throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel"); + } + + //Instantiate new view model + vm = (BaseViewModel)App.Container.Resolve(viewModelType); //Activator.CreateInstance(item.TargetViewModelType); + _viewModels.Add(viewModelType.Name, vm); + } + + //Assign player controls to viewmodel + if(vm is BasePlayerViewModel) + { + AssignPlayerControls(vm as BasePlayerViewModel); + } + + ChangeModalVisiblity(false); + + //Activate viewmodel + vm.OnActive(); + + //Deactivate last viewModel + _lastViewModel.OnInactive(); + //Unasign deactivating vm + if(_lastViewModel is BasePlayerViewModel) + { + UnassignPlayerControls(_lastViewModel as BasePlayerViewModel); + } + + var view = (View)Activator.CreateInstance(viewType); + + //Assign viewModel + _lastViewModel = vm; + view.BindingContext = vm; + + _viewContent.Content = view; + } } } \ No newline at end of file diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/MainView/MainViewModel.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/MainView/MainViewModel.cs index c2771f1..6a1e310 100644 --- a/aurora-sharp-desktop/Aurora/UserInterface/Views/MainView/MainViewModel.cs +++ b/aurora-sharp-desktop/Aurora/UserInterface/Views/MainView/MainViewModel.cs @@ -56,13 +56,13 @@ namespace Aurora.Design.Views.MainView { _pages = new ObservableCollection(new[] { - new NavigationItem { Id = 0, Title = "Songs", Group="Your Music", TargetType = typeof(SongsView), TargetViewModelType = typeof(SongsViewModel) }, - new NavigationItem { Id = 1, Title = "Artists", Group="Your Music", TargetType = typeof(ArtistsView), TargetViewModelType = typeof(ArtistsViewModel)}, - new NavigationItem { Id = 2, Title = "Albums", Group="Your Music", TargetType = typeof(AlbumsView), TargetViewModelType = typeof(AlbumsViewModel)}, - new NavigationItem { Id = 3, Title = "Stations", Group="Your Music", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)}, - new NavigationItem { Id = 4, Title = "Party", Group="Social", TargetType = typeof(PartyView), TargetViewModelType = typeof(PartyViewModel)}, - new NavigationItem { Id = 5, Title = "Profile", Group="Social", TargetType = typeof(ProfileView), TargetViewModelType = typeof(ProfileViewModel)}, - new NavigationItem { Id = 6, Title = "A + B", Group="Playlists", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)} + new NavigationItem { Title = "Songs", Group="Your Music", TargetType = typeof(SongsView), TargetViewModelType = typeof(SongsViewModel) }, + new NavigationItem { Title = "Artists", Group="Your Music", TargetType = typeof(ArtistsView), TargetViewModelType = typeof(ArtistsViewModel)}, + new NavigationItem { Title = "Albums", Group="Your Music", TargetType = typeof(AlbumsView), TargetViewModelType = typeof(AlbumsViewModel)}, + new NavigationItem { Title = "Stations", Group="Your Music", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)}, + new NavigationItem { Title = "Party", Group="Social", TargetType = typeof(PartyView), TargetViewModelType = typeof(PartyViewModel)}, + new NavigationItem { Title = "Profile", Group="Social", TargetType = typeof(ProfileView), TargetViewModelType = typeof(ProfileViewModel)}, + new NavigationItem { Title = "A + B", Group="Playlists", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)} }); } diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/BasePartyViewModel.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/BasePartyViewModel.cs new file mode 100644 index 0000000..8424c60 --- /dev/null +++ b/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/BasePartyViewModel.cs @@ -0,0 +1,75 @@ +using System.Collections.ObjectModel; +using Aurora.Proto.Party; +using Aurora.Models.Media; +using Aurora.Services.Settings; + +namespace Aurora.Design.Views.Party +{ + public enum PartyStateV2 + { + SelectingHost, + InParty, + Hosting, + Connecting, + } + + public class BasePartyViewModel : BasePlayerViewModel + { + protected string _hostname; + private PartyStateV2 _state; + private ObservableCollection _members; + private ObservableCollection _queue; + private BaseMedia _selectedMedia; + private ISettingsService _settingsService; + private int _selectedTabIndex; + + public BasePartyViewModel( + ISettingsService settingsService + ) + { + _members = new ObservableCollection(); + _queue = new ObservableCollection(); + + this._settingsService = settingsService; + + } + + public int SelectedTabIndex + { + get { return _selectedTabIndex; } + set { SetProperty(ref _selectedTabIndex, value); } + } + + /// + /// Publc property for the members list + /// + /// + public ObservableCollection Members + { + get + { + return _members; + } + set + { + SetProperty(ref _members, value); + } + } + + /// + /// Public property for the currently selected song. + /// + /// + public BaseMedia SelectedSong + { + get { return _selectedMedia; } + set { SetProperty(ref _selectedMedia, value); } + } + + public PartyStateV2 State + { + get { return _state; } + set { _state = value;} + } + } +} \ No newline at end of file diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/HostPartyViewModel.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/HostPartyViewModel.cs new file mode 100644 index 0000000..b62ec4a --- /dev/null +++ b/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/HostPartyViewModel.cs @@ -0,0 +1,112 @@ +using System.Threading.Tasks; +using Aurora.Design.Views.Party.NewPartyDialog; +using Xamarin.Forms; +using Aurora.Services.Server; +using Aurora.Services.EventManager; +using Aurora.Services.Settings; + +namespace Aurora.Design.Views.Party +{ + public class HostPartyViewModel : BasePartyViewModel + { + private IServerService _serverService; + private IEventManager _eventManager; + public HostPartyViewModel( + ISettingsService settingsService, + IServerService serverService, + IEventManager eventManager + ): base(settingsService) + { + this._serverService = serverService; + this._eventManager = eventManager; + } + + #region Properties + + /// + /// Public property for playing media command + /// + /// + public Command PlayCommand { get; private set; } + + /// + /// Public property for leave party command + /// + /// + public Command LeavePartyCommand { get; private set; } + + #endregion Properties + + /// + /// Called by framework when view becomes active + /// + /// + public override Task OnActive() + { + + return Task.FromResult(null); + } + + /// + /// Called by framework when view becomes inactive + /// + /// + public override Task OnInactive() + { + return Task.FromResult(null); + } + + private async void OnHostCommandExecute() + { + + } + + private bool CanHostCommandExecute() + { + return true; + } + + private async void OnLeavePartyCommandExecute() + { + + } + + private bool CanLeavePartyCommandExecute() + { + return true; + } + + public override void OnPlayButtonCommandExecute() + { + + } + + public override bool CanPlayButtonCommandExecute() + { + return this.State == PartyStateV2.Hosting; + } + + public override bool CanNextButtonCommandExecute() + { + return this.State == PartyStateV2.Hosting; + } + + public override bool CanPreviousButtonCommandExecute() + { + return this.State == PartyStateV2.Hosting; + } + + /// + /// On double click execute, fire media playing event + /// + public void OnDoubleClickCommandExecute() + { + } + + public bool CanDoubleClickCommandExecute() + { + return this.State == PartyStateV2.Hosting; + } + + } +} \ No newline at end of file diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/JoinPartyViewModel.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/JoinPartyViewModel.cs new file mode 100644 index 0000000..e69de29 diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/PartyViewModel.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/PartyViewModel.cs index 1ca7a70..1373a96 100644 --- a/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/PartyViewModel.cs +++ b/aurora-sharp-desktop/Aurora/UserInterface/Views/Party/PartyViewModel.cs @@ -25,158 +25,62 @@ namespace Aurora.Design.Views.Party Connecting, } delegate void EventHandler(BaseEvent e); - public class PartyViewModel : BaseViewModel + public class PartyViewModel : BasePartyViewModel { - private PartyState _state; - private string _hostname = ""; - private ObservableCollection _members; - private ObservableCollection _queue; - private BaseMedia _selectedMedia; - private ISettingsService _settingsService; - private IClientService _clientService; - private IServerService _serverService; - private IEventManager _eventManager; - private CancellationTokenSource _eventCancellationTokenSource; - - private Dictionary _eventHandlers; - - private int _selectedTabIndex; - - public PartyViewModel( - ISettingsService settingsService, - IServerService serverService, - IEventManager eventManager, - IClientService clientService) + public PartyViewModel(ISettingsService settingsService): base(settingsService) { - _members = new ObservableCollection(); - _queue = new ObservableCollection(); - - this._settingsService = settingsService; - this._serverService = serverService; - this._eventManager = eventManager; - this._clientService = clientService; - - SetState(PartyState.SelectingHost); - - PlayCommand = new Command(OnDoubleClickCommandExecute, CanDoubleClickCommandExecute); - - LeavePartyCommand = new Command(OnLeavePartyCommandExecute, CanLeavePartyCommandExecute); - - //Setup event handlers - _eventHandlers = new Dictionary() - { - {BaseEvent.DerivedEventOneofCase.MediaPausedEvent, this.OnRemoteMediaPaused}, - {BaseEvent.DerivedEventOneofCase.MediaResumedEvent, this.OnRemoteMediaResumed}, - {BaseEvent.DerivedEventOneofCase.NewMediaPlayingEvent, this.OnNewRemoteMediaPlaying}, - {BaseEvent.DerivedEventOneofCase.MemberCreatedEvent, this.OnPartyMemberJoined}, - {BaseEvent.DerivedEventOneofCase.MemberDeletedEvent, this.OnPartyMemberLeft} - }; } - #region Properties - - public int SelectedTabIndex - { - get { return _selectedTabIndex; } - set { SetProperty(ref _selectedTabIndex, value); } - } - - /// - /// Publc property for the members list - /// - /// - public ObservableCollection Members - { - get - { - return _members; - } - set - { - SetProperty(ref _members, value); - } - } - - /// - /// Public property for queue item source - /// - /// - public ObservableCollection Queue - { - get - { - return _queue; - } - set - { - if (value != _queue) - { - SetProperty(ref _queue, value); - } - } - } - - /// - /// Public property for the currently selected song. - /// - /// - public BaseMedia SelectedSong - { - get { return _selectedMedia; } - set { SetProperty(ref _selectedMedia, value); } - } - - /// - /// Public property for playing media - /// - /// - public Command PlayCommand { get; private set; } - - public Command LeavePartyCommand { get; private set; } - - #endregion Properties - - #region Events /// /// Called by framework when view becomes active /// /// - public override async Task OnActive() + public override Task OnActive() { OnPropertyChanged("SelectedTabIndex"); - if (this._state == PartyState.Hosting || - this._state == PartyState.InParty) + switch(this.State) { - await this.GetEvents().ConfigureAwait(false); - } - else - { - //Open host selection modal - NewPartyDialogViewModel vm = new NewPartyDialogViewModel(); - ConnectionDetails details = new ConnectionDetails(); - vm.Finish = () => + case PartyStateV2.Hosting: { - this.HideModal(); - details = vm.ReturnObject as ConnectionDetails; - _hostname = details.HostName; - switch (details.ConnectionType) + this.SetView.Invoke(typeof(PartyView), typeof(HostPartyViewModel)); + break; + } + case PartyStateV2.InParty: + { + // TODO + break; + } + default: + { + //Open host selection modal + NewPartyDialogViewModel vm = new NewPartyDialogViewModel(); + ConnectionDetails details = new ConnectionDetails(); + vm.Finish = () => { - case ConnectionType.Host: - { - OnHostCommandExecute(); - break; - } - case ConnectionType.Join: - { - OnJoinCommandExecute(); - break; - } - } - }; + this.HideModal(); + details = vm.ReturnObject as ConnectionDetails; + this._hostname = details.HostName; + switch (details.ConnectionType) + { + case ConnectionType.Host: + { + this.SetView.Invoke(typeof(PartyView), typeof(HostPartyViewModel)); + break; + } + case ConnectionType.Join: + { + // TODO + break; + } + } + }; - this.ShowModal(typeof(NewPartyDialog.NewPartyDialog), vm); + this.ShowModal(typeof(NewPartyDialog.NewPartyDialog), vm); + break; + } } + return Task.FromResult(null); } /// @@ -185,393 +89,11 @@ namespace Aurora.Design.Views.Party /// public override Task OnInactive() { - if(this._eventCancellationTokenSource != null){ - this._eventCancellationTokenSource.Cancel(); - } + // if(this._eventCancellationTokenSource != null){ + // this._eventCancellationTokenSource.Cancel(); + // } return Task.FromResult(null); } - - /// - /// Remote media paused event - /// - /// - /// - public void OnRemoteMediaPaused(BaseEvent e) - { - StopPlaying(); - } - - /// - /// Remote playing new media event - /// - /// - /// - public void OnNewRemoteMediaPlaying(BaseEvent e) - { - PlayFromBeginning(GetMediaFromQueue(e.NewMediaPlayingEvent.Media.Name)); - } - - /// - /// Remote resumed playing event - /// - /// - /// - public void OnRemoteMediaResumed(BaseEvent e) - { - PlayResume(); - } - - /// - /// Member joined party event - /// - /// - /// - public void OnPartyMemberJoined(BaseEvent e) - { - Members.Add(e.MemberCreatedEvent.Member); - } - - /// - /// Member left party event - /// - /// - /// - public void OnPartyMemberLeft(BaseEvent e) - { - var found = Members.Where(x => x.Name == e.MemberDeletedEvent.MemberName); - foreach (Member member in found) - { - _members.Remove(member); - } - } - - #endregion Events - - #region Commands - private async void OnJoinCommandExecute() - { - SetState(PartyState.Connecting); - _clientService.Start(_hostname, this._settingsService.DefaultPort.ToString()); - await JoinParty(false); - - //TODO add cancellation token - try - { - SetState(PartyState.InParty); - await GetEvents().ConfigureAwait(true); - } - catch (Exception ex) - { - Console.WriteLine("Exception occurred while receiviing events: ", ex.Message); - } - } - - private bool CanJoinCommandExecute() - { - return true; - } - - private async void OnHostCommandExecute() - { - //Change state - SetState(PartyState.Connecting); - _serverService.Start("test", "asdf"); - string localHost = ServerService.GetLocalIPAddress(); - _clientService.Start(localHost, this._settingsService.DefaultPort.ToString()); - await JoinParty(true); - - - //TODO add cancellation token - try - { - SetState(PartyState.Hosting); - await GetEvents().ConfigureAwait(false); - } - catch (Exception ex) - { - Console.WriteLine("Exception occurred while receiviing events: ", ex.Message); - } - } - - private bool CanHostCommandExecute() - { - return true; - } - - private async void OnLeavePartyCommandExecute() - { - await _clientService.RemotePartyServiceClient.DeleteMemberAsync(new DeleteMemberRequest() - { - Name = _settingsService.ClientName - }); - } - - private bool CanLeavePartyCommandExecute() - { - return (this._state == PartyState.InParty || this._state == PartyState.Hosting) ? true : false; - } - - public override void OnPlayButtonCommandExecute() - { - if (base.IsPlaying()) - { - //Fire play stopped event - AudioMetadata meta = _selectedMedia.Metadata as AudioMetadata; - MediaPausedEvent mediaPaused = new MediaPausedEvent(); - - _eventManager.FireEvent(new BaseEvent() - { - MediaPausedEvent = mediaPaused - }); - } - else - { - //Fire play resume event - AudioMetadata meta = _selectedMedia.Metadata as AudioMetadata; - MediaResumedEvent mediaResumed = new MediaResumedEvent(); - - _eventManager.FireEvent(new BaseEvent() - { - MediaResumedEvent = mediaResumed - }); - } - } - - public override bool CanPlayButtonCommandExecute() - { - return this._state == PartyState.Hosting; - } - - public override bool CanNextButtonCommandExecute() - { - return this._state == PartyState.Hosting; - } - - public override bool CanPreviousButtonCommandExecute() - { - return this._state == PartyState.Hosting; - } - - /// - /// On double click execute, fire media playing event - /// - public void OnDoubleClickCommandExecute() - { - //Fire Playing event - AudioMetadata meta = _selectedMedia.Metadata as AudioMetadata; - NewMediaPlayingEvent mediaPlaying = new NewMediaPlayingEvent() - { - Media = new Media() - { - //TODO need full resource name - Name = _selectedMedia.Id, - Title = meta.Title, - Artist = meta.Artist, - Album = meta.Album, - } - }; - - _eventManager.FireEvent(new BaseEvent() - { - NewMediaPlayingEvent = mediaPlaying - }); - } - - public bool CanDoubleClickCommandExecute() - { - return this._state == PartyState.Hosting; - } - - - #endregion Commands - - #region Private Methods - /// - /// Join the remote party. - /// - /// - private async Task JoinParty(bool asHost) - { - try - { - Member resp = await _clientService.RemotePartyServiceClient.CreateMemberAsync(new CreateMemberRequest - { - Member = new Member() - { - UserName = this._settingsService.Username, - } - }); - - this._settingsService.ClientName = resp.Name; - - await RefreshMembers(); - - //Subscribe to events - await SubscribeToEvents(); - - Queue.Clear(); - - ListMediaResponse mediaResponse = await _clientService.RemotePartyServiceClient.ListMediaAsync(new ListMediaRequest() - { - PageSize = 50, - Parent = "TODO" - }); - - //Convert received data to remote audio models - foreach (Media data in mediaResponse.Media) - { - //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.Name, - asHost, - meta, - _clientService.RemotePartyServiceClient); - - Queue.Add(remote); - OnPropertyChanged("Queue"); - } - } - catch (Exception ex) - { - Console.WriteLine("Error subscribing to events: " + ex.Message); - } - } - - private async Task LeaveParty() - { - //Stop receiving events - // _client.StopEvents(); - - //Unsubscribe - await UnsubscribeFromEvents(); - - //Leave party - DeleteMemberRequest req = new DeleteMemberRequest() - { - Name = _settingsService.ClientName - }; - - await _clientService.RemotePartyServiceClient.DeleteMemberAsync(req); - } - - private async Task SubscribeToEvents() - { - CreateEventSubscriptionListRequest req = new CreateEventSubscriptionListRequest(); - req.Parent = this._settingsService.ClientName; - req.EventSubscriptions.Add(new EventSubscription() { Type = EventType.MemberCreated }); - req.EventSubscriptions.Add(new EventSubscription() { Type = EventType.MemberDeleted }); - req.EventSubscriptions.Add(new EventSubscription() { Type = EventType.MediaPlaying }); - req.EventSubscriptions.Add(new EventSubscription() { Type = EventType.MediaStopped }); - - Console.WriteLine(string.Format("CLIENT {0} - SubscribeToEvents called from client with id", this._settingsService.ClientName)); - await _clientService.RemotePartyServiceClient.CreateEventSubscriptionListAsync(req); - } - private async Task UnsubscribeFromEvents() - { - DeleteAllEventSubscriptionsRequest unsubscribeReq = new DeleteAllEventSubscriptionsRequest(); - await _clientService.RemotePartyServiceClient.DeleteAllEventSubscriptionsAsync(unsubscribeReq); - } - - /// - /// Refresh members list. - /// - private async Task RefreshMembers() - { - Members.Clear(); - ListMembersResponse response = await _clientService.RemotePartyServiceClient.ListMembersAsync( - new ListMembersRequest() - { - Parent = "TODO", - PageSize = 50, - }); - //Add members - foreach (Member member in response.Members) - { - Members.Add(member); - } - } - - private void SetState(PartyState state) - { - _state = state; - OnPropertyChanged("IsSelectingHost"); - OnPropertyChanged("IsNotSelectingHost"); - } - - private BaseMedia GetMediaFromQueue(string Id) - { - if (_queue.Any((BaseMedia media) => media.Id == Id)) - { - BaseMedia media = _queue.First((BaseMedia med) => med.Id == Id); - return media; - } - else - { - return null; - } - } - private void PlayFromBeginning(BaseMedia args) - { - base.ChangePlayerState(args, Main.PlayAction.Play); - } - - private void PlayResume() - { - base.ChangePlayerState(null, Main.PlayAction.Resume); - } - - private void StopPlaying() - { - base.ChangePlayerState(null, Main.PlayAction.Pause); - } - - /// - /// Asynchronous function for processing events off of the event stream. - /// - /// - public async Task GetEvents() - { - _eventCancellationTokenSource = new CancellationTokenSource(); - string clientName = this._settingsService.ClientName; - Console.WriteLine(string.Format("CLIENT {0} - GetEvents called from client with id", clientName)); - using (AsyncServerStreamingCall eventStream = _clientService.RemotePartyServiceClient - .GetEvents(new GetEventsRequest { Parent = this._settingsService.ClientName })) - { - try - { - while (!_eventCancellationTokenSource.Token.IsCancellationRequested && - await eventStream.ResponseStream.MoveNext(_eventCancellationTokenSource.Token)) - { - try - { - BaseEvent e = new BaseEvent(eventStream.ResponseStream.Current); - - _eventHandlers.TryGetValue(e.DerivedEventCase, out EventHandler handler); - - if (handler != null && handler != null) - { - handler.Invoke(e); - } - } - catch (Exception ex) - { - Console.WriteLine("Exception while parsing event ---" + ex.Message); - } - - } - } - catch (Exception ex) - { - Console.WriteLine(string.Format("EXCEPTION while parsing events --- " + ex.Message)); - } - } - } - #endregion Private Methods } } \ No newline at end of file diff --git a/aurora-sharp-desktop/Aurora/UserInterface/Views/Songs/SongsViewModel.cs b/aurora-sharp-desktop/Aurora/UserInterface/Views/Songs/SongsViewModel.cs index b651342..5ac3bb7 100644 --- a/aurora-sharp-desktop/Aurora/UserInterface/Views/Songs/SongsViewModel.cs +++ b/aurora-sharp-desktop/Aurora/UserInterface/Views/Songs/SongsViewModel.cs @@ -5,7 +5,7 @@ using Xamarin.Forms; namespace Aurora.Design.Views.Songs { - public class SongsViewModel : BaseViewModel + public class SongsViewModel : BasePlayerViewModel { #region Fields private ObservableCollection _songsList;