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