]> git.sesse.net Git - vlc/blobdiff - projects/mozilla/control/npolibvlc.cpp
Mozilla plugin event listeners.
[vlc] / projects / mozilla / control / npolibvlc.cpp
index 31e0e1e876a1b5aaea1f462eb6c58d6ed57456cd..976d7733e50aea8021596d0ec42c58185971232c 100644 (file)
@@ -2,9 +2,10 @@
  * npolibvlc.cpp: official Javascript APIs
  *****************************************************************************
  * Copyright (C) 2002-2009 the VideoLAN team
+ * Copyright (C) 2010 M2X BV
  *
  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
- *          JP Dinger <jpd@m2x.nl>
+ *          JP Dinger <jpd@videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,9 +17,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #include "config.h"
@@ -35,6 +36,8 @@
 #include "vlcplugin.h"
 #include "npolibvlc.h"
 
+#include "position.h"
+
 /*
 ** Local helper macros and function
 */
 #define RETURN_ON_EXCEPTION(this,ex) \
     do { if( libvlc_exception_raised(&ex) ) \
     { \
-        NPN_SetException(this, libvlc_exception_get_message(&ex)); \
+        NPN_SetException(this, libvlc_errmsg()); \
         libvlc_exception_clear(&ex); \
         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 +145,7 @@ const NPUTF8 * const LibvlcRootNPObject::propertyNames[] =
     "playlist",
     "subtitle",
     "video",
+    "events",
     "VersionInfo",
 };
 COUNTNAMES(LibvlcRootNPObject,propertyCount,propertyNames);
@@ -88,6 +157,7 @@ enum LibvlcRootNPObjectPropertyIds
     ID_root_playlist,
     ID_root_subtitle,
     ID_root_video,
+    ID_root_events,
     ID_root_VersionInfo,
 };
 
@@ -100,44 +170,32 @@ LibvlcRootNPObject::getProperty(int index, NPVariant &result)
         switch( index )
         {
             case ID_root_audio:
-                // create child object in lazyman fashion to avoid
-                // ownership problem with firefox
-                if( ! audioObj )
-                    audioObj = NPN_CreateObject(_instance,
-                             RuntimeNPClass<LibvlcAudioNPObject>::getClass());
+                InstantObj<LibvlcAudioNPObject>( audioObj );
                 OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result);
                 return INVOKERESULT_NO_ERROR;
             case ID_root_input:
-                // create child object in lazyman fashion to avoid
-                // ownership problem with firefox
-                if( ! inputObj )
-                    inputObj = NPN_CreateObject(_instance,
-                             RuntimeNPClass<LibvlcInputNPObject>::getClass());
+                InstantObj<LibvlcInputNPObject>( inputObj );
                 OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), result);
                 return INVOKERESULT_NO_ERROR;
             case ID_root_playlist:
-                // create child object in lazyman fashion to avoid
-                // ownership problem with firefox
-                if( ! playlistObj )
-                    playlistObj = NPN_CreateObject(_instance,
-                          RuntimeNPClass<LibvlcPlaylistNPObject>::getClass());
+                InstantObj<LibvlcPlaylistNPObject>( playlistObj );
                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), result);
                 return INVOKERESULT_NO_ERROR;
             case ID_root_subtitle:
-                // create child object in lazyman fashion to avoid
-                // ownership problem with firefox
-                if( ! subtitleObj )
-                    subtitleObj = NPN_CreateObject(_instance,
-                             RuntimeNPClass<LibvlcSubtitleNPObject>::getClass());
+                InstantObj<LibvlcSubtitleNPObject>( subtitleObj );
                 OBJECT_TO_NPVARIANT(NPN_RetainObject(subtitleObj), result);
                 return INVOKERESULT_NO_ERROR;
             case ID_root_video:
+                InstantObj<LibvlcVideoNPObject>( videoObj );
+                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( ! videoObj )
-                    videoObj = NPN_CreateObject(_instance,
-                             RuntimeNPClass<LibvlcVideoNPObject>::getClass());
-                OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result);
+                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);
@@ -218,15 +276,13 @@ LibvlcAudioNPObject::getProperty(int index, NPVariant &result)
         {
             case ID_audio_mute:
             {
-                bool muted = libvlc_audio_get_mute(p_plugin->getVLC(), &ex);
-                RETURN_ON_EXCEPTION(this,ex);
+                bool muted = libvlc_audio_get_mute(p_plugin->getVLC());
                 BOOLEAN_TO_NPVARIANT(muted, result);
                 return INVOKERESULT_NO_ERROR;
             }
             case ID_audio_volume:
             {
-                int volume = libvlc_audio_get_volume(p_plugin->getVLC(), &ex);
-                RETURN_ON_EXCEPTION(this,ex);
+                int volume = libvlc_audio_get_volume(p_plugin->getVLC());
                 INT32_TO_NPVARIANT(volume, result);
                 return INVOKERESULT_NO_ERROR;
             }
@@ -280,8 +336,7 @@ LibvlcAudioNPObject::setProperty(int index, const NPVariant &value)
                 if( NPVARIANT_IS_BOOLEAN(value) )
                 {
                     libvlc_audio_set_mute(p_plugin->getVLC(),
-                                          NPVARIANT_TO_BOOLEAN(value), &ex);
-                    RETURN_ON_EXCEPTION(this,ex);
+                                          NPVARIANT_TO_BOOLEAN(value));
                     return INVOKERESULT_NO_ERROR;
                 }
                 return INVOKERESULT_INVALID_VALUE;
