Low-level support for events attaching/detaching
authorRémi Denis-Courmont <rdenis@simphalempin.com>
Sun, 22 Feb 2009 14:33:10 +0000 (16:33 +0200)
committerRémi Denis-Courmont <rdenis@simphalempin.com>
Sun, 22 Feb 2009 14:34:04 +0000 (16:34 +0200)
bindings/cil/src/libvlc.cs
bindings/cil/src/marshal.cs
bindings/cil/src/media.cs
bindings/cil/src/player.cs

index df676e1..45003c4 100644 (file)
@@ -117,10 +117,10 @@ namespace VideoLAN.LibVLC
         public static extern
         MediaListHandle MediaSubItems (MediaHandle media, NativeException ex);*/
 
-        /*[DllImport ("libvlc.dll", EntryPoint="libvlc_media_event_manager")]
+        [DllImport ("libvlc.dll", EntryPoint="libvlc_media_event_manager")]
         public static extern
-        EventManagerHandle MediaGetEventManager (MediaHandle media,
-                                                 NativeException ex);*/
+        EventManagerHandle MediaEventManager (MediaHandle media,
+                                              NativeException ex);
 
         [DllImport ("libvlc.dll", EntryPoint="libvlc_media_get_duration")]
         public static extern
@@ -168,11 +168,12 @@ namespace VideoLAN.LibVLC
         MediaHandle PlayerGetMedia (PlayerHandle player,
                                     NativeException ex);*/
 
-        /*[DllImport ("libvlc.dll",
+        [DllImport ("libvlc.dll",
                       EntryPoint="libvlc_media_player_event_manager")]
         public static extern
-        EventManagerHandle PlayerGetEventManager (PlayerHandle media,
-                                                  NativeException ex);*/
+        EventManagerHandle PlayerEventManager (PlayerHandle media,
+                                               NativeException ex);
+
         [DllImport ("libvlc.dll",
                     EntryPoint="libvlc_media_player_is_playing")]
         public static extern
@@ -326,5 +327,76 @@ namespace VideoLAN.LibVLC
         public static extern
         int PlayerCanPause (PlayerHandle player, NativeException ex);
 
+
+        /* TODO: video, audio */
+
+        /* event.c */
+        [DllImport ("libvlc.dll", EntryPoint="libvlc_event_attach")]
+        public static extern
+        void EventAttach (EventManagerHandle manager, EventType type,
+                          IntPtr callback, IntPtr user_data,
+                          NativeException ex);
+
+        [DllImport ("libvlc.dll", EntryPoint="libvlc_event_detach")]
+        public static extern
+        void EventDetach (EventManagerHandle manager, EventType type,
+                          IntPtr callback, IntPtr user_data,
+                          NativeException ex);
+
+        /* libvlc_event_type_name */
+    };
+
+    /**
+     * @brief EventCallback: LibVLC event handler
+     * @ingroup Internals
+     */
+    internal delegate void EventCallback (IntPtr ev, IntPtr data);
+
+    /**
+     * @brief EventType: LibVLC event types
+     * @ingroup Internals
+     */
+    internal enum EventType
+    {
+        MediaMetaChanged,
+        MediaSubItemAdded,
+        MediaDurationChanged,
+        MediaPreparsedChanged,
+        MediaFreed,
+        MediaStateChanged,
+
+        PlayerNothingSpecial,
+        PlayerOpening,
+        PlayerBuffering,
+        PlayerPlaying,
+        PlayerPaused,
+        PlayerStopped,
+        PlayerForward,
+        PlayerBackward,
+        PlayerEndReached,
+        PlayerEncounteredError,
+        PlayerTimeChanged,
+        PlayerPositionChanged,
+        PlayerSeekableChanged,
+        PlayerPausableChanged,
+
+        ListItemAdded,
+        ListWillAddItem,
+        ListItemDeleted,
+        ListWillDeleteItem,
+
+        ListViewItemAdded,
+        ListViewWillAddItem,
+        ListViewItemDeleted,
+        ListViewWillDeleteItem,
+
+        ListPlayerPlayed,
+        ListPlayerNextItemSet,
+        ListPlayerStopped,
+
+        DiscovererStarted,
+        DiscovererEnded,
+
+        PlayerTitleChanged,
     };
 };
index 51558ec..166b90d 100644 (file)
@@ -22,6 +22,8 @@
  **********************************************************************/
 
 using System;
+using System.Collections;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 
 namespace VideoLAN.LibVLC
@@ -63,7 +65,6 @@ namespace VideoLAN.LibVLC
             Destroy ();
             return true;
         }
