Player controls now get dynamically assigned to view model base classes.

This gives view models more freedom in how play events from the player are handled
This commit is contained in:
watsonb8
2019-11-06 22:32:43 -05:00
parent 759c05e53b
commit 794b4739b1
12 changed files with 549 additions and 187 deletions

View File

@ -2,6 +2,8 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Aurora.Models.Media;
using Xamarin.Forms;
namespace Aurora.Design.Views
{
@ -11,6 +13,38 @@ namespace Aurora.Design.Views
{
}
#region Player
public virtual void PlayExecute()
{
}
public virtual bool PlayCanExecute()
{
return true;
}
public virtual void NextExecute()
{
}
public virtual bool NextCanExecute()
{
return true;
}
public virtual void PreviousExecute()
{
}
public virtual bool PreviousCanExecute()
{
return true;
}
public BaseMedia Media { get; set; }
#endregion Player
#region Lifecycle
public virtual void OnActive() { }

View File

@ -6,6 +6,8 @@ using Aurora.Design.Components.NavigationMenu;
using Aurora.Design.Views.MainView;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Aurora.Models.Media;
using Aurora.Design.Components.MediaPlayer;
namespace Aurora.Design.Views.Main
{
@ -20,7 +22,7 @@ namespace Aurora.Design.Views.Main
InitializeComponent();
BindingContext = new MainViewModel();
_viewModels = new Dictionary<int, BaseViewModel>();
MasterPage.ListView.ItemSelected += ListView_ItemSelected;
MasterPage.ListView.ItemSelected += OnNavItemSelected;
Appearing += OnAppearing;
}
@ -29,7 +31,12 @@ namespace Aurora.Design.Views.Main
Appearing -= OnAppearing;
}
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
public Command PlayCommand { get; set; }
public Command PreviousCommand { get; set; }
public Command NextCommand { get; set; }
public BaseMedia Media { get; set; }
private void OnNavItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as NavigationItem;
if (item == null)
@ -54,6 +61,14 @@ namespace Aurora.Design.Views.Main
vm = (BaseViewModel)Activator.CreateInstance(item.TargetViewModelType);
_viewModels.Add(item.Id, vm);
}
//Assign player controls to viewmodel
Player player = (Player)ContentPage.FindByName("Player");
player.PlayButtonCommand = new Command(vm.PlayExecute, vm.PlayCanExecute);
player.NextButtonCommand = new Command(vm.NextExecute, vm.NextCanExecute);
player.PreviousButtonCommand = new Command(vm.PreviousExecute, vm.PreviousCanExecute);
vm.Media = this.Media;
//Activate viewmodel
vm.OnActive();
@ -98,6 +113,11 @@ namespace Aurora.Design.Views.Main
view.BindingContext = vm;
_lastViewModel = vm;
Player player = (Player)ContentPage.FindByName("Player");
player.PlayButtonCommand = new Command(vm.PlayExecute, vm.PlayCanExecute);
player.NextButtonCommand = new Command(vm.NextExecute, vm.NextCanExecute);
player.PreviousButtonCommand = new Command(vm.PreviousExecute, vm.PreviousCanExecute);
vm.Media = this.Media;
vm.OnActive();
ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent");
@ -105,6 +125,7 @@ namespace Aurora.Design.Views.Main
MasterPage.ListView.SelectedItem = screenList.FirstOrDefault();
}
}
}

View File

@ -17,6 +17,7 @@
Grid.Row="0"
x:Name="ViewContent"/>
<mp:Player
x:Name="Player"
Grid.Row="1"
HorizontalOptions="CenterAndExpand"
VerticalOptions="End"

View File

