[vlc-devel] Support of events in Mozilla plugin - Beta

y.brehon at qiplay.com y.brehon at qiplay.com
Tue Dec 1 17:06:02 CET 2009


Here is an updated version of the patch. 
Most of the requests from the various people on the mailing list have been
taken into account.
However:
- We don't register events with libvlc when an eventlistener is created,
because events would then be associated to the playlist. This means as soon
as the video is stopped, events would no longer be attached. Moreover, this
technique prevents new event listeners from being attached while a video is
being played. This is why we chose to register for all events which may
interest the plugin right from the beginning, and then filter these events
as they are called.
- The event registration is not in the constructor because we need to
re-register for events every time the playlist changes, not only at
creation
- The different events are not registered in a unique way with libvlc:
this means we cannot provide a generic way of registering events and plan
for future events which don't yet exist. For now, only MediaPlayer events
are supported. Even if we were to use strncmp to figure out if the event is
a MediaPlayer event, some (e.g., MediaPlayerLengthChanged) will cause an
error.
- This is why for now, we register all "interesting" events in
VlcPlugin::playlist_select (no way of simply knowing which event are
"registerable" and which ones are not)
- There is not (yet ?) a removeListener method for a single event
listener.

Thanks for your input,
Yannick
-------------- next part --------------
From 049b3d72dccf7b4674883d6c18d8d13c120d531a Mon Sep 17 00:00:00 2001
From: Yannick Brehon <y.brehon at qiplay.com>
Date: Wed, 25 Nov 2009 00:55:01 +0100
Subject: [PATCH] Mozilla plugin event listeners.

---
 THANKS                                 |    2 +
 projects/mozilla/control/npolibvlc.cpp |  196 ++++++++++++++++++++++++++++++++
 projects/mozilla/control/npolibvlc.h   |   25 ++++-
 projects/mozilla/support/npunix.c      |   14 +++
 projects/mozilla/vlcplugin.cpp         |   95 +++++++++++++++
 projects/mozilla/vlcplugin.h           |  113 ++++++++++++++++++
 6 files changed, 444 insertions(+), 1 deletions(-)

diff --git a/THANKS b/THANKS
index 54fb75a..25cb3cb 100644
--- a/THANKS
+++ b/THANKS
@@ -22,6 +22,7 @@ Alexey Salmin <alexey dot salmin at gmail dot com> - Russian localisation
 Alexis Ballier <aballlier at gentoo dot org> - Additional options in configure
 Alexis de Lattre <alexis at videolan dot org> - Documentation, packaging, IGMPv3 support and various fixes
 Amanpreet Singh Alam <aalam at users dot sf dot net> - Punjabi translation
+Amir Gouini <a.gouini at qiplay dot com> - VLC mozilla plugin event listerners.
 Andrea Guzzo <xant at xant dot net> - dc1394 firewire support
 André de Barros Martins Ribeiro <andrerib at ajato.com.br> - Brazilian portuguese localization
 Andre Pang <adre.pang at csiro dot au> - Annodex support
@@ -316,6 +317,7 @@ William Hawkins - Speex RTP payload format
 Xavier Maillard <zedek at fxgsproject.org> - audio converters
 Xavier Marchesini <xav at alarue.net> - Win32 fixes
 Xènia Albà Cantero <xenia_alba at hotmail.com> - Catalan translation
+Yannick Bréhon <y.brehon at qiplay dot com> - VLC mozilla plugin event listerners.
 Ye zhang <yzhang90003 _at_ gmail dot com> - Fix for VLM RTSP concurent LEAVE make VLC crash
 Yuehua Zhao <zhao908 at hotmail.com> - real video codec
 Yuksel Yildirim <xleopar at yahoo d0t com> - Turkish localisation
diff --git a/projects/mozilla/control/npolibvlc.cpp b/projects/mozilla/control/npolibvlc.cpp
index 348880d..5125680 100644
--- a/projects/mozilla/control/npolibvlc.cpp
+++ b/projects/mozilla/control/npolibvlc.cpp
@@ -47,6 +47,71 @@
         return INVOKERESULT_GENERIC_ERROR; \
     } } while(false)
 