-
     };
 
     /**
@@ -72,8 +73,7 @@ namespace VideoLAN.LibVLC
      *
      * This is the baseline for all managed LibVLC objects. It wraps:
      *  - an unmanaged LibVLC pointer,
-     *  - a native exception structure, and
-     *  - the object's native event manager.
+     *  - a native exception structure.
      */
     public class BaseObject : IDisposable
     {
@@ -121,4 +121,123 @@ namespace VideoLAN.LibVLC
             handle = null;
         }
     };
+
+    internal class EventManagerHandle : NonNullHandle
+    {
+        protected override void Destroy ()
+        {
+        }
+    };
+
+
+    /**
+     * @brief EventingObject: wrapper around an eventing LibVLC handle.
+     * @ingroup Internals
+     *
+     * This is the base class for all managed LibVLC objects which do have an
+     * event manager.
+     */
+    public abstract class EventingObject : BaseObject
+    {
+        /**
+         * @brief Managed to unmanaged event handler mapping
+         * @ingroup Internals
+         *
+         * The CLR cannot do reference counting for unmanaged callbacks.
+         * We keep track of handled events here instead.
+         */
+        private class Event
+        {
+            public EventCallback managed;
+            public IntPtr        unmanaged;
+
+            public Event (EventCallback managed, IntPtr unmanaged)
+            {
+                this.managed = managed;
+                this.unmanaged = unmanaged;
+            }
+        };
+        private Dictionary<EventType, Event> events;
+        /**< references to our unmanaged function pointers */
+
+        internal EventingObject () : base ()
+        {
+            events = new Dictionary<EventType, Event> ();
+        }
+
+        /**
+         * Releases unmanaged resources associated with the object.
+         * @param disposing true if the disposing the object explicitly,
+         *                  false if finalizing the object inside the GC.
+         */
+        protected override void Dispose (bool disposing)
+        {
+            events = null;
+            base.Dispose (disposing);
+        }
+
+        /**
+         * @return the unmanaged event manager for this object
+         */
+        internal abstract EventManagerHandle GetManager ();
+
+        /**
+         * Registers an event handler.
+         * @param type event type to register to
+         * @param callback callback to invoke when the event occurs
+         *
+         * @note
+         * For simplicity, we only allow one handler per type.
+         * Multicasting can be implemented higher up with managed code.
+         */
+        internal void Attach (EventType type, EventCallback callback)
+        {
+            EventManagerHandle manager;
+            IntPtr cb = Marshal.GetFunctionPointerForDelegate (callback);
+            Event ev = new Event (callback, cb);
+            bool unref = false;
+
+            if (events.ContainsKey (type))
+                throw new ArgumentException ("Duplicate event");
+
+            try
+            {
+                handle.DangerousAddRef (ref unref);
+                manager = GetManager ();
+                LibVLC.EventAttach (manager, type, cb, IntPtr.Zero, ex);
+            }
+            finally
+            {
+                if (unref)
+                    handle.DangerousRelease ();
+            }
+            Raise ();
+            events.Add (type, ev);
+        }
+
+        private void Detach (EventType type, IntPtr callback)
+        {
+            EventManagerHandle manager;
+            bool unref = false;
+
+            try
+            {
+                handle.DangerousAddRef (ref unref);
+                manager = GetManager ();
+                LibVLC.EventDetach (manager, type, callback, IntPtr.Zero, ex);
+            }
+            finally
+            {
+                if (unref)
+                    handle.DangerousRelease ();
+            }
+            Raise ();
+            events.Remove (type);
+        }
+
+        internal void Detach (EventType type)
+        {
+            Detach(type, events[type].unmanaged);
+        }
+    };
 };
index 60a61d9..575e4c8 100644 (file)
@@ -65,7 +65,7 @@ namespace VideoLAN.LibVLC
      * @ingroup API
      * Each media object represents an input media, such as a file or an URL.
      */
-    public class Media : BaseObject, ICloneable
+    public class Media : EventingObject, ICloneable
     {
         internal MediaHandle Handle
         {
@@ -154,6 +154,11 @@ namespace VideoLAN.LibVLC
             }
         }
 
+        internal override EventManagerHandle GetManager ()
+        {
+            return LibVLC.MediaEventManager (Handle, null);
+        }
+
         /**
          * Duration of the media in microseconds. The precision of the result
          * depends on the input stram protocol and file format. The value
index bfd622d..eda3dd9 100644 (file)
@@ -51,7 +51,7 @@ namespace VideoLAN.LibVLC
      * @ingroup API
      * Use this class to play a media.
      */
-    public class Player : BaseObject
+    public class Player : EventingObject
     {
         internal PlayerHandle Handle
         {
@@ -106,6 +106,11 @@ namespace VideoLAN.LibVLC
             Raise ();
         }
 
+        internal override EventManagerHandle GetManager ()
+        {
+            return LibVLC.PlayerEventManager (Handle, null);
+        }
+
         /**
          * Whether the player is currently active.
          * @version VLC 1.0