]> git.sesse.net Git - vlc/blob - projects/mozilla/control/npolibvlc.cpp
Mozilla plugin event listeners.
[vlc] / projects / mozilla / control / npolibvlc.cpp
1 /*****************************************************************************
2  * npolibvlc.cpp: official Javascript APIs
3  *****************************************************************************
4  * Copyright (C) 2002-2009 the VideoLAN team
5  * Copyright (C) 2010 M2X BV
6  *
7  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
8  *          JP Dinger <jpd@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 /* Mozilla stuff */
32 #ifdef HAVE_MOZILLA_CONFIG_H
33 #   include <mozilla-config.h>
34 #endif
35
36 #include "vlcplugin.h"
37 #include "npolibvlc.h"
38
39 #include "position.h"
40
41 /*
42 ** Local helper macros and function
43 */
44 #define COUNTNAMES(a,b,c) const int a::b = sizeof(a::c)/sizeof(NPUTF8 *)
45 #define RETURN_ON_EXCEPTION(this,ex) \
46     do { if( libvlc_exception_raised(&ex) ) \
47     { \
48         NPN_SetException(this, libvlc_errmsg()); \
49         libvlc_exception_clear(&ex); \
50         return INVOKERESULT_GENERIC_ERROR; \
51     } } while(false)
52
53 #define ERROR_EVENT_NOT_FOUND "ERROR: One or more events could not be found."
54 #define ERROR_API_VERSION "ERROR: NPAPI version not high enough. (Gecko >= 1.9 needed)"
55
56 // Make a copy of an NPVariant.
57 NPVariant copyNPVariant(const NPVariant& original)
58 {
59     NPVariant res;
60
61     if (NPVARIANT_IS_STRING(original))
62         STRINGZ_TO_NPVARIANT(strdup(NPVARIANT_TO_STRING(original).utf8characters), res);
63     else if (NPVARIANT_IS_INT32(original))
64         INT32_TO_NPVARIANT(NPVARIANT_TO_INT32(original), res);
65     else if (NPVARIANT_IS_DOUBLE(original))
66         DOUBLE_TO_NPVARIANT(NPVARIANT_TO_DOUBLE(original), res);
67     else if (NPVARIANT_IS_OBJECT(original))
68     {
69         NPObject *obj = NPVARIANT_TO_OBJECT(original);
70         NPN_RetainObject(obj);
71         OBJECT_TO_NPVARIANT(obj, res);
72     }
73     else if (NPVARIANT_IS_BOOLEAN(original))
74         BOOLEAN_TO_NPVARIANT(NPVARIANT_TO_BOOLEAN(original), res);
75
76     return res;
77 }
78
79 // Parse an event Array given as a NPObject by JS.
80 // This function is similar to LibvlcPlaylistNPObject::parseOptions,
81 // but we don't use it because it's not clearly accessible and the FIXME flags
82 // implie that it might be modified.
83 bool parseEventArray(NPObject *obj, eventtypes_bitmap_t &eventToGet, NPP instance)
84 {
85     NPIdentifier propId = NPN_GetStringIdentifier("length");
86     NPVariant value;
87
88     if (!NPN_GetProperty(instance, obj, propId, &value))
89         return false;
90
91     int count = NPVARIANT_TO_INT32(value);
92     NPN_ReleaseVariantValue(&value);
93     if (count == 0)
94         return false;
95
96     int nOptions = 0;
97     while (nOptions < count)
98     {
99         propId = NPN_GetIntIdentifier(nOptions);
100         // if there is no other string in the array.
101         if( ! NPN_GetProperty(instance, obj, propId, &value) )
102             break;
103
104         // if the element is not a string.
105         if( ! NPVARIANT_IS_STRING(value) )
106         {
107             NPN_ReleaseVariantValue(&value);
108             break;
109         }
110
111         if (!eventToGet.add_event(NPVARIANT_TO_STRING(value).utf8characters))
112             return false;
113         nOptions++;
114     }
115     return true;
116 }
117
118 /*
119 ** implementation of libvlc root object
120 */
121
122 LibvlcRootNPObject::~LibvlcRootNPObject()
123 {
124     /*
125     ** When the plugin is destroyed, firefox takes it upon itself to
126     ** destroy all 'live' script objects and ignores refcounting.
127     ** Therefore we cannot safely assume that refcounting will control
128     ** lifespan of objects. Hence they are only lazily created on
129     ** request, so that firefox can take ownership, and are not released
130     ** when the plugin is destroyed.
131     */
132     if( isValid() )
133     {
134         if( audioObj    ) NPN_ReleaseObject(audioObj);
135         if( inputObj    ) NPN_ReleaseObject(inputObj);
136         if( playlistObj ) NPN_ReleaseObject(playlistObj);
137         if( videoObj    ) NPN_ReleaseObject(videoObj);
138     }
139 }
140
141 const NPUTF8 * const LibvlcRootNPObject::propertyNames[] =
142 {
143     "audio",
144     "input",
145     "playlist",
146     "subtitle",
147     "video",
148     "events",
149     "VersionInfo",
150 };
151 COUNTNAMES(LibvlcRootNPObject,propertyCount,propertyNames);
152
153 enum LibvlcRootNPObjectPropertyIds
154 {
155     ID_root_audio = 0,
156     ID_root_input,
157     ID_root_playlist,
158     ID_root_subtitle,
159     ID_root_video,
160     ID_root_events,
161     ID_root_VersionInfo,
162 };
163
164 RuntimeNPObject::InvokeResult
165 LibvlcRootNPObject::getProperty(int index, NPVariant &result)
166 {
167     /* is plugin still running */
168     if( isPluginRunning() )
169     {
170         switch( index )
171         {
172             case ID_root_audio:
173                 InstantObj<LibvlcAudioNPObject>( audioObj );
174                 OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result);
175                 return INVOKERESULT_NO_ERROR;
176             case ID_root_input:
177                 InstantObj<LibvlcInputNPObject>( inputObj );
178                 OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), result);
179                 return INVOKERESULT_NO_ERROR;
180             case ID_root_playlist:
181                 InstantObj<LibvlcPlaylistNPObject>( playlistObj );
182                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), result);
183                 return INVOKERESULT_NO_ERROR;
184             case ID_root_subtitle:
185                 InstantObj<LibvlcSubtitleNPObject>( subtitleObj );
186                 OBJECT_TO_NPVARIANT(NPN_RetainObject(subtitleObj), result);
187                 return INVOKERESULT_NO_ERROR;
188             case ID_root_video:
189                 InstantObj<LibvlcVideoNPObject>( videoObj );
190                 OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result);
191                 return INVOKERESULT_NO_ERROR;
192             case ID_root_events:
193                 // create child object in lazyman fashion to avoid
194                 // ownership problem with firefox
195                 if( ! eventObj )
196                     eventObj = NPN_CreateObject(_instance,
197                              RuntimeNPClass<LibvlcEventNPObject>::getClass());
198                 OBJECT_TO_NPVARIANT(NPN_RetainObject(eventObj), result);
199                 return INVOKERESULT_NO_ERROR;
200             case ID_root_VersionInfo:
201                 return invokeResultString(libvlc_get_version(),result);
202             default:
203                 ;
204         }
205     }
206     return INVOKERESULT_GENERIC_ERROR;
207 }
208
209 const NPUTF8 * const LibvlcRootNPObject::methodNames[] =
210 {
211     "versionInfo",
212 };
213 COUNTNAMES(LibvlcRootNPObject,methodCount,methodNames);
214
215 enum LibvlcRootNPObjectMethodIds
216 {
217     ID_root_versionInfo,
218 };
219
220 RuntimeNPObject::InvokeResult LibvlcRootNPObject::invoke(int index,
221                   const NPVariant *args, uint32_t argCount, NPVariant &result)
222 {
223     /* is plugin still running */
224     if( isPluginRunning() )
225     {
226         libvlc_exception_t ex;
227         libvlc_exception_init(&ex);
228
229         switch( index )
230         {
231             case ID_root_versionInfo:
232                 if( 0 != argCount )
233                     return INVOKERESULT_NO_SUCH_METHOD;
234                 return invokeResultString(libvlc_get_version(),result);
235             default:
236                 ;
237         }
238     }
239     return INVOKERESULT_GENERIC_ERROR;
240 }
241
242 /*
243 ** implementation of libvlc audio object
244 */
245
246 const NPUTF8 * const LibvlcAudioNPObject::propertyNames[] =
247 {
248     "mute",
249     "volume",
250     "track",
251     "count",
252     "channel",
253 };
254 COUNTNAMES(LibvlcAudioNPObject,propertyCount,propertyNames);
255
256 enum LibvlcAudioNPObjectPropertyIds
257 {
258     ID_audio_mute,
259     ID_audio_volume,
260     ID_audio_track,
261     ID_audio_count,
262     ID_audio_channel,
263 };
264
265 RuntimeNPObject::InvokeResult
266 LibvlcAudioNPObject::getProperty(int index, NPVariant &result)
267 {
268     /* is plugin still running */
269     if( isPluginRunning() )
270     {
271         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
272         libvlc_exception_t ex;
273         libvlc_exception_init(&ex);
274
275         switch( index )
276         {
277             case ID_audio_mute:
278             {
279                 bool muted = libvlc_audio_get_mute(p_plugin->getVLC());
280                 BOOLEAN_TO_NPVARIANT(muted, result);
281                 return INVOKERESULT_NO_ERROR;
282             }
283             case ID_audio_volume:
284             {
285                 int volume = libvlc_audio_get_volume(p_plugin->getVLC());
286                 INT32_TO_NPVARIANT(volume, result);
287                 return INVOKERESULT_NO_ERROR;
288             }
289             case ID_audio_track:
290             {
291                 libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
292                 RETURN_ON_EXCEPTION(this,ex);
293                 int track = libvlc_audio_get_track(p_md, &ex);
294                 RETURN_ON_EXCEPTION(this,ex);
295                 INT32_TO_NPVARIANT(track, result);
296                 return INVOKERESULT_NO_ERROR;
297             }
298             case ID_audio_count:
299             {
300                 libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
301                 RETURN_ON_EXCEPTION(this,ex);
302                 // get the number of audio track available
303                 int i_track = libvlc_audio_get_track_count(p_md, &ex);
304                 RETURN_ON_EXCEPTION(this,ex);
305                 // return it
306                 INT32_TO_NPVARIANT(i_track, result);
307                 return INVOKERESULT_NO_ERROR;
308             }
309             case ID_audio_channel:
310             {
311                 int channel = libvlc_audio_get_channel(p_plugin->getVLC(), &ex);
312                 RETURN_ON_EXCEPTION(this,ex);
313                 INT32_TO_NPVARIANT(channel, result);
314                 return INVOKERESULT_NO_ERROR;
315             }
316             default:
317                 ;
318         }
319     }
320     return INVOKERESULT_GENERIC_ERROR;
321 }
322
323 RuntimeNPObject::InvokeResult
324 LibvlcAudioNPObject::setProperty(int index, const NPVariant &value)
325 {
326     /* is plugin still running */
327     if( isPluginRunning() )
328     {
329         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
330         libvlc_exception_t ex;
331         libvlc_exception_init(&ex);
332
333         switch( index )
334         {
335             case ID_audio_mute:
336                 if( NPVARIANT_IS_BOOLEAN(value) )
337                 {
338                     libvlc_audio_set_mute(p_plugin->getVLC(),
339                                           NPVARIANT_TO_BOOLEAN(value));
340                     return INVOKERESULT_NO_ERROR;
341                 }
342                 return INVOKERESULT_INVALID_VALUE;
343             case ID_audio_volume:
344                 if( isNumberValue(value) )
345                 {
346                     libvlc_audio_set_volume(p_plugin->getVLC(),
347                                             numberValue(value), &ex);
348                     RETURN_ON_EXCEPTION(this,ex);
349                     return INVOKERESULT_NO_ERROR;
350                 }
351                 return INVOKERESULT_INVALID_VALUE;
352             case ID_audio_track:
353                 if( isNumberValue(value) )
354                 {
355                     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
356                     RETURN_ON_EXCEPTION(this,ex);
357                     libvlc_audio_set_track(p_md, numberValue(value), &ex);
358                     RETURN_ON_EXCEPTION(this,ex);
359                     return INVOKERESULT_NO_ERROR;
360                 }
361                 return INVOKERESULT_INVALID_VALUE;
362             case ID_audio_channel:
363                 if( isNumberValue(value) )
364                 {
365                     libvlc_audio_set_channel(p_plugin->getVLC(),
366                                              numberValue(value), &ex);
367                     RETURN_ON_EXCEPTION(this,ex);
368                     return INVOKERESULT_NO_ERROR;
369                 }
370                 return INVOKERESULT_INVALID_VALUE;
371             default:
372                 ;
373         }
374     }
375     return INVOKERESULT_GENERIC_ERROR;
376 }
377
378 const NPUTF8 * const LibvlcAudioNPObject::methodNames[] =
379 {
380     "toggleMute",
381     "description",
382 };
383 COUNTNAMES(LibvlcAudioNPObject,methodCount,methodNames);
384
385 enum LibvlcAudioNPObjectMethodIds
386 {
387     ID_audio_togglemute,
388     ID_audio_description,
389 };
390
391 RuntimeNPObject::InvokeResult
392 LibvlcAudioNPObject::invoke(int index, const NPVariant *args,
393                             uint32_t argCount, NPVariant &result)
394 {
395     /* is plugin still running */
396     if( isPluginRunning() )
397     {
398         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
399         libvlc_exception_t ex;
400         libvlc_exception_init(&ex);
401
402         switch( index )
403         {
404             case ID_audio_togglemute:
405                 if( argCount == 0 )
406                 {
407                     libvlc_audio_toggle_mute(p_plugin->getVLC());
408                     VOID_TO_NPVARIANT(result);
409                     return INVOKERESULT_NO_ERROR;
410                 }
411                 return INVOKERESULT_NO_SUCH_METHOD;
412             case ID_audio_description:
413             {
414                 if( argCount == 1)
415                 {
416                     char *psz_name;
417                     int i_trackID, i_limit, i;
418                     libvlc_track_description_t *p_trackDesc;
419
420                     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
421                     RETURN_ON_EXCEPTION(this,ex);
422
423                     /* get tracks description */
424                     p_trackDesc = libvlc_audio_get_track_description(p_md, &ex);
425                     RETURN_ON_EXCEPTION(this,ex);
426                     if( !p_trackDesc )
427                         return INVOKERESULT_GENERIC_ERROR;
428
429                     /* get the number of track available */
430                     i_limit = libvlc_audio_get_track_count(p_md, &ex);
431                     RETURN_ON_EXCEPTION(this,ex);
432
433                     /* check if a number is given by the user
434                      * and get the track number */
435                     if( isNumberValue(args[0]) )
436                         i_trackID = numberValue(args[0]);
437                     else
438                         return INVOKERESULT_INVALID_VALUE;
439
440                     /* if bad number is given return invalid value */
441                     if ( ( i_trackID > ( i_limit - 1 ) ) || ( i_trackID < 0 ) )
442                         return INVOKERESULT_INVALID_VALUE;
443
444                     /* get the good trackDesc */
445                     for( i = 0 ; i < i_trackID ; i++ )
446                     {
447                         p_trackDesc = p_trackDesc->p_next;
448                     }
449                     psz_name = p_trackDesc->psz_name;
450
451                     /* display the name of the track chosen */
452                     return invokeResultString( psz_name, result );
453                 }
454                 return INVOKERESULT_NO_SUCH_METHOD;
455             }
456             default:
457                 ;
458         }
459     }
460     return INVOKERESULT_GENERIC_ERROR;
461 }
462
463 /*
464 ** implementation of libvlc input object
465 */
466
467 const NPUTF8 * const LibvlcInputNPObject::propertyNames[] =
468 {
469     "length",
470     "position",
471     "time",
472     "state",
473     "rate",
474     "fps",
475     "hasVout",
476 };
477 COUNTNAMES(LibvlcInputNPObject,propertyCount,propertyNames);
478
479 enum LibvlcInputNPObjectPropertyIds
480 {
481     ID_input_length,
482     ID_input_position,
483     ID_input_time,
484     ID_input_state,
485     ID_input_rate,
486     ID_input_fps,
487     ID_input_hasvout,
488 };
489
490 RuntimeNPObject::InvokeResult
491 LibvlcInputNPObject::getProperty(int index, NPVariant &result)
492 {
493     /* is plugin still running */
494     if( isPluginRunning() )
495     {
496         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
497         libvlc_exception_t ex;
498         libvlc_exception_init(&ex);
499
500         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
501         if( libvlc_exception_raised(&ex) )
502         {
503             if( index != ID_input_state )
504             {
505                 NPN_SetException(this, libvlc_errmsg());
506                 libvlc_exception_clear(&ex);
507                 return INVOKERESULT_GENERIC_ERROR;
508             }
509             else
510             {
511                 /* for input state, return CLOSED rather than an exception */
512                 INT32_TO_NPVARIANT(0, result);
513                 libvlc_exception_clear(&ex);
514                 return INVOKERESULT_NO_ERROR;
515             }
516         }
517
518         switch( index )
519         {
520             case ID_input_length:
521             {
522                 double val = (double)libvlc_media_player_get_length(p_md, &ex);
523                 RETURN_ON_EXCEPTION(this,ex);
524                 DOUBLE_TO_NPVARIANT(val, result);
525                 return INVOKERESULT_NO_ERROR;
526             }
527             case ID_input_position:
528             {
529                 double val = libvlc_media_player_get_position(p_md, &ex);
530                 RETURN_ON_EXCEPTION(this,ex);
531                 DOUBLE_TO_NPVARIANT(val, result);
532                 return INVOKERESULT_NO_ERROR;
533             }
534             case ID_input_time:
535             {
536                 double val = (double)libvlc_media_player_get_time(p_md, &ex);
537                 RETURN_ON_EXCEPTION(this,ex);
538                 DOUBLE_TO_NPVARIANT(val, result);
539                 return INVOKERESULT_NO_ERROR;
540             }
541             case ID_input_state:
542             {
543                 int val = libvlc_media_player_get_state(p_md);
544                 RETURN_ON_EXCEPTION(this,ex);
545                 INT32_TO_NPVARIANT(val, result);
546                 return INVOKERESULT_NO_ERROR;
547             }
548             case ID_input_rate:
549             {
550                 float val = libvlc_media_player_get_rate(p_md, &ex);
551                 RETURN_ON_EXCEPTION(this,ex);
552                 DOUBLE_TO_NPVARIANT(val, result);
553                 return INVOKERESULT_NO_ERROR;
554             }
555             case ID_input_fps:
556             {
557                 double val = libvlc_media_player_get_fps(p_md, &ex);
558                 RETURN_ON_EXCEPTION(this,ex);
559                 DOUBLE_TO_NPVARIANT(val, result);
560                 return INVOKERESULT_NO_ERROR;
561             }
562             case ID_input_hasvout:
563             {
564                 bool val = p_plugin->player_has_vout(&ex);
565                 RETURN_ON_EXCEPTION(this,ex);
566                 BOOLEAN_TO_NPVARIANT(val, result);
567                 return INVOKERESULT_NO_ERROR;
568             }
569             default:
570                 ;
571         }
572     }
573     return INVOKERESULT_GENERIC_ERROR;
574 }
575
576 RuntimeNPObject::InvokeResult
577 LibvlcInputNPObject::setProperty(int index, const NPVariant &value)
578 {
579     /* is plugin still running */
580     if( isPluginRunning() )
581     {
582         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
583         libvlc_exception_t ex;
584         libvlc_exception_init(&ex);
585
586         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
587         RETURN_ON_EXCEPTION(this,ex);
588
589         switch( index )
590         {
591             case ID_input_position:
592             {
593                 if( ! NPVARIANT_IS_DOUBLE(value) )
594                 {
595                     return INVOKERESULT_INVALID_VALUE;
596                 }
597
598                 float val = (float)NPVARIANT_TO_DOUBLE(value);
599                 libvlc_media_player_set_position(p_md, val, &ex);
600                 RETURN_ON_EXCEPTION(this,ex);
601                 return INVOKERESULT_NO_ERROR;
602             }
603             case ID_input_time:
604             {
605                 int64_t val;
606                 if( NPVARIANT_IS_INT32(value) )
607                     val = (int64_t)NPVARIANT_TO_INT32(value);
608                 else if( NPVARIANT_IS_DOUBLE(value) )
609                     val = (int64_t)NPVARIANT_TO_DOUBLE(value);
610                 else
611                 {
612                     return INVOKERESULT_INVALID_VALUE;
613                 }
614
615                 libvlc_media_player_set_time(p_md, val, &ex);
616                 RETURN_ON_EXCEPTION(this,ex);
617                 return INVOKERESULT_NO_ERROR;
618             }
619             case ID_input_rate:
620             {
621                 float val;
622                 if( NPVARIANT_IS_INT32(value) )
623                     val = (float)NPVARIANT_TO_INT32(value);
624                 else if( NPVARIANT_IS_DOUBLE(value) )
625                     val = (float)NPVARIANT_TO_DOUBLE(value);
626                 else
627                 {
628                     return INVOKERESULT_INVALID_VALUE;
629                 }
630
631                 libvlc_media_player_set_rate(p_md, val, &ex);
632                 RETURN_ON_EXCEPTION(this,ex);
633                 return INVOKERESULT_NO_ERROR;
634             }
635             default:
636                 ;
637         }
638     }
639     return INVOKERESULT_GENERIC_ERROR;
640 }
641
642 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =
643 {
644     /* no methods */
645     "none",
646 };
647 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
648
649 enum LibvlcInputNPObjectMethodIds
650 {
651     ID_none,
652 };
653
654 RuntimeNPObject::InvokeResult
655 LibvlcInputNPObject::invoke(int index, const NPVariant *args,
656                                     uint32_t argCount, NPVariant &result)
657 {
658     /* is plugin still running */
659     if( isPluginRunning() )
660     {
661         switch( index )
662         {
663             case ID_none:
664                 return INVOKERESULT_NO_SUCH_METHOD;
665             default:
666                 ;
667         }
668     }
669     return INVOKERESULT_GENERIC_ERROR;
670 }
671
672 /*
673 ** implementation of libvlc playlist items object
674 */
675
676 const NPUTF8 * const LibvlcPlaylistItemsNPObject::propertyNames[] =
677 {
678     "count",
679 };
680 COUNTNAMES(LibvlcPlaylistItemsNPObject,propertyCount,propertyNames);
681
682 enum LibvlcPlaylistItemsNPObjectPropertyIds
683 {
684     ID_playlistitems_count,
685 };
686
687 RuntimeNPObject::InvokeResult
688 LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
689 {
690     /* is plugin still running */
691     if( isPluginRunning() )
692     {
693         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
694
695         switch( index )
696         {
697             case ID_playlistitems_count:
698             {
699                 int val = p_plugin->playlist_count();
700                 INT32_TO_NPVARIANT(val, result);
701                 return INVOKERESULT_NO_ERROR;
702             }
703             default:
704                 ;
705         }
706     }
707     return INVOKERESULT_GENERIC_ERROR;
708 }
709
710 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
711 {
712     "clear",
713     "remove",
714 };
715 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
716
717 enum LibvlcPlaylistItemsNPObjectMethodIds
718 {
719     ID_playlistitems_clear,
720     ID_playlistitems_remove,
721 };
722
723 RuntimeNPObject::InvokeResult
724 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
725                                     uint32_t argCount, NPVariant &result)
726 {
727     /* is plugin still running */
728     if( isPluginRunning() )
729     {
730         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
731         libvlc_exception_t ex;
732         libvlc_exception_init(&ex);
733
734         switch( index )
735         {
736             case ID_playlistitems_clear:
737                 if( argCount == 0 )
738                 {
739                     p_plugin->playlist_clear(&ex);
740                     RETURN_ON_EXCEPTION(this,ex);
741                     VOID_TO_NPVARIANT(result);
742                     return INVOKERESULT_NO_ERROR;
743                 }
744                 return INVOKERESULT_NO_SUCH_METHOD;
745             case ID_playlistitems_remove:
746                 if( (argCount == 1) && isNumberValue(args[0]) )
747                 {
748                     p_plugin->playlist_delete_item(numberValue(args[0]),&ex);
749                     RETURN_ON_EXCEPTION(this,ex);
750                     VOID_TO_NPVARIANT(result);
751                     return INVOKERESULT_NO_ERROR;
752                 }
753                 return INVOKERESULT_NO_SUCH_METHOD;
754             default:
755                 ;
756         }
757     }
758     return INVOKERESULT_GENERIC_ERROR;
759 }
760
761 /*
762 ** implementation of libvlc playlist object
763 */
764
765 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
766 {
767     // Why the isValid()?
768     if( isValid() && playlistItemsObj )
769         NPN_ReleaseObject(playlistItemsObj);
770 };
771
772 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
773 {
774     "itemCount", /* deprecated */
775     "isPlaying",
776     "items",
777 };
778 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
779
780 enum LibvlcPlaylistNPObjectPropertyIds
781 {
782     ID_playlist_itemcount,
783     ID_playlist_isplaying,
784     ID_playlist_items,
785 };
786
787 RuntimeNPObject::InvokeResult
788 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
789 {
790     /* is plugin still running */
791     if( isPluginRunning() )
792     {
793         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
794
795         switch( index )
796         {
797             case ID_playlist_itemcount: /* deprecated */
798             {
799                 int val = p_plugin->playlist_count();
800                 INT32_TO_NPVARIANT(val, result);
801                 return INVOKERESULT_NO_ERROR;
802             }
803             case ID_playlist_isplaying:
804             {
805                 int val = p_plugin->playlist_isplaying();
806                 BOOLEAN_TO_NPVARIANT(val, result);
807                 return INVOKERESULT_NO_ERROR;
808             }
809             case ID_playlist_items:
810             {
811                 InstantObj<LibvlcPlaylistItemsNPObject>( playlistItemsObj );
812                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
813                 return INVOKERESULT_NO_ERROR;
814             }
815             default:
816                 ;
817         }
818     }
819     return INVOKERESULT_GENERIC_ERROR;
820 }
821
822 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
823 {
824     "add",
825     "play",
826     "playItem",
827     "togglePause",
828     "stop",
829     "next",
830     "prev",
831     "clear", /* deprecated */
832     "removeItem", /* deprecated */
833 };
834 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
835
836 enum LibvlcPlaylistNPObjectMethodIds
837 {
838     ID_playlist_add,
839     ID_playlist_play,
840     ID_playlist_playItem,
841     ID_playlist_togglepause,
842     ID_playlist_stop,
843     ID_playlist_next,
844     ID_playlist_prev,
845     ID_playlist_clear,
846     ID_playlist_removeitem
847 };
848
849 RuntimeNPObject::InvokeResult
850 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
851                                uint32_t argCount, NPVariant &result)
852 {
853     /* is plugin still running */
854     if( isPluginRunning() )
855     {
856         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
857         libvlc_exception_t ex;
858         libvlc_exception_init(&ex);
859
860         switch( index )
861         {
862             // XXX FIXME this needs squashing into something much smaller
863             case ID_playlist_add:
864             {
865                 if( (argCount < 1) || (argCount > 3) )
866                     return INVOKERESULT_NO_SUCH_METHOD;
867                 if( !NPVARIANT_IS_STRING(args[0]) )
868                     return INVOKERESULT_NO_SUCH_METHOD;
869
870                 // grab URL
871                 if( NPVARIANT_IS_NULL(args[0]) )
872                     return INVOKERESULT_NO_SUCH_METHOD;
873
874                 char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
875                 if( !s )
876                     return INVOKERESULT_OUT_OF_MEMORY;
877
878                 char *url = p_plugin->getAbsoluteURL(s);
879                 if( url )
880                     free(s);
881                 else
882                     // problem with combining url, use argument
883                     url = s;
884
885                 char *name = NULL;
886
887                 // grab name if available
888                 if( argCount > 1 )
889                 {
890                     if( NPVARIANT_IS_NULL(args[1]) )
891                     {
892                         // do nothing
893                     }
894                     else if( NPVARIANT_IS_STRING(args[1]) )
895                     {
896                         name = stringValue(NPVARIANT_TO_STRING(args[1]));
897                     }
898                     else
899                     {
900                         free(url);
901                         return INVOKERESULT_INVALID_VALUE;
902                     }
903                 }
904
905                 int i_options = 0;
906                 char** ppsz_options = NULL;
907
908                 // grab options if available
909                 if( argCount > 2 )
910                 {
911                     if( NPVARIANT_IS_NULL(args[2]) )
912                     {
913                         // do nothing
914                     }
915                     else if( NPVARIANT_IS_STRING(args[2]) )
916                     {
917                         parseOptions(NPVARIANT_TO_STRING(args[2]),
918                                      &i_options, &ppsz_options);
919
920                     }
921                     else if( NPVARIANT_IS_OBJECT(args[2]) )
922                     {
923                         parseOptions(NPVARIANT_TO_OBJECT(args[2]),
924                                      &i_options, &ppsz_options);
925                     }
926                     else
927                     {
928                         free(url);
929                         free(name);
930                         return INVOKERESULT_INVALID_VALUE;
931                     }
932                 }
933
934                 int item = p_plugin->playlist_add_extended_untrusted(url, name,
935                       i_options, const_cast<const char **>(ppsz_options), &ex);
936                 free(url);
937                 free(name);
938                 for( int i=0; i< i_options; ++i )
939                 {
940                     free(ppsz_options[i]);
941                 }
942                 free(ppsz_options);
943
944                 RETURN_ON_EXCEPTION(this,ex);
945                 INT32_TO_NPVARIANT(item, result);
946                 return INVOKERESULT_NO_ERROR;
947             }
948             case ID_playlist_play:
949                 if( argCount == 0 )
950                 {
951                     p_plugin->playlist_play(&ex);
952                     RETURN_ON_EXCEPTION(this,ex);
953                     VOID_TO_NPVARIANT(result);
954                     return INVOKERESULT_NO_ERROR;
955                 }
956                 return INVOKERESULT_NO_SUCH_METHOD;
957             case ID_playlist_playItem:
958                 if( (argCount == 1) && isNumberValue(args[0]) )
959                 {
960                     p_plugin->playlist_play_item(numberValue(args[0]),&ex);
961                     RETURN_ON_EXCEPTION(this,ex);
962                     VOID_TO_NPVARIANT(result);
963                     return INVOKERESULT_NO_ERROR;
964                 }
965                 return INVOKERESULT_NO_SUCH_METHOD;
966             case ID_playlist_togglepause:
967                 if( argCount == 0 )
968                 {
969                     p_plugin->playlist_pause(&ex);
970                     RETURN_ON_EXCEPTION(this,ex);
971                     VOID_TO_NPVARIANT(result);
972                     return INVOKERESULT_NO_ERROR;
973                 }
974                 return INVOKERESULT_NO_SUCH_METHOD;
975             case ID_playlist_stop:
976                 if( argCount == 0 )
977                 {
978                     p_plugin->playlist_stop();
979                     VOID_TO_NPVARIANT(result);
980                     return INVOKERESULT_NO_ERROR;
981                 }
982                 return INVOKERESULT_NO_SUCH_METHOD;
983             case ID_playlist_next:
984                 if( argCount == 0 )
985                 {
986                     p_plugin->playlist_next(&ex);
987                     RETURN_ON_EXCEPTION(this,ex);
988                     VOID_TO_NPVARIANT(result);
989                     return INVOKERESULT_NO_ERROR;
990                 }
991                 return INVOKERESULT_NO_SUCH_METHOD;
992             case ID_playlist_prev:
993                 if( argCount == 0 )
994                 {
995                     p_plugin->playlist_prev(&ex);
996                     RETURN_ON_EXCEPTION(this,ex);
997                     VOID_TO_NPVARIANT(result);
998                     return INVOKERESULT_NO_ERROR;
999                 }
1000                 return INVOKERESULT_NO_SUCH_METHOD;
1001             case ID_playlist_clear: /* deprecated */
1002                 if( argCount == 0 )
1003                 {
1004                     p_plugin->playlist_clear(&ex);
1005                     RETURN_ON_EXCEPTION(this,ex);
1006                     VOID_TO_NPVARIANT(result);
1007                     return INVOKERESULT_NO_ERROR;
1008                 }
1009                 return INVOKERESULT_NO_SUCH_METHOD;
1010             case ID_playlist_removeitem: /* deprecated */
1011                 if( (argCount == 1) && isNumberValue(args[0]) )
1012                 {
1013                     p_plugin->playlist_delete_item(numberValue(args[0]), &ex);
1014                     RETURN_ON_EXCEPTION(this,ex);
1015                     VOID_TO_NPVARIANT(result);
1016                     return INVOKERESULT_NO_ERROR;
1017                 }
1018                 return INVOKERESULT_NO_SUCH_METHOD;
1019             default:
1020                 ;
1021         }
1022     }
1023     return INVOKERESULT_GENERIC_ERROR;
1024 }
1025
1026 // XXX FIXME The new playlist_add creates a media instance and feeds it
1027 // XXX FIXME these options one at a time, so this hunk of code does lots
1028 // XXX FIXME of unnecessairy work. Break out something that can do one
1029 // XXX FIXME option at a time and doesn't need to realloc().
1030 // XXX FIXME Same for the other version of parseOptions.
1031
1032 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
1033                                          int *i_options, char*** ppsz_options)
1034 {
1035     if( nps.utf8length )
1036     {
1037         char *s = stringValue(nps);
1038         char *val = s;
1039         if( val )
1040         {
1041             long capacity = 16;
1042             char **options = (char **)malloc(capacity*sizeof(char *));
1043             if( options )
1044             {
1045                 int nOptions = 0;
1046
1047                 char *end = val + nps.utf8length;
1048                 while( val < end )
1049                 {
1050                     // skip leading blanks
1051                     while( (val < end)
1052                         && ((*val == ' ' ) || (*val == '\t')) )
1053                         ++val;
1054
1055                     char *start = val;
1056                     // skip till we get a blank character
1057                     while( (val < end)
1058                         && (*val != ' ' )
1059                         && (*val != '\t') )
1060                     {
1061                         char c = *(val++);
1062                         if( ('\'' == c) || ('"' == c) )
1063                         {
1064                             // skip till end of string
1065                             while( (val < end) && (*(val++) != c ) );
1066                         }
1067                     }
1068
1069                     if( val > start )
1070                     {
1071                         if( nOptions == capacity )
1072                         {
1073                             capacity += 16;
1074                             char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1075                             if( ! moreOptions )
1076                             {
1077                                 /* failed to allocate more memory */
1078                                 free(s);
1079                                 /* return what we got so far */
1080                                 *i_options = nOptions;
1081                                 *ppsz_options = options;
1082                                 return;
1083                             }
1084                             options = moreOptions;
1085                         }
1086                         *(val++) = '\0';
1087                         options[nOptions++] = strdup(start);
1088                     }
1089                     else
1090                         // must be end of string
1091                         break;
1092                 }
1093                 *i_options = nOptions;
1094                 *ppsz_options = options;
1095             }
1096             free(s);
1097         }
1098     }
1099 }
1100
1101 // XXX FIXME See comment at the other parseOptions variant.
1102 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
1103                                           char*** ppsz_options)
1104 {
1105     /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1106
1107     NPVariant value;
1108
1109     /* we are expecting to have a Javascript Array object */
1110     NPIdentifier propId = NPN_GetStringIdentifier("length");
1111     if( NPN_GetProperty(_instance, obj, propId, &value) )
1112     {
1113         int count = numberValue(value);
1114         NPN_ReleaseVariantValue(&value);
1115
1116         if( count )
1117         {
1118             long capacity = 16;
1119             char **options = (char **)malloc(capacity*sizeof(char *));
1120             if( options )
1121             {
1122                 int nOptions = 0;
1123
1124                 while( nOptions < count )
1125                 {
1126                     propId = NPN_GetIntIdentifier(nOptions);
1127                     if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1128                         /* return what we got so far */
1129                         break;
1130
1131                     if( ! NPVARIANT_IS_STRING(value) )
1132                     {
1133                         /* return what we got so far */
1134                         NPN_ReleaseVariantValue(&value);
1135                         break;
1136                     }
1137
1138                     if( nOptions == capacity )
1139                     {
1140                         capacity += 16;
1141                         char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1142                         if( ! moreOptions )
1143                         {
1144                             /* failed to allocate more memory */
1145                             NPN_ReleaseVariantValue(&value);
1146                             /* return what we got so far */
1147                             *i_options = nOptions;
1148                             *ppsz_options = options;
1149                             break;
1150                         }
1151                         options = moreOptions;
1152                     }
1153
1154                     options[nOptions++] = stringValue(value);
1155                     NPN_ReleaseVariantValue(&value);
1156                 }
1157                 *i_options = nOptions;
1158                 *ppsz_options = options;
1159             }
1160         }
1161     }
1162 }
1163
1164 /*
1165 ** implementation of libvlc subtitle object
1166 */
1167
1168 const NPUTF8 * const LibvlcSubtitleNPObject::propertyNames[] =
1169 {
1170     "track",
1171     "count",
1172 };
1173
1174 enum LibvlcSubtitleNPObjectPropertyIds
1175 {
1176     ID_subtitle_track,
1177     ID_subtitle_count,
1178 };
1179 COUNTNAMES(LibvlcSubtitleNPObject,propertyCount,propertyNames);
1180
1181 RuntimeNPObject::InvokeResult
1182 LibvlcSubtitleNPObject::getProperty(int index, NPVariant &result)
1183 {
1184     /* is plugin still running */
1185     if( isPluginRunning() )
1186     {
1187         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1188         libvlc_exception_t ex;
1189         libvlc_exception_init(&ex);
1190
1191         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1192         RETURN_ON_EXCEPTION(this,ex);
1193
1194         switch( index )
1195         {
1196             case ID_subtitle_track:
1197             {
1198                 /* get the current subtitle ID */
1199                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1200                 RETURN_ON_EXCEPTION(this,ex);
1201                 /* return it */
1202                 INT32_TO_NPVARIANT(i_spu, result);
1203                 return INVOKERESULT_NO_ERROR;
1204             }
1205             case ID_subtitle_count:
1206             {
1207                 /* get the number of subtitles available */
1208                 int i_spu = libvlc_video_get_spu_count(p_md, &ex);
1209                 RETURN_ON_EXCEPTION(this,ex);
1210                 /* return it */
1211                 INT32_TO_NPVARIANT(i_spu, result);
1212                 return INVOKERESULT_NO_ERROR;
1213             }
1214         }
1215     }
1216     return INVOKERESULT_GENERIC_ERROR;
1217 }
1218
1219 RuntimeNPObject::InvokeResult
1220 LibvlcSubtitleNPObject::setProperty(int index, const NPVariant &value)
1221 {
1222     /* is plugin still running */
1223     if( isPluginRunning() )
1224     {
1225         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1226         libvlc_exception_t ex;
1227         libvlc_exception_init(&ex);
1228
1229         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1230         RETURN_ON_EXCEPTION(this,ex);
1231
1232         switch( index )
1233         {
1234             case ID_subtitle_track:
1235             {
1236                 if( isNumberValue(value) )
1237                 {
1238                     /* set the new subtitle track to show */
1239                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1240                     RETURN_ON_EXCEPTION(this,ex);
1241
1242                     return INVOKERESULT_NO_ERROR;
1243                 }
1244                 return INVOKERESULT_INVALID_VALUE;
1245             }
1246         }
1247     }
1248     return INVOKERESULT_GENERIC_ERROR;
1249 }
1250
1251 const NPUTF8 * const LibvlcSubtitleNPObject::methodNames[] =
1252 {
1253     "description"
1254 };
1255 COUNTNAMES(LibvlcSubtitleNPObject,methodCount,methodNames);
1256
1257 enum LibvlcSubtitleNPObjectMethodIds
1258 {
1259     ID_subtitle_description
1260 };
1261
1262 RuntimeNPObject::InvokeResult
1263 LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
1264                             uint32_t argCount, NPVariant &result)
1265 {
1266     /* is plugin still running */
1267     if( isPluginRunning() )
1268     {
1269         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1270         libvlc_exception_t ex;
1271         libvlc_exception_init(&ex);
1272
1273         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1274         RETURN_ON_EXCEPTION(this,ex);
1275
1276         switch( index )
1277         {
1278             case ID_subtitle_description:
1279             {
1280                 if( argCount == 1)
1281                 {
1282                     char *psz_name;
1283                     int i_spuID, i_limit, i;
1284                     libvlc_track_description_t *p_spuDesc;
1285
1286                     /* get subtitles description */
1287                     p_spuDesc = libvlc_video_get_spu_description(p_md, &ex);
1288                     RETURN_ON_EXCEPTION(this,ex);
1289                     if( !p_spuDesc )
1290                         return INVOKERESULT_GENERIC_ERROR;
1291
1292                     /* get the number of subtitle available */
1293                     i_limit = libvlc_video_get_spu_count(p_md, &ex);
1294                     RETURN_ON_EXCEPTION(this,ex);
1295
1296                     /* check if a number is given by the user
1297                      * and get the subtitle number */
1298                     if( isNumberValue(args[0]) )
1299                         i_spuID = numberValue(args[0]);
1300                     else
1301                         return INVOKERESULT_INVALID_VALUE;
1302
1303                     /* if bad number is given return invalid value */
1304                     if ( ( i_spuID > ( i_limit -1 ) ) || ( i_spuID < 0 ) )
1305                         return INVOKERESULT_INVALID_VALUE;
1306
1307                     /* get the good spuDesc */
1308                     for( i = 0 ; i < i_spuID ; i++ )
1309                     {
1310                         p_spuDesc = p_spuDesc->p_next;
1311                     }
1312                     psz_name = p_spuDesc->psz_name;
1313
1314                     /* return the name of the track chosen */
1315                     return invokeResultString(psz_name, result);
1316                 }
1317                 return INVOKERESULT_NO_SUCH_METHOD;
1318             }
1319             default:
1320                 return INVOKERESULT_NO_SUCH_METHOD;
1321         }
1322     }
1323     return INVOKERESULT_GENERIC_ERROR;
1324 }
1325
1326 /*
1327 ** implementation of libvlc video object
1328 */
1329
1330 LibvlcVideoNPObject::~LibvlcVideoNPObject()
1331 {
1332     if( isValid() )
1333     {
1334         if( marqueeObj ) NPN_ReleaseObject(marqueeObj);
1335         if( logoObj    ) NPN_ReleaseObject(logoObj);
1336         if( deintObj   ) NPN_ReleaseObject(deintObj);
1337     }
1338 }
1339
1340 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1341 {
1342     "fullscreen",
1343     "height",
1344     "width",
1345     "aspectRatio",
1346     "subtitle",
1347     "crop",
1348     "teletext",
1349     "marquee",
1350     "logo",
1351     "deinterlace",
1352 };
1353
1354 enum LibvlcVideoNPObjectPropertyIds
1355 {
1356     ID_video_fullscreen,
1357     ID_video_height,
1358     ID_video_width,
1359     ID_video_aspectratio,
1360     ID_video_subtitle,
1361     ID_video_crop,
1362     ID_video_teletext,
1363     ID_video_marquee,
1364     ID_video_logo,
1365     ID_video_deinterlace,
1366 };
1367 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1368
1369 RuntimeNPObject::InvokeResult
1370 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1371 {
1372     /* is plugin still running */
1373     if( isPluginRunning() )
1374     {
1375         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1376         libvlc_exception_t ex;
1377         libvlc_exception_init(&ex);
1378
1379         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1380         RETURN_ON_EXCEPTION(this,ex);
1381
1382         switch( index )
1383         {
1384             case ID_video_fullscreen:
1385             {
1386                 int val = p_plugin->get_fullscreen(&ex);
1387                 RETURN_ON_EXCEPTION(this,ex);
1388                 BOOLEAN_TO_NPVARIANT(val, result);
1389                 return INVOKERESULT_NO_ERROR;
1390             }
1391             case ID_video_height:
1392             {
1393                 int val = libvlc_video_get_height(p_md, &ex);
1394                 RETURN_ON_EXCEPTION(this,ex);
1395                 INT32_TO_NPVARIANT(val, result);
1396                 return INVOKERESULT_NO_ERROR;
1397             }
1398             case ID_video_width:
1399             {
1400                 int val = libvlc_video_get_width(p_md, &ex);
1401                 RETURN_ON_EXCEPTION(this,ex);
1402                 INT32_TO_NPVARIANT(val, result);
1403                 return INVOKERESULT_NO_ERROR;
1404             }
1405             case ID_video_aspectratio:
1406             {
1407                 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1408                 RETURN_ON_EXCEPTION(this,ex);
1409                 if( !psz_aspect )
1410                     return INVOKERESULT_GENERIC_ERROR;
1411
1412                 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1413                 return INVOKERESULT_NO_ERROR;
1414             }
1415             case ID_video_subtitle:
1416             {
1417                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1418                 RETURN_ON_EXCEPTION(this,ex);
1419                 INT32_TO_NPVARIANT(i_spu, result);
1420                 return INVOKERESULT_NO_ERROR;
1421             }
1422             case ID_video_crop:
1423             {
1424                 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1425                 RETURN_ON_EXCEPTION(this,ex);
1426                 if( !psz_geometry )
1427                     return INVOKERESULT_GENERIC_ERROR;
1428
1429                 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1430                 return INVOKERESULT_NO_ERROR;
1431             }
1432             case ID_video_teletext:
1433             {
1434 /*                int i_page = libvlc_video_get_teletext(p_md, &ex);
1435                 RETURN_ON_EXCEPTION(this,ex);
1436                 INT32_TO_NPVARIANT(i_page, result);
1437                 return INVOKERESULT_NO_ERROR;
1438 */
1439                 return INVOKERESULT_NO_SUCH_METHOD;
1440             }
1441             case ID_video_marquee:
1442             {
1443                 InstantObj<LibvlcMarqueeNPObject>( marqueeObj );
1444                 OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1445                 return INVOKERESULT_NO_ERROR;
1446             }
1447             case ID_video_logo:
1448             {
1449                 InstantObj<LibvlcLogoNPObject>( logoObj );
1450                 OBJECT_TO_NPVARIANT(NPN_RetainObject(logoObj), result);
1451                 return INVOKERESULT_NO_ERROR;
1452             }
1453             case ID_video_deinterlace:
1454             {
1455                 InstantObj<LibvlcDeinterlaceNPObject>( deintObj );
1456                 OBJECT_TO_NPVARIANT(NPN_RetainObject(deintObj), result);
1457                 return INVOKERESULT_NO_ERROR;
1458             }
1459         }
1460     }
1461     return INVOKERESULT_GENERIC_ERROR;
1462 }
1463
1464 RuntimeNPObject::InvokeResult
1465 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1466 {
1467     /* is plugin still running */
1468     if( isPluginRunning() )
1469     {
1470         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1471         libvlc_exception_t ex;
1472         libvlc_exception_init(&ex);
1473
1474         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1475         RETURN_ON_EXCEPTION(this,ex);
1476
1477         switch( index )
1478         {
1479             case ID_video_fullscreen:
1480             {
1481                 if( ! NPVARIANT_IS_BOOLEAN(value) )
1482                 {
1483                     return INVOKERESULT_INVALID_VALUE;
1484                 }
1485
1486                 int val = NPVARIANT_TO_BOOLEAN(value);
1487                 p_plugin->set_fullscreen(val, &ex);
1488                 RETURN_ON_EXCEPTION(this,ex);
1489                 return INVOKERESULT_NO_ERROR;
1490             }
1491             case ID_video_aspectratio:
1492             {
1493                 char *psz_aspect = NULL;
1494
1495                 if( ! NPVARIANT_IS_STRING(value) )
1496                 {
1497                     return INVOKERESULT_INVALID_VALUE;
1498                 }
1499
1500                 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1501                 if( !psz_aspect )
1502                 {
1503                     return INVOKERESULT_GENERIC_ERROR;
1504                 }
1505
1506                 libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1507                 free(psz_aspect);
1508                 RETURN_ON_EXCEPTION(this,ex);
1509
1510                 return INVOKERESULT_NO_ERROR;
1511             }
1512             case ID_video_subtitle:
1513             {
1514                 if( isNumberValue(value) )
1515                 {
1516                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1517                     RETURN_ON_EXCEPTION(this,ex);
1518
1519                     return INVOKERESULT_NO_ERROR;
1520                 }
1521                 return INVOKERESULT_INVALID_VALUE;
1522             }
1523             case ID_video_crop:
1524             {
1525                 char *psz_geometry = NULL;
1526
1527                 if( ! NPVARIANT_IS_STRING(value) )
1528                 {
1529                     return INVOKERESULT_INVALID_VALUE;
1530                 }
1531
1532                 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1533                 if( !psz_geometry )
1534                 {
1535                     return INVOKERESULT_GENERIC_ERROR;
1536                 }
1537
1538                 libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
1539                 free(psz_geometry);
1540                 RETURN_ON_EXCEPTION(this,ex);
1541
1542                 return INVOKERESULT_NO_ERROR;
1543             }
1544             case ID_video_teletext:
1545             {
1546                 if( isNumberValue(value) )
1547                 {
1548 /*
1549                     libvlc_video_set_teletext(p_md, numberValue(value), &ex);
1550                     RETURN_ON_EXCEPTION(this,ex);
1551
1552                     return INVOKERESULT_NO_ERROR;
1553 */
1554                     return INVOKERESULT_NO_SUCH_METHOD;
1555                 }
1556                 return INVOKERESULT_INVALID_VALUE;
1557             }
1558         }
1559     }
1560     return INVOKERESULT_GENERIC_ERROR;
1561 }
1562
1563 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1564 {
1565     "toggleFullscreen",
1566     "toggleTeletext",
1567 };
1568 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1569
1570 enum LibvlcVideoNPObjectMethodIds
1571 {
1572     ID_video_togglefullscreen,
1573     ID_video_toggleteletext,
1574 };
1575
1576 RuntimeNPObject::InvokeResult
1577 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1578                             uint32_t argCount, NPVariant &result)
1579 {
1580     /* is plugin still running */
1581     if( isPluginRunning() )
1582     {
1583         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1584         libvlc_exception_t ex;
1585         libvlc_exception_init(&ex);
1586
1587         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1588         RETURN_ON_EXCEPTION(this,ex);
1589
1590         switch( index )
1591         {
1592             case ID_video_togglefullscreen:
1593             {
1594                 if( argCount == 0 )
1595                 {
1596                     p_plugin->toggle_fullscreen(&ex);
1597                     RETURN_ON_EXCEPTION(this,ex);
1598                     VOID_TO_NPVARIANT(result);
1599                     return INVOKERESULT_NO_ERROR;
1600                 }
1601                 return INVOKERESULT_NO_SUCH_METHOD;
1602             }
1603             case ID_video_toggleteletext:
1604             {
1605                 if( argCount == 0 )
1606                 {
1607                     libvlc_toggle_teletext(p_md, &ex);
1608                     RETURN_ON_EXCEPTION(this,ex);
1609                     VOID_TO_NPVARIANT(result);
1610                     return INVOKERESULT_NO_ERROR;
1611                 }
1612                 return INVOKERESULT_NO_SUCH_METHOD;
1613             }
1614             default:
1615                 return INVOKERESULT_NO_SUCH_METHOD;
1616         }
1617     }
1618     return INVOKERESULT_GENERIC_ERROR;
1619 }
1620
1621 /*
1622 ** implementation of libvlc marquee object
1623 */
1624
1625 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1626 {
1627     "color",
1628     "opacity",
1629     "position",
1630     "refresh",
1631     "size",
1632     "text",
1633     "timeout",
1634     "x",
1635     "y",
1636 };
1637
1638 enum LibvlcMarqueeNPObjectPropertyIds
1639 {
1640     ID_marquee_color,
1641     ID_marquee_opacity,
1642     ID_marquee_position,
1643     ID_marquee_refresh,
1644     ID_marquee_size,
1645     ID_marquee_text,
1646     ID_marquee_timeout,
1647     ID_marquee_x,
1648     ID_marquee_y,
1649 };
1650
1651 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
1652
1653 static const unsigned char marquee_idx[] = {
1654     libvlc_marquee_Color,
1655     libvlc_marquee_Opacity,
1656     libvlc_marquee_Position,
1657     libvlc_marquee_Refresh,
1658     libvlc_marquee_Size,
1659     0,
1660     libvlc_marquee_Timeout,
1661     libvlc_marquee_X,
1662     libvlc_marquee_Y,
1663 };
1664
1665 RuntimeNPObject::InvokeResult
1666 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1667 {
1668     char *psz;
1669
1670     if( !isPluginRunning() )
1671         return INVOKERESULT_GENERIC_ERROR;
1672
1673     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1674     libvlc_exception_t ex;
1675     libvlc_exception_init(&ex);
1676
1677     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1678     RETURN_ON_EXCEPTION(this,ex);
1679
1680     switch( index )
1681     {
1682     case ID_marquee_color:
1683     case ID_marquee_opacity:
1684     case ID_marquee_refresh:
1685     case ID_marquee_timeout:
1686     case ID_marquee_size:
1687     case ID_marquee_x:
1688     case ID_marquee_y:
1689         INT32_TO_NPVARIANT(
1690             libvlc_video_get_marquee_int(p_md, marquee_idx[index], &ex),
1691             result );
1692         RETURN_ON_EXCEPTION(this,ex);
1693         return INVOKERESULT_NO_ERROR;
1694
1695     case ID_marquee_position:
1696         STRINGZ_TO_NPVARIANT( position_bynumber(
1697             libvlc_video_get_marquee_int(p_md, libvlc_marquee_Position, &ex) ),
1698             result );
1699
1700         RETURN_ON_EXCEPTION(this,ex);
1701         break;
1702
1703     case ID_marquee_text:
1704         psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text, &ex);
1705         if( psz )
1706         {
1707             STRINGZ_TO_NPVARIANT(psz, result);
1708             return INVOKERESULT_NO_ERROR;
1709         }
1710         break;
1711     }
1712     return INVOKERESULT_GENERIC_ERROR;
1713 }
1714
1715 RuntimeNPObject::InvokeResult
1716 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1717 {
1718     size_t i;
1719
1720     if( !isPluginRunning() )
1721         return INVOKERESULT_GENERIC_ERROR;
1722
1723     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1724     libvlc_exception_t ex;
1725     libvlc_exception_init(&ex);
1726     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1727     RETURN_ON_EXCEPTION(this,ex);
1728
1729     switch( index )
1730     {
1731     case ID_marquee_color:
1732     case ID_marquee_opacity:
1733     case ID_marquee_refresh:
1734     case ID_marquee_timeout:
1735     case ID_marquee_x:
1736     case ID_marquee_y:
1737         if( NPVARIANT_IS_INT32( value ) )
1738         {
1739             libvlc_video_set_marquee_int(p_md, marquee_idx[index],
1740                                          NPVARIANT_TO_INT32( value ), &ex);
1741             RETURN_ON_EXCEPTION(this,ex);
1742             return INVOKERESULT_NO_ERROR;
1743         }
1744         break;
1745
1746     case ID_marquee_position:
1747         if( !NPVARIANT_IS_STRING(value) ||
1748             !position_byname( NPVARIANT_TO_STRING(value).utf8characters, i ) )
1749             return INVOKERESULT_INVALID_VALUE;
1750
1751         libvlc_video_set_marquee_int(p_md, libvlc_marquee_Position, i, &ex);
1752         RETURN_ON_EXCEPTION(this,ex);
1753         return INVOKERESULT_NO_ERROR;
1754
1755     case ID_marquee_text:
1756         if( NPVARIANT_IS_STRING( value ) )
1757         {
1758             char *psz_text = stringValue( NPVARIANT_TO_STRING( value ) );
1759             libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
1760                                             psz_text, &ex);
1761             free(psz_text);
1762             RETURN_ON_EXCEPTION(this,ex);
1763             return INVOKERESULT_NO_ERROR;
1764         }
1765         break;
1766     }
1767     return INVOKERESULT_NO_SUCH_METHOD;
1768 }
1769
1770 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1771 {
1772     "enable",
1773     "disable",
1774 };
1775 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1776
1777 enum LibvlcMarqueeNPObjectMethodIds
1778 {
1779     ID_marquee_enable,
1780     ID_marquee_disable,
1781 };
1782
1783 RuntimeNPObject::InvokeResult
1784 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1785                             uint32_t argCount, NPVariant &result)
1786 {
1787     if( !isPluginRunning() )
1788         return INVOKERESULT_GENERIC_ERROR;
1789
1790     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1791     libvlc_exception_t ex;
1792     libvlc_exception_init(&ex);
1793
1794     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1795     RETURN_ON_EXCEPTION(this,ex);
1796
1797     switch( index )
1798     {
1799     case ID_marquee_enable:
1800     case ID_marquee_disable:
1801         libvlc_video_set_marquee_int(p_md, libvlc_marquee_Enable,
1802                                      index!=ID_marquee_disable, &ex);
1803         RETURN_ON_EXCEPTION(this,ex);
1804         VOID_TO_NPVARIANT(result);
1805         return INVOKERESULT_NO_ERROR;
1806     }
1807     return INVOKERESULT_NO_SUCH_METHOD;
1808 }
1809
1810 const NPUTF8 * const LibvlcLogoNPObject::propertyNames[] = {
1811     "delay",
1812     "repeat",
1813     "opacity",
1814     "position",
1815     "x",
1816     "y",
1817 };
1818 enum LibvlcLogoNPObjectPropertyIds {
1819     ID_logo_delay,
1820     ID_logo_repeat,
1821     ID_logo_opacity,
1822     ID_logo_position,
1823     ID_logo_x,
1824     ID_logo_y,
1825 };
1826 COUNTNAMES(LibvlcLogoNPObject,propertyCount,propertyNames);
1827 static const unsigned char logo_idx[] = {
1828     libvlc_logo_delay,
1829     libvlc_logo_repeat,
1830     libvlc_logo_opacity,
1831     0,
1832     libvlc_logo_x,
1833     libvlc_logo_y,
1834 };
1835
1836 RuntimeNPObject::InvokeResult
1837 LibvlcLogoNPObject::getProperty(int index, NPVariant &result)
1838 {
1839     if( !isPluginRunning() )
1840         return INVOKERESULT_GENERIC_ERROR;
1841
1842     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1843     libvlc_exception_t ex;
1844     libvlc_exception_init(&ex);
1845     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1846     RETURN_ON_EXCEPTION(this,ex);
1847
1848     switch( index )
1849     {
1850     case ID_logo_delay:
1851     case ID_logo_repeat:
1852     case ID_logo_opacity:
1853     case ID_logo_x:
1854     case ID_logo_y:
1855
1856         INT32_TO_NPVARIANT(
1857             libvlc_video_get_logo_int(p_md, logo_idx[index], &ex), result);
1858
1859         RETURN_ON_EXCEPTION(this,ex);
1860         break;
1861
1862     case ID_logo_position:
1863         STRINGZ_TO_NPVARIANT( position_bynumber(
1864             libvlc_video_get_logo_int(p_md, libvlc_logo_position, &ex) ),
1865             result );
1866
1867         RETURN_ON_EXCEPTION(this,ex);
1868         break;
1869     default:
1870         return INVOKERESULT_GENERIC_ERROR;
1871     }
1872     return INVOKERESULT_NO_ERROR;
1873 }
1874
1875 RuntimeNPObject::InvokeResult
1876 LibvlcLogoNPObject::setProperty(int index, const NPVariant &value)
1877 {
1878     size_t i;
1879
1880     if( !isPluginRunning() )
1881         return INVOKERESULT_GENERIC_ERROR;
1882
1883     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1884     libvlc_exception_t ex;
1885     libvlc_exception_init(&ex);
1886
1887     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1888     RETURN_ON_EXCEPTION(this,ex);
1889
1890     switch( index )
1891     {
1892     case ID_logo_delay:
1893     case ID_logo_repeat:
1894     case ID_logo_opacity:
1895     case ID_logo_x:
1896     case ID_logo_y:
1897         if( !NPVARIANT_IS_INT32(value) )
1898             return INVOKERESULT_INVALID_VALUE;
1899
1900         libvlc_video_set_logo_int(p_md, logo_idx[index],
1901                                   NPVARIANT_TO_INT32( value ), &ex);
1902
1903         RETURN_ON_EXCEPTION(this,ex);
1904         break;
1905
1906     case ID_logo_position:
1907         if( !NPVARIANT_IS_STRING(value) ||
1908             !position_byname( NPVARIANT_TO_STRING(value).utf8characters, i ) )
1909             return INVOKERESULT_INVALID_VALUE;
1910
1911         libvlc_video_set_logo_int(p_md, libvlc_logo_position, i, &ex);
1912
1913         RETURN_ON_EXCEPTION(this,ex);
1914         break;
1915     default:
1916         return INVOKERESULT_GENERIC_ERROR;
1917     }
1918     return INVOKERESULT_NO_ERROR;
1919 }
1920
1921
1922 const NPUTF8 * const LibvlcLogoNPObject::methodNames[] = {
1923     "enable",
1924     "disable",
1925     "file",
1926 };
1927 enum LibvlcLogoNPObjectMethodIds {
1928     ID_logo_enable,
1929     ID_logo_disable,
1930     ID_logo_file,
1931 };
1932 COUNTNAMES(LibvlcLogoNPObject,methodCount,methodNames);
1933
1934 RuntimeNPObject::InvokeResult
1935 LibvlcLogoNPObject::invoke(int index, const NPVariant *args,
1936                            uint32_t argCount, NPVariant &result)
1937 {
1938     char *buf, *h;
1939     size_t i, len;
1940
1941     if( !isPluginRunning() )
1942         return INVOKERESULT_GENERIC_ERROR;
1943
1944     libvlc_exception_t ex;
1945     libvlc_exception_init(&ex);
1946     libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD(&ex);
1947     RETURN_ON_EXCEPTION(this,ex);
1948
1949     switch( index )
1950     {
1951     case ID_logo_enable:
1952     case ID_logo_disable:
1953         if( argCount != 0 )
1954             return INVOKERESULT_GENERIC_ERROR;
1955
1956         libvlc_video_set_logo_int(p_md, libvlc_logo_enable,
1957                                   index != ID_logo_disable, &ex);
1958         RETURN_ON_EXCEPTION(this,ex);
1959         VOID_TO_NPVARIANT(result);
1960         break;
1961
1962     case ID_logo_file:
1963         if( argCount == 0 )
1964             return INVOKERESULT_GENERIC_ERROR;
1965
1966         for( len=0,i=0;i<argCount;++i )
1967         {
1968             if( !NPVARIANT_IS_STRING(args[i]) )
1969                 return INVOKERESULT_INVALID_VALUE;
1970             len+=NPVARIANT_TO_STRING(args[i]).utf8length+1;
1971         }
1972
1973         buf = (char *)malloc( len+1 );
1974         if( !buf )
1975             return INVOKERESULT_OUT_OF_MEMORY;
1976
1977         for( h=buf,i=0;i<argCount;++i )
1978         {
1979             if(i) *h++=';';
1980             len=NPVARIANT_TO_STRING(args[i]).utf8length;
1981             memcpy(h,NPVARIANT_TO_STRING(args[i]).utf8characters,len);
1982             h+=len;
1983         }
1984         *h='\0';
1985
1986         libvlc_video_set_logo_string(p_md, libvlc_logo_file, buf, &ex);
1987         free( buf );
1988         RETURN_ON_EXCEPTION(this,ex);
1989         VOID_TO_NPVARIANT(result);
1990         break;
1991     default:
1992         return INVOKERESULT_NO_SUCH_METHOD;
1993     }
1994     return INVOKERESULT_NO_ERROR;
1995 }
1996
1997
1998 const NPUTF8 * const LibvlcDeinterlaceNPObject::propertyNames[] = {
1999 };
2000 enum LibvlcDeinterlaceNPObjectPropertyIds {
2001 };
2002 COUNTNAMES(LibvlcDeinterlaceNPObject,propertyCount,propertyNames);
2003
2004 RuntimeNPObject::InvokeResult
2005 LibvlcDeinterlaceNPObject::getProperty(int index, NPVariant &result)
2006 {
2007     return INVOKERESULT_GENERIC_ERROR;
2008 }
2009
2010 RuntimeNPObject::InvokeResult
2011 LibvlcDeinterlaceNPObject::setProperty(int index, const NPVariant &value)
2012 {
2013     return INVOKERESULT_GENERIC_ERROR;
2014 }
2015
2016
2017 const NPUTF8 * const LibvlcDeinterlaceNPObject::methodNames[] = {
2018     "enable",
2019     "disable",
2020 };
2021 enum LibvlcDeinterlaceNPObjectMethodIds {
2022     ID_deint_enable,
2023     ID_deint_disable,
2024 };
2025 COUNTNAMES(LibvlcDeinterlaceNPObject,methodCount,methodNames);
2026
2027 RuntimeNPObject::InvokeResult
2028 LibvlcDeinterlaceNPObject::invoke(int index, const NPVariant *args,
2029                            uint32_t argCount, NPVariant &result)
2030 {
2031     char *psz;
2032
2033     if( !isPluginRunning() )
2034         return INVOKERESULT_GENERIC_ERROR;
2035
2036     libvlc_exception_t ex;
2037     libvlc_exception_init(&ex);
2038     libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD(&ex);
2039     RETURN_ON_EXCEPTION(this,ex);
2040
2041     switch( index )
2042     {
2043     case ID_deint_disable:
2044         libvlc_video_set_deinterlace(p_md, 0, "", &ex);
2045         RETURN_ON_EXCEPTION(this,ex);
2046         break;
2047
2048     case ID_deint_enable:
2049         if( argCount != 1 || !NPVARIANT_IS_STRING( args[0] ) )
2050             return INVOKERESULT_INVALID_VALUE;
2051
2052         psz = stringValue( NPVARIANT_TO_STRING( args[0] ) );
2053         libvlc_video_set_deinterlace(p_md, 1, psz, &ex);
2054         free(psz);
2055         RETURN_ON_EXCEPTION(this,ex);
2056         break;
2057
2058     default:
2059         return INVOKERESULT_NO_SUCH_METHOD;
2060     }
2061     return INVOKERESULT_NO_ERROR;
2062 }
2063
2064
2065
2066 /*
2067 ** implementation of libvlc event object
2068 */
2069
2070 const NPUTF8 * const LibvlcEventNPObject::propertyNames[] =
2071 {
2072 };
2073
2074 enum LibvlcEventNPObjectPropertyIds
2075 {
2076 };
2077 COUNTNAMES(LibvlcEventNPObject,propertyCount,propertyNames);
2078
2079 const NPUTF8 * const LibvlcEventNPObject::methodNames[] =
2080 {
2081     "addListener",
2082     "removeListeners",
2083 };
2084 COUNTNAMES(LibvlcEventNPObject,methodCount,methodNames);
2085
2086 enum LibvlcEventNPObjectMethodIds
2087 {
2088     ID_event_addListener,
2089     ID_event_removeListeners,
2090 };
2091
2092 bool LibvlcEventNPObject::parseArgs(const NPVariant *args, uint32_t argCount,
2093                                     eventtypes_bitmap_t &eventToGet)
2094 {
2095     if (argCount > 2)
2096         eventToGet.clear();
2097
2098     for (int argIndex = 2; argIndex < argCount; argIndex++)
2099     {
2100         if (NPVARIANT_IS_STRING(args[argIndex]))
2101         {
2102             if (!eventToGet.add_event(NPVARIANT_TO_STRING(args[argIndex]).utf8characters))
2103                 return false;
2104         }
2105         else if (NPVARIANT_IS_OBJECT(args[argIndex]))
2106         {
2107             if (!parseEventArray(NPVARIANT_TO_OBJECT(args[argIndex]), eventToGet, _instance))
2108                 return false;
2109         }
2110         else
2111             return false;
2112     }
2113     return true;
2114 }
2115
2116 RuntimeNPObject::InvokeResult
2117 LibvlcEventNPObject::invoke(int index, const NPVariant *args,
2118                             uint32_t argCount, NPVariant &result)
2119 {
2120     /* is plugin still running */
2121     if( isPluginRunning() )
2122     {
2123         libvlc_exception_t ex;
2124         libvlc_exception_init(&ex);
2125
2126         switch( index )
2127         {
2128             case ID_event_addListener:
2129                 if (argCount >= 2)
2130                 {
2131                     // Checks if the first argument is a NPObject
2132                     if (!NPVARIANT_IS_OBJECT(args[0]))
2133                         return INVOKERESULT_NO_SUCH_METHOD;
2134
2135                     // Checks if the browser has the NPAPI version 0.19 at least.
2136                     if (!VlcPlugin::canUseEventListener())
2137                     {
2138                       NPN_SetException(this, strdup(ERROR_API_VERSION));
2139                       return INVOKERESULT_GENERIC_ERROR;
2140                     }
2141
2142                     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
2143
2144                     // Gets the binary field corresponding to the events the
2145                     // listener must listen to if specified.
2146                     // Else, listen to all events.
2147                     eventtypes_bitmap_t eventToGet;
2148                     eventToGet.set_all_events();
2149
2150                     if (!parseArgs(args, argCount, eventToGet))
2151                     {
2152                         NPN_SetException(this, strdup(ERROR_EVENT_NOT_FOUND));
2153                         return INVOKERESULT_GENERIC_ERROR;
2154                     }
2155
2156                     NPObject *listener = NPVARIANT_TO_OBJECT(args[0]);
2157                     NPN_RetainObject(listener);
2158
2159                     EventListener *eventListener = new EventListener();
2160                     eventListener->listener = listener;
2161                     eventListener->id = copyNPVariant(args[1]);
2162                     eventListener->eventMap = eventToGet;
2163
2164                     p_plugin->eventToCatch.add_event(eventToGet);
2165
2166                     p_plugin->eventListeners.push_back(eventListener);
2167
2168                     return INVOKERESULT_NO_ERROR;
2169                 }
2170                 return INVOKERESULT_NO_SUCH_METHOD;
2171           case ID_event_removeListeners:
2172               if (argCount == 0)
2173               {
2174                   VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
2175                   p_plugin->eventListeners.clear();
2176                   p_plugin->eventToCatch.clear();
2177                   return INVOKERESULT_NO_ERROR;
2178               }
2179               return INVOKERESULT_NO_SUCH_METHOD;
2180           default:
2181               ;
2182         }
2183     }
2184     return INVOKERESULT_GENERIC_ERROR;
2185 }