@@ -349,8 +404,7 @@ LibvlcAudioNPObject::invoke(int index, const NPVariant *args,
             case ID_audio_togglemute:
                 if( argCount == 0 )
                 {
-                    libvlc_audio_toggle_mute(p_plugin->getVLC(), &ex);
-                    RETURN_ON_EXCEPTION(this,ex);
+                    libvlc_audio_toggle_mute(p_plugin->getVLC());
                     VOID_TO_NPVARIANT(result);
                     return INVOKERESULT_NO_ERROR;
                 }
@@ -448,7 +502,7 @@ LibvlcInputNPObject::getProperty(int index, NPVariant &result)
         {
             if( index != ID_input_state )
             {
-                NPN_SetException(this, libvlc_exception_get_message(&ex));
+                NPN_SetException(this, libvlc_errmsg());
                 libvlc_exception_clear(&ex);
                 return INVOKERESULT_GENERIC_ERROR;
             }
@@ -486,7 +540,7 @@ LibvlcInputNPObject::getProperty(int index, NPVariant &result)
             }
             case ID_input_state:
             {
-                int val = libvlc_media_player_get_state(p_md, &ex);
+                int val = libvlc_media_player_get_state(p_md);
                 RETURN_ON_EXCEPTION(this,ex);
                 INT32_TO_NPVARIANT(val, result);
                 return INVOKERESULT_NO_ERROR;
@@ -588,10 +642,33 @@ LibvlcInputNPObject::setProperty(int index, const NPVariant &value)
 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =
 {
     /* no methods */
+    "none",
 };
-
 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
 
+enum LibvlcInputNPObjectMethodIds
+{
+    ID_none,
+};
+
+RuntimeNPObject::InvokeResult
+LibvlcInputNPObject::invoke(int index, const NPVariant *args,
+                                    uint32_t argCount, NPVariant &result)
+{
+    /* is plugin still running */
+    if( isPluginRunning() )
+    {
+        switch( index )
+        {
+            case ID_none:
+                return INVOKERESULT_NO_SUCH_METHOD;
+            default:
+                ;
+        }
+    }
+    return INVOKERESULT_GENERIC_ERROR;
+}
+
 /*
 ** implementation of libvlc playlist items object
 */
@@ -614,15 +691,12 @@ LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
     if( isPluginRunning() )
     {
         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
-        libvlc_exception_t ex;
-        libvlc_exception_init(&ex);
 
         switch( index )
         {
             case ID_playlistitems_count:
             {
-                int val = p_plugin->playlist_count(&ex);
-                RETURN_ON_EXCEPTION(this,ex);
+                int val = p_plugin->playlist_count();
                 INT32_TO_NPVARIANT(val, result);
                 return INVOKERESULT_NO_ERROR;
             }
@@ -717,33 +791,24 @@ LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
     if( isPluginRunning() )
     {
         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
-        libvlc_exception_t ex;
-        libvlc_exception_init(&ex);
 
         switch( index )
         {
             case ID_playlist_itemcount: /* deprecated */
             {
-                int val = p_plugin->playlist_count(&ex);
-                RETURN_ON_EXCEPTION(this,ex);
+                int val = p_plugin->playlist_count();
                 INT32_TO_NPVARIANT(val, result);
                 return INVOKERESULT_NO_ERROR;
             }
             case ID_playlist_isplaying:
             {
-                int val = p_plugin->playlist_isplaying(&ex);
-                RETURN_ON_EXCEPTION(this,ex);
+                int val = p_plugin->playlist_isplaying();
                 BOOLEAN_TO_NPVARIANT(val, result);
                 return INVOKERESULT_NO_ERROR;
             }
             case ID_playlist_items:
             {
-                // create child object in lazyman fashion to avoid
-                // ownership problem with firefox
-                if( ! playlistItemsObj )
-                    playlistItemsObj =
-                        NPN_CreateObject(_instance, RuntimeNPClass<
-                        LibvlcPlaylistItemsNPObject>::getClass());
+                InstantObj<LibvlcPlaylistItemsNPObject>( playlistItemsObj );
                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
                 return INVOKERESULT_NO_ERROR;
             }
@@ -803,6 +868,9 @@ LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
                     return INVOKERESULT_NO_SUCH_METHOD;
 
                 // grab URL
+                if( NPVARIANT_IS_NULL(args[0]) )
+                    return INVOKERESULT_NO_SUCH_METHOD;
+
                 char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
                 if( !s )
                     return INVOKERESULT_OUT_OF_MEMORY;
@@ -907,8 +975,7 @@ LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
             case ID_playlist_stop:
                 if( argCount == 0 )
                 {
-                    p_plugin->playlist_stop(&ex);
-                    RETURN_ON_EXCEPTION(this,ex);
+                    p_plugin->playlist_stop();
                     VOID_TO_NPVARIANT(result);
                     return INVOKERESULT_NO_ERROR;
                 }
@@ -1008,7 +1075,7 @@ void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
                             if( ! moreOptions )
                             {
                                 /* failed to allocate more memory */
-                               free(s);
+                                free(s);
                                 /* return what we got so far */
                                 *i_options = nOptions;
                                 *ppsz_options = options;
@@ -1085,6 +1152,7 @@ void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
                     }
 
                     options[nOptions++] = stringValue(value);
+                    NPN_ReleaseVariantValue(&value);
                 }
                 *i_options = nOptions;
                 *ppsz_options = options;
@@ -1259,6 +1327,16 @@ LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
 ** implementation of libvlc video object
 */
 
+LibvlcVideoNPObject::~LibvlcVideoNPObject()
+{
+    if( isValid() )
+    {
+        if( marqueeObj ) NPN_ReleaseObject(marqueeObj);
+        if( logoObj    ) NPN_ReleaseObject(logoObj);
+        if( deintObj   ) NPN_ReleaseObject(deintObj);
+    }
+}
+
 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
 {
     "fullscreen",
@@ -1267,7 +1345,10 @@ const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
     "aspectRatio",
     "subtitle",
     "crop",
-    "teletext"
+    "teletext",
+    "marquee",
+    "logo",
+    "deinterlace",
 };
 
 enum LibvlcVideoNPObjectPropertyIds
@@ -1278,7 +1359,10 @@ enum LibvlcVideoNPObjectPropertyIds
     ID_video_aspectratio,
     ID_video_subtitle,
     ID_video_crop,
-    ID_video_teletext
+    ID_video_teletext,
+    ID_video_marquee,
+    ID_video_logo,
+    ID_video_deinterlace,
 };
 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
 
@@ -1347,10 +1431,30 @@ LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
             }
             case ID_video_teletext:
             {
-                int i_page = libvlc_video_get_teletext(p_md, &ex);
+/*                int i_page = libvlc_video_get_teletext(p_md, &ex);
                 RETURN_ON_EXCEPTION(this,ex);
                 INT32_TO_NPVARIANT(i_page, result);
                 return INVOKERESULT_NO_ERROR;
+*/
+                return INVOKERESULT_NO_SUCH_METHOD;
+            }
+            case ID_video_marquee:
+            {
+                InstantObj<LibvlcMarqueeNPObject>( marqueeObj );
+                OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
+                return INVOKERESULT_NO_ERROR;
+            }
+            case ID_video_logo:
+            {
+                InstantObj<LibvlcLogoNPObject>( logoObj );
+                OBJECT_TO_NPVARIANT(NPN_RetainObject(logoObj), result);
+                return INVOKERESULT_NO_ERROR;
+            }
+            case ID_video_deinterlace:
+            {
+                InstantObj<LibvlcDeinterlaceNPObject>( deintObj );
+                OBJECT_TO_NPVARIANT(NPN_RetainObject(deintObj), result);
+                return INVOKERESULT_NO_ERROR;
             }
         }
     }
@@ -1441,10 +1545,13 @@ LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
             {
                 if( isNumberValue(value) )
                 {
+/*
                     libvlc_video_set_teletext(p_md, numberValue(value), &ex);
                     RETURN_ON_EXCEPTION(this,ex);
 
                     return INVOKERESULT_NO_ERROR;
+*/
+                    return INVOKERESULT_NO_SUCH_METHOD;
                 }
                 return INVOKERESULT_INVALID_VALUE;
             }
@@ -1456,14 +1563,14 @@ LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
 {
     "toggleFullscreen",
-    "toggleTeletext"
+    "toggleTeletext",
 };
 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
 
 enum LibvlcVideoNPObjectMethodIds
 {
     ID_video_togglefullscreen,
-    ID_video_toggleteletext
+    ID_video_toggleteletext,
 };
 
 RuntimeNPObject::InvokeResult
@@ -1483,6 +1590,7 @@ LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
         switch( index )
         {
             case ID_video_togglefullscreen:
+            {
                 if( argCount == 0 )
                 {
                     p_plugin->toggle_fullscreen(&ex);
@@ -1491,7 +1599,9 @@ LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
                     return INVOKERESULT_NO_ERROR;
                 }
                 return INVOKERESULT_NO_SUCH_METHOD;
+            }
             case ID_video_toggleteletext:
+            {
                 if( argCount == 0 )
                 {
                     libvlc_toggle_teletext(p_md, &ex);
@@ -1500,9 +1610,576 @@ LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
                     return INVOKERESULT_NO_ERROR;
                 }
                 return INVOKERESULT_NO_SUCH_METHOD;
+            }
             default:
                 return INVOKERESULT_NO_SUCH_METHOD;
         }
     }
     return INVOKERESULT_GENERIC_ERROR;
 }