+#define ERROR_EVENT_NOT_FOUND "ERROR: One or more events could not be found."
+#define ERROR_API_VERSION "ERROR: NPAPI version not high enough. (Gecko >= 1.9 needed)"
+
+// Make a copy of an NPVariant.
+NPVariant copyNPVariant(const NPVariant& original)
+{
+    NPVariant res;
+
+    if (NPVARIANT_IS_STRING(original))
+        STRINGZ_TO_NPVARIANT(strdup(NPVARIANT_TO_STRING(original).utf8characters), res);
+    else if (NPVARIANT_IS_INT32(original))
+        INT32_TO_NPVARIANT(NPVARIANT_TO_INT32(original), res);
+    else if (NPVARIANT_IS_DOUBLE(original))
+        DOUBLE_TO_NPVARIANT(NPVARIANT_TO_DOUBLE(original), res);
+    else if (NPVARIANT_IS_OBJECT(original))
+    {
+        NPObject *obj = NPVARIANT_TO_OBJECT(original);
+        NPN_RetainObject(obj);
+        OBJECT_TO_NPVARIANT(obj, res);
+    }
+    else if (NPVARIANT_IS_BOOLEAN(original))
+        BOOLEAN_TO_NPVARIANT(NPVARIANT_TO_BOOLEAN(original), res);
+
+    return res;
+}
+
+// Parse an event Array given as a NPObject by JS.
+// This function is similar to LibvlcPlaylistNPObject::parseOptions,
+// but we don't use it because it's not clearly accessible and the FIXME flags
+// implie that it might be modified.
+bool parseEventArray(NPObject *obj, eventtypes_bitmap_t &eventToGet, NPP instance)
+{
+    NPIdentifier propId = NPN_GetStringIdentifier("length");
+    NPVariant value;
+
+    if (!NPN_GetProperty(instance, obj, propId, &value))
+        return false;
+
+    int count = NPVARIANT_TO_INT32(value);
+    NPN_ReleaseVariantValue(&value);
+    if (count == 0)
+        return false;
+
+    int nOptions = 0;
+    while (nOptions < count)
+    {
+        propId = NPN_GetIntIdentifier(nOptions);
+        // if there is no other string in the array.
+        if( ! NPN_GetProperty(instance, obj, propId, &value) )
+            break;
+
+        // if the element is not a string.
+        if( ! NPVARIANT_IS_STRING(value) )
+        {
+            NPN_ReleaseVariantValue(&value);
+            break;
+        }
+
+        if (!eventToGet.add_event(NPVARIANT_TO_STRING(value).utf8characters))
+            return false;
+        nOptions++;
+    }
+    return true;
+}
+
 /*
 ** implementation of libvlc root object
 */
@@ -77,6 +142,7 @@ const NPUTF8 * const LibvlcRootNPObject::propertyNames[] =
     "playlist",
     "subtitle",
     "video",
+    "events",
     "VersionInfo",
 };
 COUNTNAMES(LibvlcRootNPObject,propertyCount,propertyNames);
@@ -88,6 +154,7 @@ enum LibvlcRootNPObjectPropertyIds
     ID_root_playlist,
     ID_root_subtitle,
     ID_root_video,
+    ID_root_events,
     ID_root_VersionInfo,
 };
 
@@ -139,6 +206,14 @@ LibvlcRootNPObject::getProperty(int index, NPVariant &result)
                              RuntimeNPClass<LibvlcVideoNPObject>::getClass());
                 OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result);
                 return INVOKERESULT_NO_ERROR;
+            case ID_root_events:
+                // create child object in lazyman fashion to avoid
+                // ownership problem with firefox
+                if( ! eventObj )
+                    eventObj = NPN_CreateObject(_instance,
+                             RuntimeNPClass<LibvlcEventNPObject>::getClass());
+                OBJECT_TO_NPVARIANT(NPN_RetainObject(eventObj), result);
+                return INVOKERESULT_NO_ERROR;
             case ID_root_VersionInfo:
                 return invokeResultString(libvlc_get_version(),result);
             default:
@@ -1837,3 +1912,124 @@ LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
     }
     return INVOKERESULT_GENERIC_ERROR;
 }
