Commit 332cf8d0 authored by Stéphane Mitermite's avatar Stéphane Mitermite Committed by Martin Finkel

Improves MVVM scenario

- Rename Loaded event which could be confusing
- Fix support for changing mediaplayers multiple times on a videoView
- Simplifies the sample
parent 3e771727
......@@ -23,16 +23,20 @@ namespace LibVLCSharp.Forms.Platforms.GTK
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
if (Control == null)
{
......
using LibVLCSharp.Shared;
using LibVLCSharp.Forms.Platforms.WPF;
using LibVLCSharp.Forms.Platforms.WPF;
using LibVLCSharp.Forms.Shared;
using LibVLCSharp.Shared;
using Xamarin.Forms.Platform.WPF;
[assembly: ExportRenderer(typeof(VideoView), typeof(VideoViewRenderer))]
......@@ -19,16 +19,20 @@ namespace LibVLCSharp.Forms.Platforms.WPF
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
Control.MediaPlayer = e.NewMediaPlayer;
}
......
......@@ -27,16 +27,20 @@ namespace LibVLCSharp.Forms.Platforms.Android
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
Control.MediaPlayer = e.NewMediaPlayer;
Control.TriggerLayoutChangeListener();
......
......@@ -22,16 +22,20 @@ namespace LibVLCSharp.Forms.Platforms.Mac
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
Control.MediaPlayer = e.NewMediaPlayer;
}
......
......@@ -24,16 +24,20 @@ namespace LibVLCSharp.Forms.Platforms.iOS
if (e.OldElement != null)
{
e.OldElement.MediaPlayerChanged -= OnMediaPlayerChanged;
e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
}
if (e.NewElement != null)
{
e.NewElement.MediaPlayerChanged += OnMediaPlayerChanged;
e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
if (Control.MediaPlayer != e.NewElement.MediaPlayer)
{
OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control.MediaPlayer, e.NewElement.MediaPlayer));
}
}
}
private void OnMediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
private void OnMediaPlayerChanging(object sender, MediaPlayerChangingEventArgs e)
{
Control.MediaPlayer = e.NewMediaPlayer;
}
......
......@@ -8,20 +8,19 @@ namespace LibVLCSharp.Forms.Shared
public class VideoView : View
{
/// <summary>
/// Raised when a new MediaPlayer is set and attached to the view
/// Raised when a new MediaPlayer is set and will be attached to the view
/// </summary>
public event EventHandler<MediaPlayerChangedEventArgs> MediaPlayerChanged;
public event EventHandler<MediaPlayerChangingEventArgs> MediaPlayerChanging;
/// <summary>
/// Raised after the first mediaplayer has been set.
/// This is mostly needed with LibVLCSharp.Forms.WPF to prevent timing issues regarding HWND creation.
/// It is safe to call Play() when Loaded has been raised.
/// Raised when a new MediaPlayer is set and attached to the view
/// </summary>
public event EventHandler Loaded;
public event EventHandler<MediaPlayerChangedEventArgs> MediaPlayerChanged;
public static readonly BindableProperty MediaPlayerProperty = BindableProperty.Create(nameof(MediaPlayer),
typeof(LibVLCSharp.Shared.MediaPlayer),
public static readonly BindableProperty MediaPlayerProperty = BindableProperty.Create(nameof(MediaPlayer),
typeof(LibVLCSharp.Shared.MediaPlayer),
typeof(VideoView),
propertyChanging: OnMediaPlayerChanging,
propertyChanged: OnMediaPlayerChanged);
/// <summary>
......@@ -33,14 +32,18 @@ namespace LibVLCSharp.Forms.Shared
set { SetValue(MediaPlayerProperty, value); }
}
private static void OnMediaPlayerChanging(BindableObject bindable, object oldValue, object newValue)
{
var videoView = (VideoView)bindable;
Debug.WriteLine("OnMediaPlayerChanging");
videoView.MediaPlayerChanging?.Invoke(videoView, new MediaPlayerChangingEventArgs(oldValue as LibVLCSharp.Shared.MediaPlayer, newValue as LibVLCSharp.Shared.MediaPlayer));
}
private static void OnMediaPlayerChanged(BindableObject bindable, object oldValue, object newValue)
{
var videoView = (VideoView)bindable;
Trace.WriteLine("OnMediaPlayerChanged");
Debug.WriteLine("OnMediaPlayerChanged");
videoView.MediaPlayerChanged?.Invoke(videoView, new MediaPlayerChangedEventArgs(oldValue as LibVLCSharp.Shared.MediaPlayer, newValue as LibVLCSharp.Shared.MediaPlayer));
if(oldValue == null && newValue != null) // assuming this is the first MediaPlayer set
videoView.Loaded?.Invoke(videoView, EventArgs.Empty);
}
}
}
\ No newline at end of file
......@@ -19,7 +19,7 @@ namespace LibVLCSharp.WPF
{
DefaultStyleKey = typeof(VideoView);
}
public static readonly DependencyProperty MediaPlayerProperty = DependencyProperty.Register(nameof(MediaPlayer),
typeof(MediaPlayer),
typeof(VideoView),
......@@ -63,7 +63,7 @@ namespace LibVLCSharp.WPF
Content = ViewContent
};
}
Hwnd = (Template.FindName(PART_PlayerView, this) as System.Windows.Forms.Panel)?.Handle ?? IntPtr.Zero;
if (Hwnd == null)
{
......@@ -116,8 +116,8 @@ namespace LibVLCSharp.WPF
{
if (disposing)
{
if(MediaPlayer != null)
{
if (MediaPlayer != null)
{
MediaPlayer.Hwnd = IntPtr.Zero;
}
}
......
using System;
namespace LibVLCSharp.Shared
{
public class MediaPlayerChangedEventArgs : EventArgs
{
public MediaPlayerChangedEventArgs(LibVLCSharp.Shared.MediaPlayer oldMediaPlayer, LibVLCSharp.Shared.MediaPlayer newMediaPlayer)
{
OldMediaPlayer = oldMediaPlayer;
NewMediaPlayer = newMediaPlayer;
}
public LibVLCSharp.Shared.MediaPlayer OldMediaPlayer { get; }
public LibVLCSharp.Shared.MediaPlayer NewMediaPlayer { get; }
}
}
using System;
namespace LibVLCSharp.Shared
{
public class MediaPlayerChangingEventArgs : EventArgs
{
public MediaPlayerChangingEventArgs(LibVLCSharp.Shared.MediaPlayer oldMediaPlayer, LibVLCSharp.Shared.MediaPlayer newMediaPlayer)
{
OldMediaPlayer = oldMediaPlayer;
NewMediaPlayer = newMediaPlayer;
}
public LibVLCSharp.Shared.MediaPlayer OldMediaPlayer { get; }
public LibVLCSharp.Shared.MediaPlayer NewMediaPlayer { get; }
}
}
......@@ -103,7 +103,7 @@ namespace LibVLCSharp.Shared
int _mutedRegistrationCount;
int _unmutedRegistrationCount;
int _volumeChangedRegistrationCount;
EventCallback _positionChangedCallback;
EventCallback _mediaChangedCallback;
EventCallback _nothingSpecialCallback;
......@@ -137,7 +137,7 @@ namespace LibVLCSharp.Shared
protected internal override void AttachEvent<T>(EventType eventType, EventHandler<T> eventHandler)
{
lock(_lock)
lock (_lock)
{
switch (eventType)
{
......@@ -284,43 +284,43 @@ namespace LibVLCSharp.Shared
ref _eSSelectedRegistrationCount,
() => _mediaPlayerESSelected += eventHandler as EventHandler<MediaPlayerESSelectedEventArgs>,
() => _eSSelectedCallback = OnESSelected);
break;
break;
case EventType.MediaPlayerAudioDevice:
Attach(eventType,
ref _audioDeviceRegistrationCount,
() => _mediaPlayerAudioDevice += eventHandler as EventHandler<MediaPlayerAudioDeviceEventArgs>,
() => _audioDeviceCallback = OnAudioDevice);
break;
break;
case EventType.MediaPlayerCorked:
Attach(eventType,
ref _corkedRegistrationCount,
() => _mediaPlayerCorked += eventHandler as EventHandler<EventArgs>,
() => _corkedCallback = OnCorked);
break;
break;
case EventType.MediaPlayerUncorked:
Attach(eventType,
ref _uncorkedRegistrationCount,
() => _mediaPlayerUncorked += eventHandler as EventHandler<EventArgs>,
() => _uncorkedCallback = OnUncorked);
break;
break;
case EventType.MediaPlayerMuted:
Attach(eventType,
ref _mutedRegistrationCount,
() => _mediaPlayerMuted += eventHandler as EventHandler<EventArgs>,
() => _mutedCallback = OnMuted);
break;
break;
case EventType.MediaPlayerUnmuted:
Attach(eventType,
ref _unmutedRegistrationCount,
() => _mediaPlayerUnmuted += eventHandler as EventHandler<EventArgs>,
() => _unmutedCallback = OnUnmuted);
break;
break;
case EventType.MediaPlayerAudioVolume:
Attach(eventType,
ref _volumeChangedRegistrationCount,
() => _mediaPlayerVolumeChanged += eventHandler as EventHandler<MediaPlayerVolumeChangedEventArgs>,
() => _volumeChangedCallback = OnVolumeChanged);
break;
break;
default:
OnEventUnhandled(this, eventType);
break;
......@@ -520,7 +520,7 @@ namespace LibVLCSharp.Shared
}
}
}
#if IOS
[MonoPInvokeCallback(typeof(EventCallback))]
static void OnMediaChanged(IntPtr ptr)
......@@ -892,16 +892,4 @@ namespace LibVLCSharp.Shared
#endif
}
public class MediaPlayerChangedEventArgs : EventArgs
{
public MediaPlayerChangedEventArgs(LibVLCSharp.Shared.MediaPlayer oldMediaPlayer, LibVLCSharp.Shared.MediaPlayer newMediaPlayer)
{
OldMediaPlayer = oldMediaPlayer;
NewMediaPlayer = newMediaPlayer;
}
public LibVLCSharp.Shared.MediaPlayer OldMediaPlayer { get; }
public LibVLCSharp.Shared.MediaPlayer NewMediaPlayer { get; }
}
}
\ No newline at end of file
......@@ -8,5 +8,5 @@
<local:MainViewModel />
</ContentPage.BindingContext>
<shared:VideoView MediaPlayer="{Binding MediaPlayer}" x:Name="videoView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
<shared:VideoView MediaPlayer="{Binding MediaPlayer}" MediaPlayerChanged="VideoView_MediaPlayerChanged" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
</ContentPage>
using LibVLCSharp.Shared;
using System.Diagnostics;
using Xamarin.Forms;
namespace LibVLCSharp.Forms.Sample
{
public partial class MainPage : ContentPage
{
MainViewModel _vm;
public MainPage()
{
InitializeComponent();
......@@ -16,29 +13,12 @@ namespace LibVLCSharp.Forms.Sample
protected override void OnAppearing()
{
base.OnAppearing();
videoView.MediaPlayerChanged += VideoView_MediaPlayerChanged;
videoView.Loaded += VideoView_Loaded;
_vm = BindingContext as MainViewModel;
_vm.PropertyChanged += Vm_PropertyChanged;
_vm.Initialize();
}
private void VideoView_Loaded(object sender, System.EventArgs e)
{
_vm.MediaPlayer.Play();
}
private void Vm_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if(e.PropertyName.Equals(nameof(_vm.MediaPlayer)))
Trace.WriteLine("MediaPlayer change raised from ViewModel.Propertychanged");
((MainViewModel)BindingContext).OnAppearing();
}
private void VideoView_MediaPlayerChanged(object sender, MediaPlayerChangedEventArgs e)
{
Trace.WriteLine("VideoView_MediaPlayerChanged");
((MainViewModel)BindingContext).OnVideoViewInitialized();
}
}
}
\ No newline at end of file
using LibVLCSharp.Shared;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
namespace LibVLCSharp.Forms.Sample
{
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
LibVLC _libVLC;
public MainViewModel()
{
Task.Run((Action)Initialize);
}
private LibVLC LibVLC { get; set; }
private MediaPlayer _mediaPlayer;
public MediaPlayer MediaPlayer
......@@ -15,6 +23,9 @@ namespace LibVLCSharp.Forms.Sample
private set => Set(nameof(MediaPlayer), ref _mediaPlayer, value);
}
private bool IsLoaded { get; set; }
private bool IsVideoViewInitialized { get; set; }
private void Set<T>(string propertyName, ref T field, T value)
{
if (field == null && value != null || field != null && !field.Equals(value))
......@@ -24,17 +35,37 @@ namespace LibVLCSharp.Forms.Sample
}
}
public void Initialize()
private void Initialize()
{
Core.Initialize();
_libVLC = new LibVLC();
MediaPlayer = new MediaPlayer(_libVLC)
LibVLC = new LibVLC();
MediaPlayer = new MediaPlayer(LibVLC)
{
Media = new Media(_libVLC,
"http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4",
FromType.FromLocation)
Media = new Media(LibVLC,
"http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4",
FromType.FromLocation)
};
}
public void OnAppearing()
{
IsLoaded = true;
Play();
}
public void OnVideoViewInitialized()
{
IsVideoViewInitialized = true;
Play();
}
private void Play()
{
if (IsLoaded && IsVideoViewInitialized)
{
MediaPlayer.Play();
}
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment