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