Working player contained within main page and control delegated to viewmodels

This commit is contained in:
watsonb8 2019-11-08 19:54:51 -05:00
parent 794b4739b1
commit 63efcdad69
7 changed files with 134 additions and 75 deletions

View File

@ -14,11 +14,9 @@
<StackLayout <StackLayout
Grid.Column="0"> Grid.Column="0">
<Label <Label
x:Name="SongTitleLabel" x:Name="SongTitleLabel"/>
Text="{Binding SongTitle}"/>
<Label <Label
x:Name="ArtistNameLabel" x:Name="ArtistNameLabel"/>
Text="{Binding ArtistName}"/>
</StackLayout> </StackLayout>
<StackLayout <StackLayout
Grid.Column="1" Grid.Column="1"
@ -26,19 +24,16 @@
<Button <Button
Text="Previous" Text="Previous"
x:Name="PreviousButton" x:Name="PreviousButton"
Command="{Binding PreviousCommand}"
WidthRequest="100" WidthRequest="100"
HeightRequest="50"/> HeightRequest="50"/>
<Button <Button
x:Name="PlayButton" x:Name="PlayButton"
Text="{Binding PlayButtonText}" Text="Play/Pause"
Command="{Binding PlayCommand}"
WidthRequest="100" WidthRequest="100"
HeightRequest="50"/> HeightRequest="50"/>
<Button <Button
Text="Next" Text="Next"
x:Name="NextButton" x:Name="NextButton"
Command="{Binding NextCommand}"
WidthRequest="100" WidthRequest="100"
HeightRequest="50"/> HeightRequest="50"/>
</StackLayout> </StackLayout>

View File