+
+/*
+** implementation of libvlc event object
+*/
+
+const NPUTF8 * const LibvlcEventNPObject::propertyNames[] =
+{
+};
+
+enum LibvlcEventNPObjectPropertyIds
+{
+};
+COUNTNAMES(LibvlcEventNPObject,propertyCount,propertyNames);
+
+const NPUTF8 * const LibvlcEventNPObject::methodNames[] =
+{
+    "addListener",
+    "removeListeners",
+};
+COUNTNAMES(LibvlcEventNPObject,methodCount,methodNames);
+
+enum LibvlcEventNPObjectMethodIds
+{
+    ID_event_addListener,
+    ID_event_removeListeners,
+};
+
+bool LibvlcEventNPObject::parseArgs(const NPVariant *args, uint32_t argCount,
+                                    eventtypes_bitmap_t &eventToGet)
+{
+    if (argCount > 2)
+        eventToGet.clear();
+
+    for (int argIndex = 2; argIndex < argCount; argIndex++)
+    {
+        if (NPVARIANT_IS_STRING(args[argIndex]))
+        {
+            if (!eventToGet.add_event(NPVARIANT_TO_STRING(args[argIndex]).utf8characters))
+                return false;
+        }
+        else if (NPVARIANT_IS_OBJECT(args[argIndex]))
+        {
+            if (!parseEventArray(NPVARIANT_TO_OBJECT(args[argIndex]), eventToGet, _instance))
+                return false;
+        }
+        else
+            return false;
+    }
+    return true;
+}
+
+RuntimeNPObject::InvokeResult
+LibvlcEventNPObject::invoke(int index, const NPVariant *args,
+                            uint32_t argCount, NPVariant &result)
+{
+    /* is plugin still running */
+    if( isPluginRunning() )
+    {
+        libvlc_exception_t ex;
+        libvlc_exception_init(&ex);
+
+        switch( index )
+        {
+            case ID_event_addListener:
+                if (argCount >= 2)
+                {
+                    // Checks if the first argument is a NPObject
+                    if (!NPVARIANT_IS_OBJECT(args[0]))
+                        return INVOKERESULT_NO_SUCH_METHOD;
+
+                    // Checks if the browser has the NPAPI version 0.19 at least.
+                    if (!VlcPlugin::canUseEventListener())
+                    {
+                      NPN_SetException(this, strdup(ERROR_API_VERSION));
+                      return INVOKERESULT_GENERIC_ERROR;
+                    }
+
+                    VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
+
+                    // Gets the binary field corresponding to the events the
+                    // listener must listen to if specified.
+                    // Else, listen to all events.
+                    eventtypes_bitmap_t eventToGet;
+                    eventToGet.set_all_events();
+
+                    if (!parseArgs(args, argCount, eventToGet))
+                    {
+                        NPN_SetException(this, strdup(ERROR_EVENT_NOT_FOUND));
+                        return INVOKERESULT_GENERIC_ERROR;
+                    }
+
+                    NPObject *listener = NPVARIANT_TO_OBJECT(args[0]);
+                    NPN_RetainObject(listener);
+
+                    EventListener *eventListener = new EventListener();
+                    eventListener->listener = listener;
+                    eventListener->id = copyNPVariant(args[1]);
+                    eventListener->eventMap = eventToGet;
+
+                    p_plugin->eventToCatch.add_event(eventToGet);
+
+                    p_plugin->eventListeners.push_back(eventListener);
+
+                    return INVOKERESULT_NO_ERROR;
+                }
+                return INVOKERESULT_NO_SUCH_METHOD;
+          case ID_event_removeListeners:
+              if (argCount == 0)
+              {
+                  VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
+                  p_plugin->eventListeners.clear();
+                  p_plugin->eventToCatch.clear();
+                  return INVOKERESULT_NO_ERROR;
+              }
+              return INVOKERESULT_NO_SUCH_METHOD;
+          default:
+              ;
+        }
+    }
+    return INVOKERESULT_GENERIC_ERROR;
+}
diff --git a/projects/mozilla/control/npolibvlc.h b/projects/mozilla/control/npolibvlc.h
index 2fc3107..53d551d 100644
--- a/projects/mozilla/control/npolibvlc.h
+++ b/projects/mozilla/control/npolibvlc.h
@@ -38,7 +38,8 @@ protected:
     inputObj(NULL),
     playlistObj(NULL),
     subtitleObj(NULL),
