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

@ -14,8 +14,10 @@
<StackLayout
Grid.Column="0">
<Label
x:Name="SongTitleLabel"
Text="{Binding SongTitle}"/>
<Label
x:Name="ArtistNameLabel"
Text="{Binding ArtistName}"/>
</StackLayout>
<StackLayout
@ -23,16 +25,19 @@
Orientation="Horizontal">
<Button
Text="Previous"
x:Name="PreviousButton"
Command="{Binding PreviousCommand}"
WidthRequest="100"
HeightRequest="50"/>
<Button
x:Name="PlayButton"
Text="{Binding PlayButtonText}"
Command="{Binding PlayCommand}"
WidthRequest="100"
HeightRequest="50"/>
<Button
Text="Next"
x:Name="NextButton"
Command="{Binding NextCommand}"
WidthRequest="100"
HeightRequest="50"/>

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace Aurora.Design.Components.MediaPlayer
@ -8,8 +7,276 @@ namespace Aurora.Design.Components.MediaPlayer
{
public Player()
{
BindingContext = new PlayerViewModel();
// this.PreviousButton.Clicked += OnPreviousButtonClicked;
// this.PlayButton.Clicked += OnPlayButtonClicked;
// this.NextButton.Clicked += OnNextButtonClicked;
InitializeComponent();
}
#region SongTitle Bindable
public static readonly BindableProperty SongTitleProperty =
BindableProperty.Create(propertyName: "SongTitle",
returnType: typeof(string),
declaringType: typeof(Player),
propertyChanged: OnSongTitlePropertyChanged);
public string SongTitle
{
get
{
return (string)GetValue(SongTitleProperty);
}
set
{
SetValue(SongTitleProperty, value);
}
}
private static void OnSongTitlePropertyChanged(BindableObject bindable, object newValue, object oldValue)
{
Player component = bindable as Player;
component.SongTitleLabel.Text = (string)newValue;
}
#endregion SongTitle Bindable
#region ArtistName Bindable
public static readonly BindableProperty ArtistNameProperty =
BindableProperty.Create(propertyName: "ArtistName",
returnType: typeof(string),
declaringType: typeof(Player),
propertyChanged: OnArtistNamePropertyChanged);
public string ArtistName
{
get
{
return (string)GetValue(ArtistNameProperty);
}
set
{
SetValue(ArtistNameProperty, value);
}
}
private static void OnArtistNamePropertyChanged(BindableObject bindable, object newValue, object oldValue)
{
Player component = bindable as Player;
component.ArtistNameLabel.Text = (string)newValue;
}
#endregion ArtistName Bindable
#region PreviousButton
public static readonly BindableProperty PreviousButtonCommandProperty =
BindableProperty.Create(propertyName: "PreviousButtonCommand",
returnType: typeof(Command),
propertyChanged: OnPreviousButtonPropertyChanged,
declaringType: typeof(Player));
public Command PreviousButtonCommand
{
get
{
return (Command)GetValue(PreviousButtonCommandProperty);
}
set
{
SetValue(PreviousButtonCommandProperty, value);
}
}
private void OnPreviousButtonClicked(object sender, EventArgs args)
{
if (PreviousButtonCommand.CanExecute(null))
{
PreviousButtonCommand.Execute(null);
PreviousButtonCommand.ChangeCanExecute();
PlayButtonCommand.ChangeCanExecute();
NextButtonCommand.ChangeCanExecute();
}
}
/// <summary>
/// Event handler to hook up can execute events on property changed
/// </summary>
/// <param name="bindable"></param>
/// <param name="newValue"></param>
/// <param name="oldValue"></param>
private static void OnPreviousButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
Player component = bindable as Player;
if (newValue is Command)
{
Command cmd = newValue as Command;
component.PreviousButton.Clicked += component.OnPreviousButtonClicked;
cmd.CanExecuteChanged += (sender, e) => OnPreviousButtonCanExecuteChanged(sender, e, component, cmd);
}
if (oldValue is Command && oldValue != null)
{
Command cmd = newValue as Command;
component.PreviousButton.Clicked -= component.OnPreviousButtonClicked;
cmd.CanExecuteChanged -= (sender, e) => OnPreviousButtonCanExecuteChanged(sender, e, component, cmd);
}
}
/// <summary>
/// Can execute changed event handler
/// </summary>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
/// <param name="component"></param>
/// <param name="cmd"></param>
private static void OnPreviousButtonCanExecuteChanged(object sender,
EventArgs eventArgs,
Player component,
Command cmd)
{
component.NextButton.IsEnabled = cmd.CanExecute(null);
}
#endregion PreviousButton
#region PlayButton
public static readonly BindableProperty PlayButtonCommandProperty =
BindableProperty.Create(propertyName: "PlayButtonCommand",
returnType: typeof(Command),
propertyChanged: OnPlayButtonPropertyChanged,
declaringType: typeof(Player));
public Command PlayButtonCommand
{
get
{
return (Command)GetValue(PlayButtonCommandProperty);
}
set
{
SetValue(PlayButtonCommandProperty, value);
}
}
private void OnPlayButtonClicked(object sender, EventArgs args)
{
if (PlayButtonCommand.CanExecute(null))
{
PlayButtonCommand.Execute(null);
PreviousButtonCommand.ChangeCanExecute();
PlayButtonCommand.ChangeCanExecute();
NextButtonCommand.ChangeCanExecute();
}
}
/// <summary>
/// Event handler to hook up can execute events on property changed
/// </summary>
/// <param name="bindable"></param>
/// <param name="newValue"></param>
/// <param name="oldValue"></param>
private static void OnPlayButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
Player component = bindable as Player;
if (newValue is Command)
{
Command cmd = newValue as Command;
component.PlayButton.Clicked += component.OnPlayButtonClicked;
cmd.CanExecuteChanged += (sender, e) => OnPlayButtonCanExecuteChanged(sender, e, component, cmd);
}
if (oldValue is Command && oldValue != null)
{
Command cmd = newValue as Command;
component.PlayButton.Clicked -= component.OnPlayButtonClicked;
cmd.CanExecuteChanged -= (sender, e) => OnPlayButtonCanExecuteChanged(sender, e, component, cmd);
}
}
/// <summary>
/// Can execute changed event handler
/// </summary>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
/// <param name="component"></param>
/// <param name="cmd"></param>
private static void OnPlayButtonCanExecuteChanged(object sender,
EventArgs eventArgs,
Player component,
Command cmd)
{
component.NextButton.IsEnabled = cmd.CanExecute(null);
}
#endregion PlayButton
#region NextButton
public static readonly BindableProperty NextButtonCommandProperty =
BindableProperty.Create(propertyName: "NextButtonCommand",
returnType: typeof(Command),
declaringType: typeof(Player),
propertyChanged: OnNextButtonPropertyChanged);
public Command NextButtonCommand
{
get
{
return (Command)GetValue(NextButtonCommandProperty);
}
set
{
SetValue(NextButtonCommandProperty, value);
}
}
private void OnNextButtonClicked(object sender, EventArgs args)
{
if (NextButtonCommand.CanExecute(null))
{
NextButtonCommand.Execute(null);
PreviousButtonCommand.ChangeCanExecute();
PlayButtonCommand.ChangeCanExecute();
NextButtonCommand.ChangeCanExecute();
}
}
/// <summary>
/// Event handler to hook up can execute events on property changed
/// </summary>
/// <param name="bindable"></param>
/// <param name="newValue"></param>
/// <param name="oldValue"></param>
private static void OnNextButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
Player component = bindable as Player;
if (newValue is Command)
{
Command cmd = newValue as Command;
component.NextButton.Clicked += component.OnNextButtonClicked;
cmd.CanExecuteChanged += (sender, e) => OnNextButtonCanExecuteChanged(sender, e, component, cmd);
}
if (oldValue is Command && oldValue != null)
{
Command cmd = oldValue as Command;
component.NextButton.Clicked -= component.OnNextButtonClicked;
cmd.CanExecuteChanged -= (sender, e) => OnNextButtonCanExecuteChanged(sender, e, component, cmd);
}
}
/// <summary>
/// Can execute changed event handler
/// </summary>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
/// <param name="component"></param>
/// <param name="cmd"></param>
private static void OnNextButtonCanExecuteChanged(object sender,
EventArgs eventArgs,
Player component,
Command cmd)
{
component.NextButton.IsEnabled = cmd.CanExecute(null);
}
#endregion PlayButton
}
}

