Commit d9bc2eda authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Low-level support for events attaching/detaching

parent 113488b7
......@@ -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,
};
};
......@@ -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);
}
};
};
......@@ -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
......
......@@ -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
......
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