-    videoObj(NULL) {};
+    videoObj(NULL),
+    eventObj(NULL) {};
 
     virtual ~LibvlcRootNPObject();
 
@@ -58,6 +59,7 @@ private:
     NPObject *playlistObj;
     NPObject *subtitleObj;
     NPObject *videoObj;
+    NPObject *eventObj;
 };
 
 class LibvlcAudioNPObject: public RuntimeNPObject
@@ -218,3 +220,24 @@ protected:
 
     InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result);
 };
+
+class LibvlcEventNPObject: public RuntimeNPObject
+{
+protected:
+    friend class RuntimeNPClass<LibvlcEventNPObject>;
+
+    LibvlcEventNPObject(NPP instance, const NPClass *aClass) :
+        RuntimeNPObject(instance, aClass) {};
+    virtual ~LibvlcEventNPObject() {};
+
+    static const int propertyCount;
+    static const NPUTF8 * const propertyNames[];
+
+    static const int methodCount;
+    static const NPUTF8 * const methodNames[];
+
+    InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result);
+
+    bool parseArgs(const NPVariant *args, uint32_t argCount,
+                   eventtypes_bitmap_t &eventToGet);
+};
diff --git a/projects/mozilla/support/npunix.c b/projects/mozilla/support/npunix.c
index 41ceff2..52096bc 100644
--- a/projects/mozilla/support/npunix.c
+++ b/projects/mozilla/support/npunix.c
@@ -100,6 +100,16 @@ NPN_Version(int* plugin_major, int* plugin_minor,
     *netscape_minor = gNetscapeFuncs.version & 0xFF;
 }
 
+void
+NPN_PluginThreadAsyncCall(NPP plugin,
+                          void (*func)(void *),
+                          void *userData)
+{
+#if (((NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR) >= 20)
+    return (*gNetscapeFuncs.pluginthreadasynccall)(plugin, func, userData);
+#endif
+}
+
 NPError
 NPN_GetValue(NPP instance, NPNVariable variable, void *r_value)
 {
@@ -846,6 +856,10 @@ NP_Initialize(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs)
         gNetscapeFuncs.memfree       = nsTable->memfree;
         gNetscapeFuncs.memflush      = nsTable->memflush;
         gNetscapeFuncs.reloadplugins = nsTable->reloadplugins;
+#if (((NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR) >= 20)
+        gNetscapeFuncs.pluginthreadasynccall =
+            nsTable->pluginthreadasynccall;
+#endif
 #ifdef OJI
         if( minor >= NPVERS_HAS_LIVECONNECT )
         {
diff --git a/projects/mozilla/vlcplugin.cpp b/projects/mozilla/vlcplugin.cpp
index 34526c0..1c265cd 100644
--- a/projects/mozilla/vlcplugin.cpp
+++ b/projects/mozilla/vlcplugin.cpp
@@ -36,6 +36,7 @@
 #include "control/npolibvlc.h"
 
 #include <ctype.h>
+#include <string>
 
 /*****************************************************************************
  * VlcPlugin constructor and destructor
@@ -86,6 +87,48 @@ static bool boolValue(const char *value) {
              !strcasecmp(value, "yes") );
 }
 
+void eventAsync(void *param)
+{
+    VlcPlugin *plugin = (VlcPlugin*)param;
+    NPVariant result;
+    NPVariant params[2];
+
+    pthread_mutex_lock(&plugin->mutex);
+
+    for (int i = 0; i < plugin->eventList.size(); i++)
+    {
+        for (int j = 0; j < plugin->eventListeners.size(); j++)
+        {
+            libvlc_event_type_t event = plugin->eventList[i];
+
+            if (plugin->eventListeners[j]->eventMap.have_event(event))
+            {
+                STRINGZ_TO_NPVARIANT(libvlc_event_type_name(event), params[0]);
+                params[1] = plugin->eventListeners[j]->id;
+                NPN_InvokeDefault(plugin->getBrowser(), plugin->eventListeners[j]->listener, params, 2, &result);
+                NPN_ReleaseVariantValue(&result);
+            }
+        }
+    }
+    plugin->eventList.clear();
+
+    pthread_mutex_unlock(&plugin->mutex);
+}
+
+void event_callback(const libvlc_event_t* event, void *param)
+{
+    VlcPlugin *plugin = (VlcPlugin*)param;
+
+    pthread_mutex_lock(&plugin->mutex);
+
+    if (plugin->eventToCatch.have_event(event->type))
+        plugin->eventList.push_back(event->type);
+
+    pthread_mutex_unlock(&plugin->mutex);
+
+    NPN_PluginThreadAsyncCall(plugin->getBrowser(), eventAsync, plugin);
+}
+
 NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[])
 {
     /* prepare VLC command line */
@@ -264,6 +307,9 @@ NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[])
     /* new APIs */
     p_scriptClass = RuntimeNPClass<LibvlcRootNPObject>::getClass();
 
+    if (pthread_mutex_init(&mutex, NULL) != 0)
+        return NPERR_GENERIC_ERROR;
+
     return NPERR_NO_ERROR;
 }
 
