From: RĂ©mi Denis-Courmont Date: Sun, 22 Feb 2009 14:33:10 +0000 (+0200) Subject: Low-level support for events attaching/detaching X-Git-Tag: 1.0.0-pre1~487 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=d9bc2eda82bb3fc99a1fef77ccd6076a2625517b;p=vlc Low-level support for events attaching/detaching --- diff --git a/bindings/cil/src/libvlc.cs b/bindings/cil/src/libvlc.cs index df676e1c04..45003c4bd6 100644 --- a/bindings/cil/src/libvlc.cs +++ b/bindings/cil/src/libvlc.cs @@ -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, }; }; diff --git a/bindings/cil/src/marshal.cs b/bindings/cil/src/marshal.cs index 51558ecf07..166b90d8a8 100644 --- a/bindings/cil/src/marshal.cs +++ b/bindings/cil/src/marshal.cs @@ -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 events; + /**< references to our unmanaged function pointers */ + + internal EventingObject () : base () + { + events = new Dictionary (); + } + + /** + * 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); + } + }; }; diff --git a/bindings/cil/src/media.cs b/bindings/cil/src/media.cs index 60a61d9bee..575e4c87c7 100644 --- a/bindings/cil/src/media.cs +++ b/bindings/cil/src/media.cs @@ -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 diff --git a/bindings/cil/src/player.cs b/bindings/cil/src/player.cs index bfd622d274..eda3dd907c 100644 --- a/bindings/cil/src/player.cs +++ b/bindings/cil/src/player.cs @@ -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