View File

@ -1,163 +0,0 @@
using System;
using Xamarin.Forms;
using Aurora.Design.Views;
using Aurora.Services.PlayerService;
using Aurora.Models.Media;
namespace Aurora.Design.Components.MediaPlayer
{
public class PlayerViewModel : BaseViewModel
{
PlayerService _playerService;
BaseMetadata _metadata;
public PlayerViewModel()
{
_playerService = PlayerService.Instance;
_playerService.PlaybackStateChanged += OnPlaybackStateChanged;
_playerService.MediaChanged += OnMediaChanged;
PlayCommand = new Command(OnPlayExecute, CanPlayExecute);
PreviousCommand = new Command(OnPreviousExecute, CanPreviousExecute);
NextCommand = new Command(OnNextExecute, CanNextExecute);
}
~PlayerViewModel()
{
_playerService.PlaybackStateChanged -= OnPlaybackStateChanged;
}
#region Public Properties
public Command PlayCommand { get; private set; }
public Command NextCommand { get; private set; }
public Command PreviousCommand { get; private set; }
public string PlayButtonText
{
get { return _playerService.PlaybackState == PlaybackState.Buffering ? "Play" : "Pause"; }
}
/// <summary>
/// TODO keep player view generic between audio and video.
/// </summary>
/// <value></value>
public string ArtistName
{
get
{
if (_metadata == null)
{
return "";
}
AudioMetadata metadata = _metadata as AudioMetadata;
return metadata.Artist;
}
}
/// <summary>
/// TODO keep player view generic between audio and video.
/// </summary>
/// <value></value>
public string SongTitle
{
get
{
if (_metadata == null)
{
return "";
}
AudioMetadata metadata = _metadata as AudioMetadata;
return metadata.Title;
}
}
#endregion Public Properties
#region Public Methods
public bool CanPreviousExecute()
{
return true;
}
public void OnPreviousExecute()
{
}
public bool CanPlayExecute()
{
switch (_playerService.PlaybackState)
{
case PlaybackState.Buffering:
{
return true;
}
case PlaybackState.Playing:
{
return true;
}
case PlaybackState.Stopped:
{
return false;
}
}
return false;
}
public void OnPlayExecute()
{
switch (_playerService.PlaybackState)
{
case PlaybackState.Buffering:
{
_playerService.Play();
break;
}
case PlaybackState.Playing:
{
_playerService.Pause();
break;
}
}
}
public bool CanNextExecute()
{
return true;
}
public void OnNextExecute()
{
}
#endregion public Methods
#region EventHandlers
/// <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");
PlayCommand.ChangeCanExecute();
NextCommand.ChangeCanExecute();
PreviousCommand.ChangeCanExecute();
}
/// <summary>
/// PlayerService media changed event handler.
/// </summary>
/// <param name="sender">The sending object.</param>
/// <param name="args">Event arguments.</param>
public void OnMediaChanged(object sender, MediaChangedEventArgs args)
{
_metadata = args.NewMetadata;
OnPropertyChanged("ArtistName");
OnPropertyChanged("SongTitle");
}
#endregion EventHandlers
}
}

