Commit 4633523b authored by Martin Finkel's avatar Martin Finkel

Remove LibVLC from VideoView and uncouple MediaPlayer from the view lifecycle

parent 05debdd8
using LibVLCSharp.Shared;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
......@@ -17,21 +18,38 @@ namespace LibVLCSharp.WPF
public VideoView()
{
DefaultStyleKey = typeof(VideoView);
}
private void Attach()
{
if (!IsDesignMode)
{
Core.Initialize();
if (MediaPlayer == null)
{
Trace.Write("No MediaPlayer is set, aborting...");
return;
}
LibVLC = new LibVLC();
MediaPlayer = new MediaPlayer(LibVLC);
var hwnd = (Template.FindName(PART_PlayerView, this) as System.Windows.Forms.Panel)?.Handle;
if (hwnd == null)
{
Trace.WriteLine("HWND is NULL, aborting...");
return;
}
Unloaded += VideoView_Unloaded;
MediaPlayer.Hwnd = (IntPtr)hwnd;
}
}
~VideoView()
private void Detach()
{
Dispose();
if (!IsDesignMode)
{
if (MediaPlayer != null)
{
MediaPlayer.Hwnd = IntPtr.Zero;
}
}
}
private bool IsDesignMode => (bool)DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue;
......@@ -39,12 +57,23 @@ namespace LibVLCSharp.WPF
private bool IsUpdatingContent { get; set; }
private UIElement ViewContent { get; set; }
public MediaPlayer MediaPlayer { get; private set; }
public LibVLC LibVLC { get; private set; }
private void VideoView_Unloaded(object sender, RoutedEventArgs e)
private MediaPlayer _mediaPlayer;
public MediaPlayer MediaPlayer
{
Dispose();
get => _mediaPlayer;
set
{
if (_mediaPlayer != value)
{
Detach();
_mediaPlayer = value;
if (_mediaPlayer != null)
{
Attach();
}
}
}
}
public override void OnApplyTemplate()
......@@ -56,14 +85,10 @@ namespace LibVLCSharp.WPF
var windowsFormsHost = Template.FindName(PART_PlayerHost, this) as FrameworkElement;
if (windowsFormsHost != null)
{
ForegroundWindow = new ForegroundWindow(windowsFormsHost);
ForegroundWindow.Content = ViewContent;
}
var hwnd = (Template.FindName(PART_PlayerView, this) as System.Windows.Forms.Panel)?.Handle;
if (hwnd != null)
{
MediaPlayer.Hwnd = (IntPtr)hwnd;
ForegroundWindow = new ForegroundWindow(windowsFormsHost)
{
Content = ViewContent
};
}
}
}
......@@ -94,24 +119,29 @@ namespace LibVLCSharp.WPF
}
}
public void Dispose()
{
Unloaded -= VideoView_Unloaded;
#region IDisposable Support
if (MediaPlayer != null)
bool disposedValue;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (MediaPlayer.IsPlaying)
MediaPlayer.Stop();
MediaPlayer.Hwnd = IntPtr.Zero;
MediaPlayer.Dispose();
MediaPlayer = null;
}
if (disposing)
{
Detach();
}
if (LibVLC != null)
{
LibVLC.Dispose();
LibVLC = null;
ViewContent = null;
ForegroundWindow = null;
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
#endregion
}
}
\ No newline at end of file
......@@ -14,30 +14,60 @@ namespace LibVLCSharp.Platforms.Android
public class VideoView : SurfaceView, IVLCVoutCallback, IVideoView
{
MediaPlayer _mediaPlayer;
LibVLC _libVLC;
AWindow _awindow;
LayoutChangeListener _layoutListener;
#region ctors
public VideoView(IntPtr javaReference, JniHandleOwnership transfer, string[] cliOptions = default (string[])) : base(javaReference, transfer) => Init(cliOptions);
public VideoView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public VideoView(Context context, string[] cliOptions = default(string[])) : base(context) => Init(cliOptions);
public VideoView(Context context) : base(context)
{
}
public VideoView(Context context, IAttributeSet attrs, string[] cliOptions = default(string[])) : base(context, attrs) => Init(cliOptions);
public VideoView(Context context, IAttributeSet attrs) : base(context, attrs)
{
}
public VideoView(Context context, IAttributeSet attrs, int defStyleAttr, string[] cliOptions = default(string[])) : base(context, attrs, defStyleAttr) => Init(cliOptions);
public VideoView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
}
public VideoView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes, string[] cliOptions = default(string[]))
: base(context, attrs, defStyleAttr, defStyleRes) => Init(cliOptions);
public VideoView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes)
: base(context, attrs, defStyleAttr, defStyleRes)
{
}
#endregion
public LibVLCSharp.Shared.MediaPlayer MediaPlayer => _mediaPlayer;
public LibVLC LibVLC => _libVLC;
/// <summary>
/// The MediaPlayer object attached to this VideoView. Use this to manage playback and more
/// </summary>
public MediaPlayer MediaPlayer
{
get => _mediaPlayer;
set
{
if (_mediaPlayer != value)
{
Detach();
_mediaPlayer = value;
if (_mediaPlayer != null)
{
Attach();
}
}
}
}
void Attach()
{
if (_mediaPlayer == null)
throw new NullReferenceException(nameof(_mediaPlayer));
_awindow = new AWindow(new SurfaceCallback(_mediaPlayer));
_awindow.AddCallback(this);
_awindow.SetVideoView(this);
......@@ -51,16 +81,18 @@ namespace LibVLCSharp.Platforms.Android
void Detach()
{
_awindow.RemoveCallback(this);
_awindow.DetachViews();
_awindow?.RemoveCallback(this);
_awindow?.DetachViews();
_mediaPlayer.SetAndroidContext(IntPtr.Zero);
_mediaPlayer?.SetAndroidContext(IntPtr.Zero);
RemoveOnLayoutChangeListener(_layoutListener);
_layoutListener.Dispose();
if (_layoutListener != null)
RemoveOnLayoutChangeListener(_layoutListener);
_layoutListener?.Dispose();
_layoutListener = null;
_awindow.Dispose();
_awindow?.Dispose();
_awindow = null;
}
......@@ -72,25 +104,15 @@ namespace LibVLCSharp.Platforms.Android
{
}
void Init(string[] cliOptions)
{
Core.Initialize();
_libVLC = new LibVLC(cliOptions);
_mediaPlayer = new MediaPlayer(_libVLC);
Attach();
}
/// <summary>
/// Detach the mediaplayer from the view and dispose the view
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Detach();
_mediaPlayer.Media?.Dispose();
_mediaPlayer.Dispose();
_libVLC.Dispose();
}
}
}
\ No newline at end of file
......@@ -6,30 +6,54 @@ namespace LibVLCSharp.Platforms.Mac
{
public class VideoView : NSView, IVideoView
{
public VideoView(string[] cliOptions = default(string[]))
{
LibVLC = new LibVLC(cliOptions);
MediaPlayer = new Shared.MediaPlayer(LibVLC);
Shared.MediaPlayer _mediaPlayer;
Attach();
/// <summary>
/// The MediaPlayer object attached to this VideoView. Use this to manage playback and more
/// </summary>
public Shared.MediaPlayer MediaPlayer
{
get => _mediaPlayer;
set
{
if (_mediaPlayer != value)
{
Detach();
_mediaPlayer = value;
if (_mediaPlayer != null)
{
Attach();
}
}
}
}
public Shared.MediaPlayer MediaPlayer { get; }
public LibVLC LibVLC { get; }
void Attach() => MediaPlayer.NsObject = Handle;
void Attach()
{
if (MediaPlayer != null)
{
MediaPlayer.NsObject = Handle;
}
}
void Detach() => MediaPlayer.NsObject = IntPtr.Zero;
void Detach()
{
if (MediaPlayer != null)
{
MediaPlayer.NsObject = IntPtr.Zero;
}
}
/// <summary>
/// Detach the mediaplayer from the view and dispose the view
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Detach();
MediaPlayer.Media?.Dispose();
MediaPlayer.Dispose();
LibVLC.Dispose();
}
}
}
}
\ No newline at end of file
......@@ -8,30 +8,54 @@ namespace LibVLCSharp.Platforms.iOS
{
public class VideoView : UIView, IVideoView
{
public VideoView(string[] cliOptions = default(string[]))
Shared.MediaPlayer _mediaPlayer;
/// <summary>
/// The MediaPlayer object attached to this VideoView. Use this to manage playback and more
/// </summary>
public Shared.MediaPlayer MediaPlayer
{
LibVLC = new LibVLC(cliOptions);
MediaPlayer = new Shared.MediaPlayer(LibVLC);
Attach();
get => _mediaPlayer;
set
{
if (_mediaPlayer != value)
{
Detach();
_mediaPlayer = value;
if (_mediaPlayer != null)
{
Attach();
}
}
}
}
public Shared.MediaPlayer MediaPlayer { get; }
public LibVLC LibVLC { get; }
void Attach() => MediaPlayer.NsObject = Handle;
void Attach()
{
if (MediaPlayer != null)
{
MediaPlayer.NsObject = Handle;
}
}
void Detach() => MediaPlayer.NsObject = IntPtr.Zero;
void Detach()
{
if (MediaPlayer != null)
{
MediaPlayer.NsObject = IntPtr.Zero;
}
}
/// <summary>
/// Detach the mediaplayer from the view and dispose the view
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Detach();
MediaPlayer.Media?.Dispose();
MediaPlayer.Dispose();
LibVLC.Dispose();
}
}
}
\ No newline at end of file
......@@ -3,6 +3,5 @@
public interface IVideoView
{
MediaPlayer MediaPlayer { get; }
LibVLC LibVLC { get; }
}
}
\ 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