@ -7,9 +7,6 @@ namespace Aurora.Design.Components.MediaPlayer
{ {
public Player() public Player()
{ {
// this.PreviousButton.Clicked += OnPreviousButtonClicked;
// this.PlayButton.Clicked += OnPlayButtonClicked;
// this.NextButton.Clicked += OnNextButtonClicked;
InitializeComponent(); InitializeComponent();
} }
@ -33,7 +30,7 @@ namespace Aurora.Design.Components.MediaPlayer
} }
} }
private static void OnSongTitlePropertyChanged(BindableObject bindable, object newValue, object oldValue) private static void OnSongTitlePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{ {
Player component = bindable as Player; Player component = bindable as Player;
component.SongTitleLabel.Text = (string)newValue; component.SongTitleLabel.Text = (string)newValue;
@ -60,7 +57,7 @@ namespace Aurora.Design.Components.MediaPlayer
} }
} }
private static void OnArtistNamePropertyChanged(BindableObject bindable, object newValue, object oldValue) private static void OnArtistNamePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{ {
Player component = bindable as Player; Player component = bindable as Player;
component.ArtistNameLabel.Text = (string)newValue; component.ArtistNameLabel.Text = (string)newValue;

View File

@ -4,44 +4,71 @@ using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Aurora.Models.Media; using Aurora.Models.Media;
using Xamarin.Forms; using Xamarin.Forms;
using Aurora.Design.Views.Main;
namespace Aurora.Design.Views namespace Aurora.Design.Views
{ {
public class BaseViewModel : INotifyPropertyChanged public class BaseViewModel : INotifyPropertyChanged
{ {
private BaseMedia _baseMedia;
public BaseViewModel() public BaseViewModel()
{ {
} }
#region Player #region Player
public virtual void PlayExecute()
{
} /// <summary>
public virtual bool PlayCanExecute() /// Command event handler for player play button
/// </summary>
public virtual void OnPlayExecute() { }
public virtual bool CanPlayExecute()
{ {
return true; return true;
} }
public virtual void NextExecute() /// <summary>
{ /// Command event handler for player next button
/// </summary>
} public virtual void OnNextExecute() { }
public virtual bool NextCanExecute() public virtual bool CanNextExecute()
{ {
return true; return true;
} }
public virtual void PreviousExecute() /// <summary>
{ /// Command event handler for player previous button
/// </summary>
} public virtual void OnPreviousExecute() { }
public virtual bool PreviousCanExecute() public virtual bool CanPreviousExecute()
{ {
return true; return true;
} }
public BaseMedia Media { get; set; } /// <summary>
/// Model for the currently playing music.
/// </summary>
/// <value></value>
public BaseMedia Media
{
get
{
return this._baseMedia;
}
set
{
if (value != _baseMedia)
{
_baseMedia = value;
if (this.SetPlayerMetadata != null)
{
SetPlayerMetadata.Invoke(value);
}
}
}
}
public SetPlayerMetadataDelegate SetPlayerMetadata { get; set; }
#endregion Player #endregion Player

View File

@ -11,8 +11,14 @@ using Aurora.Design.Components.MediaPlayer;
namespace Aurora.Design.Views.Main namespace Aurora.Design.Views.Main
{ {
/// <summary>
/// Delegate for updating player metadata
/// </summary>
/// <param name="media"></param>
public delegate void SetPlayerMetadataDelegate(BaseMedia media);
[XamlCompilation(XamlCompilationOptions.Compile)] [XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainView : MasterDetailPage public partial class MainView : MasterDetailPage, IDisposable
{ {
private Dictionary<int, BaseViewModel> _viewModels; private Dictionary<int, BaseViewModel> _viewModels;
private BaseViewModel _lastViewModel; private BaseViewModel _lastViewModel;
@ -26,16 +32,17 @@ namespace Aurora.Design.Views.Main
Appearing += OnAppearing; Appearing += OnAppearing;
} }
~MainView()
public void Dispose()
{ {
Appearing -= OnAppearing; Appearing -= OnAppearing;
} }
public Command PlayCommand { get; set; } /// <summary>
public Command PreviousCommand { get; set; } /// Event handler for side bar items being selected
public Command NextCommand { get; set; } /// </summary>
public BaseMedia Media { get; set; } /// <param name="sender"></param>
/// <param name="e"></param>
private void OnNavItemSelected(object sender, SelectedItemChangedEventArgs e) private void OnNavItemSelected(object sender, SelectedItemChangedEventArgs e)
{ {
var item = e.SelectedItem as NavigationItem; var item = e.SelectedItem as NavigationItem;
@ -60,24 +67,22 @@ namespace Aurora.Design.Views.Main
//Instantiate new view model //Instantiate new view model
vm = (BaseViewModel)Activator.CreateInstance(item.TargetViewModelType); vm = (BaseViewModel)Activator.CreateInstance(item.TargetViewModelType);
_viewModels.Add(item.Id, vm); _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 //Activate viewmodel
vm.OnActive(); vm.OnActive();
//Deactivate last viewModel //Deactivate last viewModel
_lastViewModel.OnInactive(); _lastViewModel.OnInactive();
//Unasign deactivating vm
UnassignPlayerControls(_lastViewModel);
//Assign viewModel //Assign viewModel
_lastViewModel = vm; _lastViewModel = vm;
view.BindingContext = vm; view.BindingContext = vm;
//Assign player controls to viewmodel
AssignPlayerControls(vm);
ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent"); ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent");
viewContent.Content = view; viewContent.Content = view;
@ -113,19 +118,50 @@ namespace Aurora.Design.Views.Main
view.BindingContext = vm; view.BindingContext = vm;
_lastViewModel = vm; _lastViewModel = vm;
Player player = (Player)ContentPage.FindByName("Player"); AssignPlayerControls(vm);
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(); vm.OnActive();
ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent"); ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent");
viewContent.Content = view; viewContent.Content = view;
MasterPage.ListView.SelectedItem = screenList.FirstOrDefault(); MasterPage.ListView.SelectedItem = screenList.FirstOrDefault();
} }
/// <summary>
/// Unassign setplayer delegate to prevent vms from changing player info when inactive
/// </summary>
/// <param name="vm"></param>
private void UnassignPlayerControls(BaseViewModel vm)
{
vm.SetPlayerMetadata = null;
}
/// <summary>
/// Assign main views music player controls to a view model
/// </summary>
/// <param name="vm">BaseViewModel to assign controls to</param>
private void AssignPlayerControls(BaseViewModel vm)
{
Player player = (Player)ContentPage.FindByName("Player");
player.PlayButtonCommand = new Command(vm.OnPlayExecute, vm.CanPlayExecute);
player.NextButtonCommand = new Command(vm.OnNextExecute, vm.CanNextExecute);
player.PreviousButtonCommand = new Command(vm.OnPreviousExecute, vm.CanPreviousExecute);
//Assign SetPlayer delegate
vm.SetPlayerMetadata = SetPlayerDelegate;
}
private void SetPlayerDelegate(BaseMedia media)
{
Player player = (Player)ContentPage.FindByName("Player");
if (media.Metadata is AudioMetadata)
{
AudioMetadata meta = (AudioMetadata)media.Metadata;
player.ArtistName = meta.Artist;
player.SongTitle = meta.Title;
}
}
} }
} }

View File

@ -6,7 +6,8 @@
xmlns:mp="clr-namespace:Aurora.Design.Components.MediaPlayer" xmlns:mp="clr-namespace:Aurora.Design.Components.MediaPlayer"
x:Class="Aurora.Design.Views.MainView.PageContainer"> x:Class="Aurora.Design.Views.MainView.PageContainer">
<ContentPage.Content> <ContentPage.Content>
<Grid> <Grid
x:Name="Grid">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition <RowDefinition
Height="*"/> Height="*"/>

View File

@ -39,7 +39,7 @@ namespace Aurora.Design.Views.Party
SetState(PartyState.SelectingHost); SetState(PartyState.SelectingHost);
PlayCommand = new Command(PlayExecute); PlayCommand = new Command(OnPlayExecute);
//Hook up event handler //Hook up event handler
ClientService.Instance.EventReceived += this.OnEventReceived; ClientService.Instance.EventReceived += this.OnEventReceived;
@ -182,7 +182,7 @@ namespace Aurora.Design.Views.Party
Port = derivedEvent.Member.Port Port = derivedEvent.Member.Port
}; };
AddMember(member); Members.Add(member);
break; break;
} }
@ -315,8 +315,6 @@ namespace Aurora.Design.Views.Party
//Leave party //Leave party
LeavePartyRequest leaveReq = new LeavePartyRequest(); LeavePartyRequest leaveReq = new LeavePartyRequest();
await ClientService.Instance.RemotePartyClient.LeavePartyAsync(leaveReq); await ClientService.Instance.RemotePartyClient.LeavePartyAsync(leaveReq);
} }
/// <summary> /// <summary>
@ -339,16 +337,27 @@ namespace Aurora.Design.Views.Party
OnPropertyChanged("IsNotSelectingHost"); OnPropertyChanged("IsNotSelectingHost");
} }
private void AddMember(PartyMember member) public override async void OnPlayExecute()
{ {
Members.Add(member); await PlayerService.Instance.LoadMedia(_selectedSong).ConfigureAwait(true);
}
public async void PlayExecute()
{
await PlayerService.Instance.LoadMedia(_selectedSong);
PlayerService.Instance.Play(); PlayerService.Instance.Play();
} }
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 #endregion Private Methods
} }
} }