View File

@ -15,9 +15,8 @@ namespace Aurora.Design.Components.NavigationMenu
public int Id { get; set; }
public string Title { get; set; }
public string Group { get; set; }
public Type TargetType { get; set; }
public Type TargetViewModelType { get; set; }
}
}

View File

@ -129,7 +129,7 @@ namespace Aurora.Design.Components.Queue
private static void OnDoubleClickPropertyChanged(BindableObject bindable, object newValue, object oldValue)
{
Queue control = bindable as Queue;
var queueDataGrid = control.FindByName("QueueDataGrid") as DataGrid;
var queueDataGrid = control.QueueDataGrid;
if (queueDataGrid.GestureRecognizers.Count > 0)
{
var gestureRecognizer = queueDataGrid.GestureRecognizers.First();

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
}
}

View File

@ -93,5 +93,13 @@ namespace Aurora.Services.ClientService
}
}
}
public void StopEvents()
{
if (!_eventCancellationTokenSource.IsCancellationRequested)
{
_eventCancellationTokenSource.Cancel();
}
}
}
}

View File

@ -34,6 +34,19 @@ namespace Aurora.Services.PlayerService
get { return _state; }
}
public bool IsLoaded
{
get
{
return this._currentMedia == null;
}
}
public bool IsMediaLoaded(BaseMedia media)
{
return _currentMedia == media;
}
/// <summary>
/// Load media into the media player.
/// </summary>
@ -51,7 +64,11 @@ namespace Aurora.Services.PlayerService
_mediaPlayer.Stopped += OnStopped;
md.Dispose();
MediaChanged.Invoke(this, new MediaChangedEventArgs(_currentMedia.Metadata));
if (MediaChanged != null)
{
MediaChanged.Invoke(this, new MediaChangedEventArgs(_currentMedia.Metadata));
}
}
/// <summary>
@ -62,7 +79,11 @@ namespace Aurora.Services.PlayerService
PlaybackState oldState = _state;
_state = PlaybackState.Playing;
_mediaPlayer.Play();
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
if (PlaybackStateChanged != null)
{
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
}
}
/// <summary>
@ -73,7 +94,11 @@ namespace Aurora.Services.PlayerService
PlaybackState oldState = _state;
_state = PlaybackState.Buffering;
_mediaPlayer.Pause();
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
if (PlaybackStateChanged != null)
{
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
}
}
/// <summary>
@ -84,7 +109,12 @@ namespace Aurora.Services.PlayerService
PlaybackState oldState = _state;
_state = PlaybackState.Stopped;
_mediaPlayer.Stop();
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
if (PlaybackStateChanged != null)
{
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
}
}
public void Enqueue(BaseMedia song)
@ -103,6 +133,7 @@ namespace Aurora.Services.PlayerService
private void Unload()
{
_currentMedia.Unload();
_currentMedia = null;
_mediaPlayer.Media = null;
_mediaPlayer = null;
}