+
+/*
+** implementation of libvlc marquee object
+*/
+
+const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
+{
+    "color",
+    "opacity",
+    "position",
+    "refresh",
+    "size",
+    "text",
+    "timeout",
+    "x",
+    "y",
+};
+
+enum LibvlcMarqueeNPObjectPropertyIds
+{
+    ID_marquee_color,
+    ID_marquee_opacity,
+    ID_marquee_position,
+    ID_marquee_refresh,
+    ID_marquee_size,
+    ID_marquee_text,
+    ID_marquee_timeout,
+    ID_marquee_x,
+    ID_marquee_y,
+};
+
+COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
+
+static const unsigned char marquee_idx[] = {
+    libvlc_marquee_Color,
+    libvlc_marquee_Opacity,
+    libvlc_marquee_Position,
+    libvlc_marquee_Refresh,
+    libvlc_marquee_Size,
+    0,
+    libvlc_marquee_Timeout,
+    libvlc_marquee_X,
+    libvlc_marquee_Y,
+};
+
+RuntimeNPObject::InvokeResult
+LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
+{
+    char *psz;
+
+    if( !isPluginRunning() )
+        return INVOKERESULT_GENERIC_ERROR;
+
+    VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+
+    libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
+    RETURN_ON_EXCEPTION(this,ex);
+
+    switch( index )
+    {
+    case ID_marquee_color:
+    case ID_marquee_opacity:
+    case ID_marquee_refresh:
+    case ID_marquee_timeout:
+    case ID_marquee_size:
+    case ID_marquee_x:
+    case ID_marquee_y:
+        INT32_TO_NPVARIANT(
+            libvlc_video_get_marquee_int(p_md, marquee_idx[index], &ex),
+            result );
+        RETURN_ON_EXCEPTION(this,ex);
+        return INVOKERESULT_NO_ERROR;
+
+    case ID_marquee_position:
+        STRINGZ_TO_NPVARIANT( position_bynumber(
+            libvlc_video_get_marquee_int(p_md, libvlc_marquee_Position, &ex) ),
+            result );
+
+        RETURN_ON_EXCEPTION(this,ex);
+        break;
+
+    case ID_marquee_text:
+        psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text, &ex);
+        if( psz )
+        {
+            STRINGZ_TO_NPVARIANT(psz, result);
+            return INVOKERESULT_NO_ERROR;
+        }
+        break;
+    }
+    return INVOKERESULT_GENERIC_ERROR;
+}
+
+RuntimeNPObject::InvokeResult
+LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
+{
+    size_t i;
+
+    if( !isPluginRunning() )
+        return INVOKERESULT_GENERIC_ERROR;
+
+    VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+    libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
+    RETURN_ON_EXCEPTION(this,ex);
+
+    switch( index )
+    {
+    case ID_marquee_color:
+    case ID_marquee_opacity:
+    case ID_marquee_refresh:
+    case ID_marquee_timeout:
+    case ID_marquee_x:
+    case ID_marquee_y:
+        if( NPVARIANT_IS_INT32( value ) )
+        {
+            libvlc_video_set_marquee_int(p_md, marquee_idx[index],
+                                         NPVARIANT_TO_INT32( value ), &ex);
+            RETURN_ON_EXCEPTION(this,ex);
+            return INVOKERESULT_NO_ERROR;
+        }
+        break;
+
+    case ID_marquee_position:
+        if( !NPVARIANT_IS_STRING(value) ||
+            !position_byname( NPVARIANT_TO_STRING(value).utf8characters, i ) )
+            return INVOKERESULT_INVALID_VALUE;
+
+        libvlc_video_set_marquee_int(p_md, libvlc_marquee_Position, i, &ex);
+        RETURN_ON_EXCEPTION(this,ex);
+        return INVOKERESULT_NO_ERROR;
+
+    case ID_marquee_text:
+        if( NPVARIANT_IS_STRING( value ) )
+        {
+            char *psz_text = stringValue( NPVARIANT_TO_STRING( value ) );
+            libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
+                                            psz_text, &ex);
+            free(psz_text);
+            RETURN_ON_EXCEPTION(this,ex);
+            return INVOKERESULT_NO_ERROR;
+        }
+        break;
+    }
+    return INVOKERESULT_NO_SUCH_METHOD;
+}
+
+const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
+{
+    "enable",
+    "disable",
+};
+COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
+
+enum LibvlcMarqueeNPObjectMethodIds
+{
+    ID_marquee_enable,
+    ID_marquee_disable,
+};
+
+RuntimeNPObject::InvokeResult
+LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
+                            uint32_t argCount, NPVariant &result)
+{
+    if( !isPluginRunning() )
+        return INVOKERESULT_GENERIC_ERROR;
+
+    VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+
+    libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
+    RETURN_ON_EXCEPTION(this,ex);
+
+    switch( index )
+    {
+    case ID_marquee_enable:
+    case ID_marquee_disable:
+        libvlc_video_set_marquee_int(p_md, libvlc_marquee_Enable,
+                                     index!=ID_marquee_disable, &ex);
+        RETURN_ON_EXCEPTION(this,ex);
+        VOID_TO_NPVARIANT(result);
+        return INVOKERESULT_NO_ERROR;
+    }
+    return INVOKERESULT_NO_SUCH_METHOD;
+}
+
+const NPUTF8 * const LibvlcLogoNPObject::propertyNames[] = {
+    "delay",
+    "repeat",
+    "opacity",
+    "position",
+    "x",
+    "y",
+};
+enum LibvlcLogoNPObjectPropertyIds {
+    ID_logo_delay,
+    ID_logo_repeat,
+    ID_logo_opacity,
+    ID_logo_position,
+    ID_logo_x,
+    ID_logo_y,
+};
+COUNTNAMES(LibvlcLogoNPObject,propertyCount,propertyNames);
+static const unsigned char logo_idx[] = {
+    libvlc_logo_delay,
+    libvlc_logo_repeat,
+    libvlc_logo_opacity,
+    0,
+    libvlc_logo_x,
+    libvlc_logo_y,
+};
+
+RuntimeNPObject::InvokeResult
+LibvlcLogoNPObject::getProperty(int index, NPVariant &result)
+{
+    if( !isPluginRunning() )
+        return INVOKERESULT_GENERIC_ERROR;
+
+    VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+    libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
+    RETURN_ON_EXCEPTION(this,ex);
+
+    switch( index )
+    {
+    case ID_logo_delay:
+    case ID_logo_repeat:
+    case ID_logo_opacity:
+    case ID_logo_x:
+    case ID_logo_y:
+
+        INT32_TO_NPVARIANT(
+            libvlc_video_get_logo_int(p_md, logo_idx[index], &ex), result);
+
+        RETURN_ON_EXCEPTION(this,ex);
+        break;
+
+    case ID_logo_position:
+        STRINGZ_TO_NPVARIANT( position_bynumber(
+            libvlc_video_get_logo_int(p_md, libvlc_logo_position, &ex) ),
+            result );
+
+        RETURN_ON_EXCEPTION(this,ex);
+        break;
+    default:
+        return INVOKERESULT_GENERIC_ERROR;
+    }
+    return INVOKERESULT_NO_ERROR;
+}
+
+RuntimeNPObject::InvokeResult
+LibvlcLogoNPObject::setProperty(int index, const NPVariant &value)
+{
+    size_t i;
+
+    if( !isPluginRunning() )
+        return INVOKERESULT_GENERIC_ERROR;
+
+    VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+
+    libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
+    RETURN_ON_EXCEPTION(this,ex);
+
+    switch( index )
+    {
+    case ID_logo_delay:
+    case ID_logo_repeat:
+    case ID_logo_opacity:
+    case ID_logo_x:
+    case ID_logo_y:
+        if( !NPVARIANT_IS_INT32(value) )
+            return INVOKERESULT_INVALID_VALUE;
+
+        libvlc_video_set_logo_int(p_md, logo_idx[index],
+                                  NPVARIANT_TO_INT32( value ), &ex);
+
+        RETURN_ON_EXCEPTION(this,ex);
+        break;
+
+    case ID_logo_position:
+        if( !NPVARIANT_IS_STRING(value) ||
+            !position_byname( NPVARIANT_TO_STRING(value).utf8characters, i ) )
+            return INVOKERESULT_INVALID_VALUE;
+
+        libvlc_video_set_logo_int(p_md, libvlc_logo_position, i, &ex);
+
+        RETURN_ON_EXCEPTION(this,ex);
+        break;
+    default:
+        return INVOKERESULT_GENERIC_ERROR;
+    }
+    return INVOKERESULT_NO_ERROR;
+}
+
+
+const NPUTF8 * const LibvlcLogoNPObject::methodNames[] = {
+    "enable",
+    "disable",
+    "file",
+};
+enum LibvlcLogoNPObjectMethodIds {
+    ID_logo_enable,
+    ID_logo_disable,
+    ID_logo_file,
+};
+COUNTNAMES(LibvlcLogoNPObject,methodCount,methodNames);
+
+RuntimeNPObject::InvokeResult
+LibvlcLogoNPObject::invoke(int index, const NPVariant *args,
+                           uint32_t argCount, NPVariant &result)
+{
+    char *buf, *h;
+    size_t i, len;
+
+    if( !isPluginRunning() )
+        return INVOKERESULT_GENERIC_ERROR;
+
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+    libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD(&ex);
+    RETURN_ON_EXCEPTION(this,ex);
+
+    switch( index )
+    {
+    case ID_logo_enable:
+    case ID_logo_disable:
+        if( argCount != 0 )
+            return INVOKERESULT_GENERIC_ERROR;
+
+        libvlc_video_set_logo_int(p_md, libvlc_logo_enable,
+                                  index != ID_logo_disable, &ex);
+        RETURN_ON_EXCEPTION(this,ex);
+        VOID_TO_NPVARIANT(result);
+        break;
+
+    case ID_logo_file:
+        if( argCount == 0 )
+            return INVOKERESULT_GENERIC_ERROR;
+
+        for( len=0,i=0;i<argCount;++i )
+        {
+            if( !NPVARIANT_IS_STRING(args[i]) )
+                return INVOKERESULT_INVALID_VALUE;
+            len+=NPVARIANT_TO_STRING(args[i]).utf8length+1;
+        }
+
+        buf = (char *)malloc( len+1 );
+        if( !buf )
+            return INVOKERESULT_OUT_OF_MEMORY;
+
+        for( h=buf,i=0;i<argCount;++i )
+        {
+            if(i) *h++=';';
+            len=NPVARIANT_TO_STRING(args[i]).utf8length;
+            memcpy(h,NPVARIANT_TO_STRING(args[i]).utf8characters,len);
+            h+=len;
+        }
+        *h='\0';
+
+        libvlc_video_set_logo_string(p_md, libvlc_logo_file, buf, &ex);
+        free( buf );
+        RETURN_ON_EXCEPTION(this,ex);
+        VOID_TO_NPVARIANT(result);
+        break;
+    default:
+        return INVOKERESULT_NO_SUCH_METHOD;
+    }
+    return INVOKERESULT_NO_ERROR;
+}
+
+
+const NPUTF8 * const LibvlcDeinterlaceNPObject::propertyNames[] = {
+};
+enum LibvlcDeinterlaceNPObjectPropertyIds {
+};
+COUNTNAMES(LibvlcDeinterlaceNPObject,propertyCount,propertyNames);
+
+RuntimeNPObject::InvokeResult
+LibvlcDeinterlaceNPObject::getProperty(int index, NPVariant &result)
+{
+    return INVOKERESULT_GENERIC_ERROR;
+}
+
+RuntimeNPObject::InvokeResult
+LibvlcDeinterlaceNPObject::setProperty(int index, const NPVariant &value)
+{
+    return INVOKERESULT_GENERIC_ERROR;
+}
+
+
+const NPUTF8 * const LibvlcDeinterlaceNPObject::methodNames[] = {
+    "enable",
+    "disable",
+};
+enum LibvlcDeinterlaceNPObjectMethodIds {
+    ID_deint_enable,
+    ID_deint_disable,
+};
+COUNTNAMES(LibvlcDeinterlaceNPObject,methodCount,methodNames);
+
+RuntimeNPObject::InvokeResult
+LibvlcDeinterlaceNPObject::invoke(int index, const NPVariant *args,
+                           uint32_t argCount, NPVariant &result)
+{
+    char *psz;
+
+    if( !isPluginRunning() )
+        return INVOKERESULT_GENERIC_ERROR;
+
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+    libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD(&ex);
+    RETURN_ON_EXCEPTION(this,ex);
+
+    switch( index )
+    {
+    case ID_deint_disable:
+        libvlc_video_set_deinterlace(p_md, 0, "", &ex);
+        RETURN_ON_EXCEPTION(this,ex);
+        break;
+
+    case ID_deint_enable:
+        if( argCount != 1 || !NPVARIANT_IS_STRING( args[0] ) )
+            return INVOKERESULT_INVALID_VALUE;
+
+        psz = stringValue( NPVARIANT_TO_STRING( args[0] ) );
+        libvlc_video_set_deinterlace(p_md, 1, psz, &ex);
+        free(psz);
+        RETURN_ON_EXCEPTION(this,ex);
+        break;
+
+    default:
+        return INVOKERESULT_NO_SUCH_METHOD;
+    }
+    return INVOKERESULT_NO_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;
+}