@ -17,6 +17,7 @@ namespace Aurora.Design.Views.Party
{
SelectingHost,
InParty,
Hosting,
Connecting,
}
@ -51,6 +52,10 @@ namespace Aurora.Design.Views.Party
#region Properties
/// <summary>
/// Publc property for the members list
/// </summary>
/// <value></value>
public ObservableCollection<PartyMember> Members
{
get
@ -68,11 +73,19 @@ namespace Aurora.Design.Views.Party
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
@ -88,26 +101,63 @@ namespace Aurora.Design.Views.Party
}
}
public Command JoinCommand { get; set; }
public Command HostCommand { get; set; }
/// <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 _selectedSong; }
set { SetProperty(ref _selectedSong, 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>
@ -154,10 +204,11 @@ namespace Aurora.Design.Views.Party
#region Commands
private async void OnJoinExecute()
{
SetState(PartyState.Connecting);
ClientService.Instance.Start(Hostname, SettingsService.Instance.DefaultPort.ToString());
await JoinParty();
SetState(PartyState.Connecting);
SetState(PartyState.InParty);
}
private bool CanJoinExecute()
@ -167,15 +218,24 @@ namespace Aurora.Design.Views.Party
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();
ClientService.Instance.GetEvents();
try
{
//Execute task without waiting
await ClientService.Instance.GetEvents().ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine("Exception occurred while receiviing events: ", ex.Message);
}
//Change state
SetState(PartyState.Connecting);
SetState(PartyState.Hosting);
}
private bool CanHostExecute()
@ -243,6 +303,22 @@ namespace Aurora.Design.Views.Party
}
}
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>

View File

@ -11,14 +11,20 @@ namespace Aurora.Design.Views.Songs
#region Fields
private ObservableCollection<BaseMedia> _songsList;
private BaseMedia _selectedSong;
private BaseMedia _playingSong;
private PlayerService _player;
#endregion Fields
#region Constructor
public SongsViewModel()
{
_player = PlayerService.Instance;
_songsList = new ObservableCollection<BaseMedia>();
PlayCommand = new Command(PlayExecute);
PlayCommand = new Command(PlayExecute, PlayCanExecute);
_player.PlaybackStateChanged += OnPlaybackStateChanged;
Initialize();
}
@ -37,6 +43,12 @@ namespace Aurora.Design.Views.Songs
set { SetProperty(ref _selectedSong, value); }
}
public BaseMedia PlayingSong
{
get { return _playingSong; }
set { SetProperty(ref _playingSong, value); }
}
public Command PlayCommand { get; private set; }
#endregion Properties
@ -48,13 +60,84 @@ namespace Aurora.Design.Views.Songs
SongsList = LibraryService.Instance.GetLibrary();
}
public void PlayExecute()
{
PlayerService.Instance.LoadMedia(_selectedSong);
PlayerService.Instance.Play();
}
#endregion Methods
#region Commmands
public override bool PreviousCanExecute()
{
return true;
}
public override void PreviousExecute()
{
}
public override bool PlayCanExecute()
{
switch (_player.PlaybackState)
{
case PlaybackState.Buffering:
{
return true;
}
case PlaybackState.Playing:
{
return true;
}
case PlaybackState.Stopped:
{
return true;
}
}
return false;
}
public async override void PlayExecute()
{
if (!_player.IsMediaLoaded(_selectedSong))
{
await _player.LoadMedia(_selectedSong).ConfigureAwait(true);
}
_player.Play();
switch (_player.PlaybackState)
{
case PlaybackState.Buffering:
{
_player.Play();
break;
}
case PlaybackState.Playing:
{
_player.Pause();
break;
}
}
}
public override bool NextCanExecute()
{
return true;
}
public override void NextExecute()
{
}
#endregion Commands
#region Events
/// <summary>
/// PlayerService playback state changed event handler.
/// </summary>
/// <param name="sender">The sending object.</param>
/// <param name="args">Event arguments.</param>
public void OnPlaybackStateChanged(object sender, PlaybackStateChangedEventArgs args)
{
OnPropertyChanged("PlayButtonText");
}
#endregion Events
}
}