VideoView.cs 3.79 KB
Newer Older
Jérémy VIGNELLES's avatar
Jérémy VIGNELLES committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
using System;
using System.Runtime.InteropServices;
using Gdk;
using Gtk;
using LibVLCSharp.Shared;

namespace LibVLCSharp.GTK
{
    /// <summary>
    /// GTK VideoView for Windows, Linux and Mac.
    /// Mac is currently unsupported (see https://github.com/mono/gtk-sharp/issues/257)
    /// </summary>
    public class VideoView : DrawingArea, IVideoView
    {
        struct Native
        {
            /// <summary>
            /// Gets the window's HWND
            /// </summary>
            /// <remarks>Window only</remarks>
            /// <param name="gdkWindow">The pointer to the GdkWindow object</param>
            /// <returns>The window's HWND</returns>
            [DllImport("libgdk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
            internal static extern IntPtr gdk_win32_drawable_get_handle(IntPtr gdkWindow);

            /// <summary>
            /// Gets the window's XID
            /// </summary>
            /// <remarks>Linux X11 only</remarks>
            /// <param name="gdkWindow">The pointer to the GdkWindow object</param>
            /// <returns>The window's XID</returns>
            [DllImport("libgdk-x11-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
            internal static extern uint gdk_x11_drawable_get_xid(IntPtr gdkWindow);

            /// <summary>
            /// Gets the nsview's handle
            /// </summary>
            /// <remarks>Mac only</remarks>
            /// <param name="gdkWindow">The pointer to the GdkWindow object</param>
            /// <returns>The nsview's handle</returns>
            [DllImport("libgdk-quartz-2.0.0.dylib")]
            internal static extern IntPtr gdk_quartz_window_get_nsview(IntPtr gdkWindow);
        }

        private MediaPlayer _mediaPlayer;

        public VideoView()
        {
            Color black = Color.Zero;
            Color.Parse("black", ref black);
            ModifyBg(StateType.Normal, black);

            Realized += (s, e) => Attach();
        }

        public MediaPlayer MediaPlayer
        {
            get
            {
                return _mediaPlayer;
            }
            set
            {
                if (ReferenceEquals(_mediaPlayer, value))
                {
                    return;
                }

                Detach();
                _mediaPlayer = value;
                Attach();
            }
        }

        void Attach()
        {
            if (!IsRealized || _mediaPlayer == null)
            {
                return;
            }

            if (PlatformHelper.IsWindows)
            {
                MediaPlayer.Hwnd = Native.gdk_win32_drawable_get_handle(GdkWindow.Handle);
            }
            else if (PlatformHelper.IsLinux)
            {
                MediaPlayer.XWindow = Native.gdk_x11_drawable_get_xid(GdkWindow.Handle);
            }
            else if (PlatformHelper.IsMac)
            {
                MediaPlayer.NsObject = Native.gdk_quartz_window_get_nsview(GdkWindow.Handle);
            }
            else
            {
                throw new PlatformNotSupportedException();
            }
        }

        void Detach()
        {
            if (!IsRealized || _mediaPlayer == null)
            {
                return;
            }

            if (PlatformHelper.IsWindows)
            {
                MediaPlayer.Hwnd = IntPtr.Zero;
            }
            else if (PlatformHelper.IsLinux)
            {
                MediaPlayer.XWindow = 0;
            }
            else if (PlatformHelper.IsMac)
            {
                MediaPlayer.NsObject = IntPtr.Zero;
            }
            else
            {
                throw new PlatformNotSupportedException();
            }
        }

        public override void Dispose()
        {
            Detach();
            base.Dispose();
        }
    }
}