View File

@ -11,7 +11,6 @@ namespace Aurora.Design.Views.Songs
#region Fields #region Fields
private ObservableCollection<BaseMedia> _songsList; private ObservableCollection<BaseMedia> _songsList;
private BaseMedia _selectedSong; private BaseMedia _selectedSong;
private BaseMedia _playingSong;
private PlayerService _player; private PlayerService _player;
#endregion Fields #endregion Fields
@ -21,7 +20,7 @@ namespace Aurora.Design.Views.Songs
{ {
_player = PlayerService.Instance; _player = PlayerService.Instance;
_songsList = new ObservableCollection<BaseMedia>(); _songsList = new ObservableCollection<BaseMedia>();
PlayCommand = new Command(PlayExecute, PlayCanExecute); PlayCommand = new Command(OnPlayExecute, CanPlayExecute);
_player.PlaybackStateChanged += OnPlaybackStateChanged; _player.PlaybackStateChanged += OnPlaybackStateChanged;
@ -43,12 +42,6 @@ namespace Aurora.Design.Views.Songs
set { SetProperty(ref _selectedSong, value); } set { SetProperty(ref _selectedSong, value); }
} }
public BaseMedia PlayingSong
{
get { return _playingSong; }
set { SetProperty(ref _playingSong, value); }
}
public Command PlayCommand { get; private set; } public Command PlayCommand { get; private set; }
#endregion Properties #endregion Properties
@ -63,16 +56,16 @@ namespace Aurora.Design.Views.Songs
#endregion Methods #endregion Methods
#region Commmands #region Commmands
public override bool PreviousCanExecute() public override bool CanPreviousExecute()
{ {
return true; return true;
} }
public override void PreviousExecute() public override void OnPreviousExecute()
{ {
} }
public override bool PlayCanExecute() public override bool CanPlayExecute()
{ {
switch (_player.PlaybackState) switch (_player.PlaybackState)
{ {
@ -92,11 +85,12 @@ namespace Aurora.Design.Views.Songs
return false; return false;
} }
public async override void PlayExecute() public async override void OnPlayExecute()
{ {
if (!_player.IsMediaLoaded(_selectedSong)) base.Media = _selectedSong;
if (!_player.IsMediaLoaded(base.Media))
{ {
await _player.LoadMedia(_selectedSong).ConfigureAwait(true); await _player.LoadMedia(base.Media).ConfigureAwait(true);
} }
_player.Play(); _player.Play();
@ -115,12 +109,12 @@ namespace Aurora.Design.Views.Songs
} }
} }
public override bool NextCanExecute() public override bool CanNextExecute()
{ {
return true; return true;
} }
public override void NextExecute() public override void OnNextExecute()
{ {
} }