@@ -279,6 +325,15 @@ VlcPlugin::~VlcPlugin()
         libvlc_media_list_release( libvlc_media_list );
     if( libvlc_instance )
         libvlc_release(libvlc_instance);
+    
+    for (int i = 0; i < eventListeners.size(); i++)
+    {
+        NPN_ReleaseObject(eventListeners[i]->listener);
+        NPN_ReleaseVariantValue(&(eventListeners[i]->id));
+        delete eventListeners[i];
+    }
+
+    pthread_mutex_destroy(&mutex);
 }
 
 /*****************************************************************************
@@ -343,6 +398,7 @@ int VlcPlugin::playlist_add_extended_untrusted( const char *mrl, const char *nam
 bool VlcPlugin::playlist_select( int idx, libvlc_exception_t *ex )
 {
     libvlc_media_t *p_m = NULL;
+    libvlc_event_manager_t *eventManager = NULL;
 
     libvlc_media_list_lock(libvlc_media_list);
 
@@ -368,9 +424,31 @@ bool VlcPlugin::playlist_select( int idx, libvlc_exception_t *ex )
     }
 
     libvlc_media_player = libvlc_media_player_new_from_media(p_m,ex);
+
     if( libvlc_media_player )
+      {
         set_player_window(ex);
 
+        // Registers the events we're interested in.
+        eventManager = libvlc_media_player_event_manager(libvlc_media_player, ex);
+
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerOpening, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerBuffering, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerPlaying, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerStopped, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerPaused, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerEndReached, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerForward, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerBackward, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerEndReached, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerEncounteredError, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerTimeChanged, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerPositionChanged, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerTitleChanged, event_callback, this, ex);
+        libvlc_event_attach(eventManager, libvlc_MediaPlayerSnapshotTaken, event_callback, this, ex);
+
+      }
+
     libvlc_media_release( p_m );
     return !libvlc_exception_raised(ex);
 
@@ -911,3 +989,20 @@ vlc_toolbar_clicked_t VlcPlugin::getToolbarButtonClicked( int i_xpos, int i_ypos
 }
 #undef BTN_SPACE
 #endif
+
+// Verifies the version of the NPAPI.
+// The eventListeners use a NPAPI function available
+// since Gecko 1.9.
+bool VlcPlugin::canUseEventListener()
+{
+    int plugin_major, plugin_minor;
+    int browser_major, browser_minor;
+
+    NPN_Version(&plugin_major, &plugin_minor,
+                &browser_major, &browser_minor);
+
+    if (browser_minor >= 19 || browser_major > 0)
+        return true;
+    return false;
+}
+
diff --git a/projects/mozilla/vlcplugin.h b/projects/mozilla/vlcplugin.h
index 517530e..80c237c 100644
--- a/projects/mozilla/vlcplugin.h
+++ b/projects/mozilla/vlcplugin.h
@@ -31,6 +31,7 @@
 
 #include <vlc/vlc.h>
 #include <npapi.h>
+#include <vector>
 #include "control/nporuntime.h"
 
 #if !defined(XP_MACOSX) && !defined(XP_UNIX) && !defined(XP_WIN)
@@ -79,6 +80,109 @@ typedef enum vlc_toolbar_clicked_e {
     clicked_Unmute
 } vlc_toolbar_clicked_t;
 
+
+// Note that the accessor functions are unsafe, but this is handled in
+// the next layer up. 64bit uints can be substituted to taste (shift=6).
+template<size_t M> class bitmap
+{
+private:
+    typedef uint32_t bitu_t; enum { shift=5 };
+    enum { bmax=M, bpu=1<<shift, mask=bpu-1, units=(bmax+bpu-1)/bpu };
+    bitu_t bits[units];
+public:
+    bool get(size_t idx) const
+    {
+        return bits[idx>>shift]&(1<<(idx&mask));
+    }
+
+    void set(size_t idx)       { bits[idx>>shift]|=  1<<(idx&mask);  }
+    void reset(size_t idx)     { bits[idx>>shift]&=~(1<<(idx&mask)); }
+    void toggle(size_t idx)    { bits[idx>>shift]^=  1<<(idx&mask);  }
+    size_t maxbit() const      { return bmax; }
+    void clear()               { memset(bits,0,sizeof(bits)); }
+    bitmap() { clear(); }
+    ~bitmap() { }
+};
+
+typedef bitmap<libvlc_num_event_types> parent;
+
+class eventtypes_bitmap_t: private bitmap<libvlc_num_event_types> {
+private:
+    typedef libvlc_event_type_t event_t;
+    event_t find_event(const char *s) const
+    {
+        event_t i;
+        for(i=0;i<maxbit();++i)
+            if(!strcmp(s,libvlc_event_type_name(i)))
+                break;
+        return i;
+    }
+public:
+    bool add_event(const eventtypes_bitmap_t &eventBitmap)
+    {
+        event_t i;
+        for(i=0;i<maxbit();++i)
+            if (eventBitmap.have_event(i))
+                set(i);
+    }
+    bool add_event(const char *s)
+    {
+        if (!strcmp(s, "all"))
+        {
+            set_all_events();
+            return true;
+        }
+        if (!strcmp(s, "none"))
+        {
+            clear();
+            return true;
+        }
+
+        event_t event = find_event(s);
+        bool b = event<maxbit();
+        if(b) set(event);
+        return b;
+    }
+    bool del_event(const char *s)
+    {
+        event_t event=find_event(s);
+        bool b=event<maxbit();
+        if(b) reset(event);
+        return b;
+    }
+    bool have_event(libvlc_event_type_t event) const
+    {
+        return event<maxbit()?get(event):false;
+    }
+    void clear()
+    {
+        parent::clear();
+    }
+    void set_all_events()
+    {
+        event_t i;
+        for(i=0;i<maxbit();++i)
+            set(i);
+    }
+};
+
+
+// Structure used to represent an EventListener.
+// It contains the listener object that will be invoked,
+// An Id given by the addEventListener function and sent
+// when invoking the listener. Can be anything or nothing.
+// The profile associated with the listener used to invoke
+// the listener only to some events.
+typedef struct s_EventListener
+{
+    NPObject *listener;
+    NPVariant id;
+    eventtypes_bitmap_t eventMap;
+    
+} EventListener;
+
+void event_callback(const libvlc_event_t* event, void *param);
+
 class VlcPlugin
 {
 public:
@@ -197,6 +301,15 @@ public:
 
     bool  player_has_vout( libvlc_exception_t * );
 
+
+    // Events related members
+    std::vector<EventListener*> eventListeners; // List of registered listerners.
+    std::vector<libvlc_event_type_t> eventList; // List of event sent by VLC that must be returned to JS.
+    eventtypes_bitmap_t eventToCatch;
+    pthread_mutex_t mutex;
+
+    static bool canUseEventListener();
+
 private:
     bool playlist_select(int,libvlc_exception_t *);
     void set_player_window( libvlc_exception_t * );
-- 
1.5.6.3



More information about the vlc-devel mailing list