73d198e1d2247f72b29064e2141b761b6639e3b9
[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(), &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_errmsg());
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     "none",
592 };
593 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
594
595 enum LibvlcInputNPObjectMethodIds
596 {
597     ID_none,
598 };
599
600 RuntimeNPObject::InvokeResult
601 LibvlcInputNPObject::invoke(int index, const NPVariant *args,
602                                     uint32_t argCount, NPVariant &result)
603 {
604     /* is plugin still running */
605     if( isPluginRunning() )
606     {
607         switch( index )
608         {
609             case ID_none:
610                 return INVOKERESULT_NO_SUCH_METHOD;
611             default:
612                 ;
613         }
614     }
615     return INVOKERESULT_GENERIC_ERROR;
616 }
617
618 /*
619 ** implementation of libvlc playlist items object
620 */
621
622 const NPUTF8 * const LibvlcPlaylistItemsNPObject::propertyNames[] =
623 {
624     "count",
625 };
626 COUNTNAMES(LibvlcPlaylistItemsNPObject,propertyCount,propertyNames);
627
628 enum LibvlcPlaylistItemsNPObjectPropertyIds
629 {
630     ID_playlistitems_count,
631 };
632
633 RuntimeNPObject::InvokeResult
634 LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
635 {
636     /* is plugin still running */
637     if( isPluginRunning() )
638     {
639         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
640         libvlc_exception_t ex;
641         libvlc_exception_init(&ex);
642
643         switch( index )
644         {
645             case ID_playlistitems_count:
646             {
647                 int val = p_plugin->playlist_count(&ex);
648                 RETURN_ON_EXCEPTION(this,ex);
649                 INT32_TO_NPVARIANT(val, result);
650                 return INVOKERESULT_NO_ERROR;
651             }
652             default:
653                 ;
654         }
655     }
656     return INVOKERESULT_GENERIC_ERROR;
657 }
658
659 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
660 {
661     "clear",
662     "remove",
663 };
664 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
665
666 enum LibvlcPlaylistItemsNPObjectMethodIds
667 {
668     ID_playlistitems_clear,
669     ID_playlistitems_remove,
670 };
671
672 RuntimeNPObject::InvokeResult
673 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
674                                     uint32_t argCount, NPVariant &result)
675 {
676     /* is plugin still running */
677     if( isPluginRunning() )
678     {
679         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
680         libvlc_exception_t ex;
681         libvlc_exception_init(&ex);
682
683         switch( index )
684         {
685             case ID_playlistitems_clear:
686                 if( argCount == 0 )
687                 {
688                     p_plugin->playlist_clear(&ex);
689                     RETURN_ON_EXCEPTION(this,ex);
690                     VOID_TO_NPVARIANT(result);
691                     return INVOKERESULT_NO_ERROR;
692                 }
693                 return INVOKERESULT_NO_SUCH_METHOD;
694             case ID_playlistitems_remove:
695                 if( (argCount == 1) && isNumberValue(args[0]) )
696                 {
697                     p_plugin->playlist_delete_item(numberValue(args[0]),&ex);
698                     RETURN_ON_EXCEPTION(this,ex);
699                     VOID_TO_NPVARIANT(result);
700                     return INVOKERESULT_NO_ERROR;
701                 }
702                 return INVOKERESULT_NO_SUCH_METHOD;
703             default:
704                 ;
705         }
706     }
707     return INVOKERESULT_GENERIC_ERROR;
708 }
709
710 /*
711 ** implementation of libvlc playlist object
712 */
713
714 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
715 {
716     // Why the isValid()?
717     if( isValid() && playlistItemsObj )
718         NPN_ReleaseObject(playlistItemsObj);
719 };
720
721 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
722 {
723     "itemCount", /* deprecated */
724     "isPlaying",
725     "items",
726 };
727 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
728
729 enum LibvlcPlaylistNPObjectPropertyIds
730 {
731     ID_playlist_itemcount,
732     ID_playlist_isplaying,
733     ID_playlist_items,
734 };
735
736 RuntimeNPObject::InvokeResult
737 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
738 {
739     /* is plugin still running */
740     if( isPluginRunning() )
741     {
742         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
743         libvlc_exception_t ex;
744         libvlc_exception_init(&ex);
745
746         switch( index )
747         {
748             case ID_playlist_itemcount: /* deprecated */
749             {
750                 int val = p_plugin->playlist_count(&ex);
751                 RETURN_ON_EXCEPTION(this,ex);
752                 INT32_TO_NPVARIANT(val, result);
753                 return INVOKERESULT_NO_ERROR;
754             }
755             case ID_playlist_isplaying:
756             {
757                 int val = p_plugin->playlist_isplaying(&ex);
758                 RETURN_ON_EXCEPTION(this,ex);
759                 BOOLEAN_TO_NPVARIANT(val, result);
760                 return INVOKERESULT_NO_ERROR;
761             }
762             case ID_playlist_items:
763             {
764                 // create child object in lazyman fashion to avoid
765                 // ownership problem with firefox
766                 if( ! playlistItemsObj )
767                     playlistItemsObj =
768                         NPN_CreateObject(_instance, RuntimeNPClass<
769                         LibvlcPlaylistItemsNPObject>::getClass());
770                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
771                 return INVOKERESULT_NO_ERROR;
772             }
773             default:
774                 ;
775         }
776     }
777     return INVOKERESULT_GENERIC_ERROR;
778 }
779
780 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
781 {
782     "add",
783     "play",
784     "playItem",
785     "togglePause",
786     "stop",
787     "next",
788     "prev",
789     "clear", /* deprecated */
790     "removeItem", /* deprecated */
791 };
792 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
793
794 enum LibvlcPlaylistNPObjectMethodIds
795 {
796     ID_playlist_add,
797     ID_playlist_play,
798     ID_playlist_playItem,
799     ID_playlist_togglepause,
800     ID_playlist_stop,
801     ID_playlist_next,
802     ID_playlist_prev,
803     ID_playlist_clear,
804     ID_playlist_removeitem
805 };
806
807 RuntimeNPObject::InvokeResult
808 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
809                                uint32_t argCount, NPVariant &result)
810 {
811     /* is plugin still running */
812     if( isPluginRunning() )
813     {
814         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
815         libvlc_exception_t ex;
816         libvlc_exception_init(&ex);
817
818         switch( index )
819         {
820             // XXX FIXME this needs squashing into something much smaller
821             case ID_playlist_add:
822             {
823                 if( (argCount < 1) || (argCount > 3) )
824                     return INVOKERESULT_NO_SUCH_METHOD;
825                 if( !NPVARIANT_IS_STRING(args[0]) )
826                     return INVOKERESULT_NO_SUCH_METHOD;
827
828                 // grab URL
829                 if( NPVARIANT_IS_NULL(args[0]) )
830                     return INVOKERESULT_NO_SUCH_METHOD;
831
832                 char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
833                 if( !s )
834                     return INVOKERESULT_OUT_OF_MEMORY;
835
836                 char *url = p_plugin->getAbsoluteURL(s);
837                 if( url )
838                     free(s);
839                 else
840                     // problem with combining url, use argument
841                     url = s;
842
843                 char *name = NULL;
844
845                 // grab name if available
846                 if( argCount > 1 )
847                 {
848                     if( NPVARIANT_IS_NULL(args[1]) )
849                     {
850                         // do nothing
851                     }
852                     else if( NPVARIANT_IS_STRING(args[1]) )
853                     {
854                         name = stringValue(NPVARIANT_TO_STRING(args[1]));
855                     }
856                     else
857                     {
858                         free(url);
859                         return INVOKERESULT_INVALID_VALUE;
860                     }
861                 }
862
863                 int i_options = 0;
864                 char** ppsz_options = NULL;
865
866                 // grab options if available
867                 if( argCount > 2 )
868                 {
869                     if( NPVARIANT_IS_NULL(args[2]) )
870                     {
871                         // do nothing
872                     }
873                     else if( NPVARIANT_IS_STRING(args[2]) )
874                     {
875                         parseOptions(NPVARIANT_TO_STRING(args[2]),
876                                      &i_options, &ppsz_options);
877
878                     }
879                     else if( NPVARIANT_IS_OBJECT(args[2]) )
880                     {
881                         parseOptions(NPVARIANT_TO_OBJECT(args[2]),
882                                      &i_options, &ppsz_options);
883                     }
884                     else
885                     {
886                         free(url);
887                         free(name);
888                         return INVOKERESULT_INVALID_VALUE;
889                     }
890                 }
891
892                 int item = p_plugin->playlist_add_extended_untrusted(url, name,
893                       i_options, const_cast<const char **>(ppsz_options), &ex);
894                 free(url);
895                 free(name);
896                 for( int i=0; i< i_options; ++i )
897                 {
898                     free(ppsz_options[i]);
899                 }
900                 free(ppsz_options);
901
902                 RETURN_ON_EXCEPTION(this,ex);
903                 INT32_TO_NPVARIANT(item, result);
904                 return INVOKERESULT_NO_ERROR;
905             }
906             case ID_playlist_play:
907                 if( argCount == 0 )
908                 {
909                     p_plugin->playlist_play(&ex);
910                     RETURN_ON_EXCEPTION(this,ex);
911                     VOID_TO_NPVARIANT(result);
912                     return INVOKERESULT_NO_ERROR;
913                 }
914                 return INVOKERESULT_NO_SUCH_METHOD;
915             case ID_playlist_playItem:
916                 if( (argCount == 1) && isNumberValue(args[0]) )
917                 {
918                     p_plugin->playlist_play_item(numberValue(args[0]),&ex);
919                     RETURN_ON_EXCEPTION(this,ex);
920                     VOID_TO_NPVARIANT(result);
921                     return INVOKERESULT_NO_ERROR;
922                 }
923                 return INVOKERESULT_NO_SUCH_METHOD;
924             case ID_playlist_togglepause:
925                 if( argCount == 0 )
926                 {
927                     p_plugin->playlist_pause(&ex);
928                     RETURN_ON_EXCEPTION(this,ex);
929                     VOID_TO_NPVARIANT(result);
930                     return INVOKERESULT_NO_ERROR;
931                 }
932                 return INVOKERESULT_NO_SUCH_METHOD;
933             case ID_playlist_stop:
934                 if( argCount == 0 )
935                 {
936                     p_plugin->playlist_stop(&ex);
937                     RETURN_ON_EXCEPTION(this,ex);
938                     VOID_TO_NPVARIANT(result);
939                     return INVOKERESULT_NO_ERROR;
940                 }
941                 return INVOKERESULT_NO_SUCH_METHOD;
942             case ID_playlist_next:
943                 if( argCount == 0 )
944                 {
945                     p_plugin->playlist_next(&ex);
946                     RETURN_ON_EXCEPTION(this,ex);
947                     VOID_TO_NPVARIANT(result);
948                     return INVOKERESULT_NO_ERROR;
949                 }
950                 return INVOKERESULT_NO_SUCH_METHOD;
951             case ID_playlist_prev:
952                 if( argCount == 0 )
953                 {
954                     p_plugin->playlist_prev(&ex);
955                     RETURN_ON_EXCEPTION(this,ex);
956                     VOID_TO_NPVARIANT(result);
957                     return INVOKERESULT_NO_ERROR;
958                 }
959                 return INVOKERESULT_NO_SUCH_METHOD;
960             case ID_playlist_clear: /* deprecated */
961                 if( argCount == 0 )
962                 {
963                     p_plugin->playlist_clear(&ex);
964                     RETURN_ON_EXCEPTION(this,ex);
965                     VOID_TO_NPVARIANT(result);
966                     return INVOKERESULT_NO_ERROR;
967                 }
968                 return INVOKERESULT_NO_SUCH_METHOD;
969             case ID_playlist_removeitem: /* deprecated */
970                 if( (argCount == 1) && isNumberValue(args[0]) )
971                 {
972                     p_plugin->playlist_delete_item(numberValue(args[0]), &ex);
973                     RETURN_ON_EXCEPTION(this,ex);
974                     VOID_TO_NPVARIANT(result);
975                     return INVOKERESULT_NO_ERROR;
976                 }
977                 return INVOKERESULT_NO_SUCH_METHOD;
978             default:
979                 ;
980         }
981     }
982     return INVOKERESULT_GENERIC_ERROR;
983 }
984
985 // XXX FIXME The new playlist_add creates a media instance and feeds it
986 // XXX FIXME these options one at a time, so this hunk of code does lots
987 // XXX FIXME of unnecessairy work. Break out something that can do one
988 // XXX FIXME option at a time and doesn't need to realloc().
989 // XXX FIXME Same for the other version of parseOptions.
990
991 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
992                                          int *i_options, char*** ppsz_options)
993 {
994     if( nps.utf8length )
995     {
996         char *s = stringValue(nps);
997         char *val = s;
998         if( val )
999         {
1000             long capacity = 16;
1001             char **options = (char **)malloc(capacity*sizeof(char *));
1002             if( options )
1003             {
1004                 int nOptions = 0;
1005
1006                 char *end = val + nps.utf8length;
1007                 while( val < end )
1008                 {
1009                     // skip leading blanks
1010                     while( (val < end)
1011                         && ((*val == ' ' ) || (*val == '\t')) )
1012                         ++val;
1013
1014                     char *start = val;
1015                     // skip till we get a blank character
1016                     while( (val < end)
1017                         && (*val != ' ' )
1018                         && (*val != '\t') )
1019                     {
1020                         char c = *(val++);
1021                         if( ('\'' == c) || ('"' == c) )
1022                         {
1023                             // skip till end of string
1024                             while( (val < end) && (*(val++) != c ) );
1025                         }
1026                     }
1027
1028                     if( val > start )
1029                     {
1030                         if( nOptions == capacity )
1031                         {
1032                             capacity += 16;
1033                             char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1034                             if( ! moreOptions )
1035                             {
1036                                 /* failed to allocate more memory */
1037                                 free(s);
1038                                 /* return what we got so far */
1039                                 *i_options = nOptions;
1040                                 *ppsz_options = options;
1041                                 return;
1042                             }
1043                             options = moreOptions;
1044                         }
1045                         *(val++) = '\0';
1046                         options[nOptions++] = strdup(start);
1047                     }
1048                     else
1049                         // must be end of string
1050                         break;
1051                 }
1052                 *i_options = nOptions;
1053                 *ppsz_options = options;
1054             }
1055             free(s);
1056         }
1057     }
1058 }
1059
1060 // XXX FIXME See comment at the other parseOptions variant.
1061 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
1062                                           char*** ppsz_options)
1063 {
1064     /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1065
1066     NPVariant value;
1067
1068     /* we are expecting to have a Javascript Array object */
1069     NPIdentifier propId = NPN_GetStringIdentifier("length");
1070     if( NPN_GetProperty(_instance, obj, propId, &value) )
1071     {
1072         int count = numberValue(value);
1073         NPN_ReleaseVariantValue(&value);
1074
1075         if( count )
1076         {
1077             long capacity = 16;
1078             char **options = (char **)malloc(capacity*sizeof(char *));
1079             if( options )
1080             {
1081                 int nOptions = 0;
1082
1083                 while( nOptions < count )
1084                 {
1085                     propId = NPN_GetIntIdentifier(nOptions);
1086                     if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1087                         /* return what we got so far */
1088                         break;
1089
1090                     if( ! NPVARIANT_IS_STRING(value) )
1091                     {
1092                         /* return what we got so far */
1093                         NPN_ReleaseVariantValue(&value);
1094                         break;
1095                     }
1096
1097                     if( nOptions == capacity )
1098                     {
1099                         capacity += 16;
1100                         char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1101                         if( ! moreOptions )
1102                         {
1103                             /* failed to allocate more memory */
1104                             NPN_ReleaseVariantValue(&value);
1105                             /* return what we got so far */
1106                             *i_options = nOptions;
1107                             *ppsz_options = options;
1108                             break;
1109                         }
1110                         options = moreOptions;
1111                     }
1112
1113                     options[nOptions++] = stringValue(value);
1114                     NPN_ReleaseVariantValue(&value);
1115                 }
1116                 *i_options = nOptions;
1117                 *ppsz_options = options;
1118             }
1119         }
1120     }
1121 }
1122
1123 /*
1124 ** implementation of libvlc subtitle object
1125 */
1126
1127 const NPUTF8 * const LibvlcSubtitleNPObject::propertyNames[] =
1128 {
1129     "track",
1130     "count",
1131 };
1132
1133 enum LibvlcSubtitleNPObjectPropertyIds
1134 {
1135     ID_subtitle_track,
1136     ID_subtitle_count,
1137 };
1138 COUNTNAMES(LibvlcSubtitleNPObject,propertyCount,propertyNames);
1139
1140 RuntimeNPObject::InvokeResult
1141 LibvlcSubtitleNPObject::getProperty(int index, NPVariant &result)
1142 {
1143     /* is plugin still running */
1144     if( isPluginRunning() )
1145     {
1146         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1147         libvlc_exception_t ex;
1148         libvlc_exception_init(&ex);
1149
1150         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1151         RETURN_ON_EXCEPTION(this,ex);
1152
1153         switch( index )
1154         {
1155             case ID_subtitle_track:
1156             {
1157                 /* get the current subtitle ID */
1158                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1159                 RETURN_ON_EXCEPTION(this,ex);
1160                 /* return it */
1161                 INT32_TO_NPVARIANT(i_spu, result);
1162                 return INVOKERESULT_NO_ERROR;
1163             }
1164             case ID_subtitle_count:
1165             {
1166                 /* get the number of subtitles available */
1167                 int i_spu = libvlc_video_get_spu_count(p_md, &ex);
1168                 RETURN_ON_EXCEPTION(this,ex);
1169                 /* return it */
1170                 INT32_TO_NPVARIANT(i_spu, result);
1171                 return INVOKERESULT_NO_ERROR;
1172             }
1173         }
1174     }
1175     return INVOKERESULT_GENERIC_ERROR;
1176 }
1177
1178 RuntimeNPObject::InvokeResult
1179 LibvlcSubtitleNPObject::setProperty(int index, const NPVariant &value)
1180 {
1181     /* is plugin still running */
1182     if( isPluginRunning() )
1183     {
1184         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1185         libvlc_exception_t ex;
1186         libvlc_exception_init(&ex);
1187
1188         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1189         RETURN_ON_EXCEPTION(this,ex);
1190
1191         switch( index )
1192         {
1193             case ID_subtitle_track:
1194             {
1195                 if( isNumberValue(value) )
1196                 {
1197                     /* set the new subtitle track to show */
1198                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1199                     RETURN_ON_EXCEPTION(this,ex);
1200
1201                     return INVOKERESULT_NO_ERROR;
1202                 }
1203                 return INVOKERESULT_INVALID_VALUE;
1204             }
1205         }
1206     }
1207     return INVOKERESULT_GENERIC_ERROR;
1208 }
1209
1210 const NPUTF8 * const LibvlcSubtitleNPObject::methodNames[] =
1211 {
1212     "description"
1213 };
1214 COUNTNAMES(LibvlcSubtitleNPObject,methodCount,methodNames);
1215
1216 enum LibvlcSubtitleNPObjectMethodIds
1217 {
1218     ID_subtitle_description
1219 };
1220
1221 RuntimeNPObject::InvokeResult
1222 LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
1223                             uint32_t argCount, NPVariant &result)
1224 {
1225     /* is plugin still running */
1226     if( isPluginRunning() )
1227     {
1228         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1229         libvlc_exception_t ex;
1230         libvlc_exception_init(&ex);
1231
1232         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1233         RETURN_ON_EXCEPTION(this,ex);
1234
1235         switch( index )
1236         {
1237             case ID_subtitle_description:
1238             {
1239                 if( argCount == 1)
1240                 {
1241                     char *psz_name;
1242                     int i_spuID, i_limit, i;
1243                     libvlc_track_description_t *p_spuDesc;
1244
1245                     /* get subtitles description */
1246                     p_spuDesc = libvlc_video_get_spu_description(p_md, &ex);
1247                     RETURN_ON_EXCEPTION(this,ex);
1248                     if( !p_spuDesc )
1249                         return INVOKERESULT_GENERIC_ERROR;
1250
1251                     /* get the number of subtitle available */
1252                     i_limit = libvlc_video_get_spu_count(p_md, &ex);
1253                     RETURN_ON_EXCEPTION(this,ex);
1254
1255                     /* check if a number is given by the user
1256                      * and get the subtitle number */
1257                     if( isNumberValue(args[0]) )
1258                         i_spuID = numberValue(args[0]);
1259                     else
1260                         return INVOKERESULT_INVALID_VALUE;
1261
1262                     /* if bad number is given return invalid value */
1263                     if ( ( i_spuID > ( i_limit -1 ) ) || ( i_spuID < 0 ) )
1264                         return INVOKERESULT_INVALID_VALUE;
1265
1266                     /* get the good spuDesc */
1267                     for( i = 0 ; i < i_spuID ; i++ )
1268                     {
1269                         p_spuDesc = p_spuDesc->p_next;
1270                     }
1271                     psz_name = p_spuDesc->psz_name;
1272
1273                     /* return the name of the track chosen */
1274                     return invokeResultString(psz_name, result);
1275                 }
1276                 return INVOKERESULT_NO_SUCH_METHOD;
1277             }
1278             default:
1279                 return INVOKERESULT_NO_SUCH_METHOD;
1280         }
1281     }
1282     return INVOKERESULT_GENERIC_ERROR;
1283 }
1284
1285 /*
1286 ** implementation of libvlc video object
1287 */
1288
1289 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1290 {
1291     "fullscreen",
1292     "height",
1293     "width",
1294     "aspectRatio",
1295     "subtitle",
1296     "crop",
1297     "teletext",
1298     "marquee"
1299 };
1300
1301 enum LibvlcVideoNPObjectPropertyIds
1302 {
1303     ID_video_fullscreen,
1304     ID_video_height,
1305     ID_video_width,
1306     ID_video_aspectratio,
1307     ID_video_subtitle,
1308     ID_video_crop,
1309     ID_video_teletext,
1310     ID_video_marquee
1311 };
1312 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1313
1314 RuntimeNPObject::InvokeResult
1315 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1316 {
1317     /* is plugin still running */
1318     if( isPluginRunning() )
1319     {
1320         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1321         libvlc_exception_t ex;
1322         libvlc_exception_init(&ex);
1323
1324         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1325         RETURN_ON_EXCEPTION(this,ex);
1326
1327         switch( index )
1328         {
1329             case ID_video_fullscreen:
1330             {
1331                 int val = p_plugin->get_fullscreen(&ex);
1332                 RETURN_ON_EXCEPTION(this,ex);
1333                 BOOLEAN_TO_NPVARIANT(val, result);
1334                 return INVOKERESULT_NO_ERROR;
1335             }
1336             case ID_video_height:
1337             {
1338                 int val = libvlc_video_get_height(p_md, &ex);
1339                 RETURN_ON_EXCEPTION(this,ex);
1340                 INT32_TO_NPVARIANT(val, result);
1341                 return INVOKERESULT_NO_ERROR;
1342             }
1343             case ID_video_width:
1344             {
1345                 int val = libvlc_video_get_width(p_md, &ex);
1346                 RETURN_ON_EXCEPTION(this,ex);
1347                 INT32_TO_NPVARIANT(val, result);
1348                 return INVOKERESULT_NO_ERROR;
1349             }
1350             case ID_video_aspectratio:
1351             {
1352                 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1353                 RETURN_ON_EXCEPTION(this,ex);
1354                 if( !psz_aspect )
1355                     return INVOKERESULT_GENERIC_ERROR;
1356
1357                 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1358                 return INVOKERESULT_NO_ERROR;
1359             }
1360             case ID_video_subtitle:
1361             {
1362                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1363                 RETURN_ON_EXCEPTION(this,ex);
1364                 INT32_TO_NPVARIANT(i_spu, result);
1365                 return INVOKERESULT_NO_ERROR;
1366             }
1367             case ID_video_crop:
1368             {
1369                 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1370                 RETURN_ON_EXCEPTION(this,ex);
1371                 if( !psz_geometry )
1372                     return INVOKERESULT_GENERIC_ERROR;
1373
1374                 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1375                 return INVOKERESULT_NO_ERROR;
1376             }
1377             case ID_video_teletext:
1378             {
1379                 int i_page = libvlc_video_get_teletext(p_md, &ex);
1380                 RETURN_ON_EXCEPTION(this,ex);
1381                 INT32_TO_NPVARIANT(i_page, result);
1382                 return INVOKERESULT_NO_ERROR;
1383             }
1384             case ID_video_marquee:
1385             {
1386                 if( ! marqueeObj )
1387                     marqueeObj = NPN_CreateObject(_instance,
1388                              RuntimeNPClass<LibvlcMarqueeNPObject>::getClass());
1389                OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1390                 return INVOKERESULT_NO_ERROR;
1391             }
1392         }
1393     }
1394     return INVOKERESULT_GENERIC_ERROR;
1395 }
1396
1397 RuntimeNPObject::InvokeResult
1398 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1399 {
1400     /* is plugin still running */
1401     if( isPluginRunning() )
1402     {
1403         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1404         libvlc_exception_t ex;
1405         libvlc_exception_init(&ex);
1406
1407         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1408         RETURN_ON_EXCEPTION(this,ex);
1409
1410         switch( index )
1411         {
1412             case ID_video_fullscreen:
1413             {
1414                 if( ! NPVARIANT_IS_BOOLEAN(value) )
1415                 {
1416                     return INVOKERESULT_INVALID_VALUE;
1417                 }
1418
1419                 int val = NPVARIANT_TO_BOOLEAN(value);
1420                 p_plugin->set_fullscreen(val, &ex);
1421                 RETURN_ON_EXCEPTION(this,ex);
1422                 return INVOKERESULT_NO_ERROR;
1423             }
1424             case ID_video_aspectratio:
1425             {
1426                 char *psz_aspect = NULL;
1427
1428                 if( ! NPVARIANT_IS_STRING(value) )
1429                 {
1430                     return INVOKERESULT_INVALID_VALUE;
1431                 }
1432
1433                 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1434                 if( !psz_aspect )
1435                 {
1436                     return INVOKERESULT_GENERIC_ERROR;
1437                 }
1438
1439                 libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1440                 free(psz_aspect);
1441                 RETURN_ON_EXCEPTION(this,ex);
1442
1443                 return INVOKERESULT_NO_ERROR;
1444             }
1445             case ID_video_subtitle:
1446             {
1447                 if( isNumberValue(value) )
1448                 {
1449                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1450                     RETURN_ON_EXCEPTION(this,ex);
1451
1452                     return INVOKERESULT_NO_ERROR;
1453                 }
1454                 return INVOKERESULT_INVALID_VALUE;
1455             }
1456             case ID_video_crop:
1457             {
1458                 char *psz_geometry = NULL;
1459
1460                 if( ! NPVARIANT_IS_STRING(value) )
1461                 {
1462                     return INVOKERESULT_INVALID_VALUE;
1463                 }
1464
1465                 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1466                 if( !psz_geometry )
1467                 {
1468                     return INVOKERESULT_GENERIC_ERROR;
1469                 }
1470
1471                 libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
1472                 free(psz_geometry);
1473                 RETURN_ON_EXCEPTION(this,ex);
1474
1475                 return INVOKERESULT_NO_ERROR;
1476             }
1477             case ID_video_teletext:
1478             {
1479                 if( isNumberValue(value) )
1480                 {
1481                     libvlc_video_set_teletext(p_md, numberValue(value), &ex);
1482                     RETURN_ON_EXCEPTION(this,ex);
1483
1484                     return INVOKERESULT_NO_ERROR;
1485                 }
1486                 return INVOKERESULT_INVALID_VALUE;
1487             }
1488         }
1489     }
1490     return INVOKERESULT_GENERIC_ERROR;
1491 }
1492
1493 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1494 {
1495     "toggleFullscreen",
1496     "toggleTeletext",
1497     "deinterlaceEnable",
1498     "deinterlaceDisable"
1499 };
1500 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1501
1502 enum LibvlcVideoNPObjectMethodIds
1503 {
1504     ID_video_togglefullscreen,
1505     ID_video_toggleteletext,
1506     ID_video_deinterlaceenable,
1507     ID_video_deinterlacedisable
1508 };
1509
1510 RuntimeNPObject::InvokeResult
1511 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1512                             uint32_t argCount, NPVariant &result)
1513 {
1514     /* is plugin still running */
1515     if( isPluginRunning() )
1516     {
1517         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1518         libvlc_exception_t ex;
1519         libvlc_exception_init(&ex);
1520
1521         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1522         RETURN_ON_EXCEPTION(this,ex);
1523
1524         switch( index )
1525         {
1526             case ID_video_togglefullscreen:
1527             {
1528                 if( argCount == 0 )
1529                 {
1530                     p_plugin->toggle_fullscreen(&ex);
1531                     RETURN_ON_EXCEPTION(this,ex);
1532                     VOID_TO_NPVARIANT(result);
1533                     return INVOKERESULT_NO_ERROR;
1534                 }
1535                 return INVOKERESULT_NO_SUCH_METHOD;
1536             }
1537             case ID_video_toggleteletext:
1538             {
1539                 if( argCount == 0 )
1540                 {
1541                     libvlc_toggle_teletext(p_md, &ex);
1542                     RETURN_ON_EXCEPTION(this,ex);
1543                     VOID_TO_NPVARIANT(result);
1544                     return INVOKERESULT_NO_ERROR;
1545                 }
1546                 return INVOKERESULT_NO_SUCH_METHOD;
1547             }
1548             case ID_video_deinterlacedisable:
1549             {
1550                 libvlc_video_set_deinterlace(p_md, 0, "", &ex);
1551                 RETURN_ON_EXCEPTION(this,ex);
1552                 return INVOKERESULT_NO_ERROR;
1553             }
1554             case ID_video_deinterlaceenable:
1555             {
1556                 if(argCount == 1)
1557                 {
1558                     if( NPVARIANT_IS_STRING( args[0] ) )
1559                     {
1560                         /* get deinterlace mode from the user */
1561                         char *psz_mode = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1562                         /* enable deinterlace filter if possible */
1563                         libvlc_video_set_deinterlace(p_md, 1, psz_mode, &ex);
1564                         free(psz_mode);
1565                         RETURN_ON_EXCEPTION(this,ex);
1566                         return INVOKERESULT_NO_ERROR;
1567                     }
1568                     else
1569                     {
1570                         return INVOKERESULT_INVALID_VALUE;
1571                     }
1572                 }
1573             }
1574             default:
1575                 return INVOKERESULT_NO_SUCH_METHOD;
1576         }
1577     }
1578     return INVOKERESULT_GENERIC_ERROR;
1579 }
1580
1581 /*
1582 ** implementation of libvlc marquee object
1583 */
1584
1585 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1586 {
1587 };
1588
1589 enum LibvlcMarqueeNPObjectPropertyIds
1590 {
1591 };
1592 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
1593
1594 RuntimeNPObject::InvokeResult
1595 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1596 {
1597     /* is plugin still running */
1598     if( isPluginRunning() )
1599     {
1600         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1601         libvlc_exception_t ex;
1602         libvlc_exception_init(&ex);
1603
1604         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1605         RETURN_ON_EXCEPTION(this,ex);
1606
1607         switch( index )
1608         {
1609         }
1610     }
1611     return INVOKERESULT_GENERIC_ERROR;
1612 }
1613
1614 RuntimeNPObject::InvokeResult
1615 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1616 {
1617     /* is plugin still running */
1618     if( isPluginRunning() )
1619     {
1620         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1621         libvlc_exception_t ex;
1622         libvlc_exception_init(&ex);
1623
1624         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1625         RETURN_ON_EXCEPTION(this,ex);
1626
1627         switch( index )
1628         {
1629         }
1630     }
1631     return INVOKERESULT_GENERIC_ERROR;
1632 }
1633
1634 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1635 {
1636     "enable",
1637     "disable",
1638     "color",
1639     "opacity",
1640     "position",
1641     "refresh",
1642     "size",
1643     "text",
1644     "timeout",
1645     "x",
1646     "y"
1647 };
1648 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1649
1650 enum LibvlcMarqueeNPObjectMethodIds
1651 {
1652     ID_marquee_enable,
1653     ID_marquee_disable,
1654     ID_marquee_color,
1655     ID_marquee_opacity,
1656     ID_marquee_position,
1657     ID_marquee_refresh,
1658     ID_marquee_size,
1659     ID_marquee_text,
1660     ID_marquee_timeout,
1661     ID_marquee_x,
1662     ID_marquee_y
1663 };
1664
1665 RuntimeNPObject::InvokeResult
1666 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1667                             uint32_t argCount, NPVariant &result)
1668 {
1669     /* is plugin still running */
1670     if( isPluginRunning() )
1671     {
1672         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1673         libvlc_exception_t ex;
1674         libvlc_exception_init(&ex);
1675
1676         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1677         RETURN_ON_EXCEPTION(this,ex);
1678
1679         switch( index )
1680         {
1681             case ID_marquee_enable:
1682             {
1683                 libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Enabled, true, &ex);
1684                     RETURN_ON_EXCEPTION(this,ex);
1685                 return INVOKERESULT_NO_ERROR;
1686             }
1687             case ID_marquee_disable:
1688             {
1689                 libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Enabled, false, &ex);
1690                     RETURN_ON_EXCEPTION(this,ex);
1691                 return INVOKERESULT_NO_ERROR;
1692             }
1693             case ID_marquee_color:
1694             {
1695                 if( argCount == 1)
1696                 {
1697                     if( NPVARIANT_IS_INT32( args[0] ) )
1698                     {
1699                         int i_color = NPVARIANT_TO_INT32( args[0] );
1700                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Color, i_color, &ex);
1701                             RETURN_ON_EXCEPTION(this,ex);
1702                         return INVOKERESULT_NO_ERROR;
1703                     }
1704                     else
1705                         return INVOKERESULT_GENERIC_ERROR;
1706                 }
1707                 return INVOKERESULT_NO_SUCH_METHOD;
1708             }
1709             case ID_marquee_opacity:
1710             {
1711                 if( argCount == 1)
1712                 {
1713                     if( NPVARIANT_IS_INT32( args[0] ) )
1714                     {
1715                         int i_opacity = NPVARIANT_TO_INT32( args[0] );
1716                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Opacity, i_opacity, &ex);
1717                             RETURN_ON_EXCEPTION(this,ex);
1718                         return INVOKERESULT_NO_ERROR;
1719                     }
1720                     else
1721                         return INVOKERESULT_GENERIC_ERROR;
1722                 }
1723                 return INVOKERESULT_NO_SUCH_METHOD;
1724             }
1725             case ID_marquee_position:
1726             {
1727                 if( argCount == 1)
1728                 {
1729                     if( NPVARIANT_IS_INT32( args[0] ) )
1730                     {
1731                         int i_position = NPVARIANT_TO_INT32( args[0] );
1732                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Position, i_position, &ex);
1733                             RETURN_ON_EXCEPTION(this,ex);
1734                         return INVOKERESULT_NO_ERROR;
1735                     }
1736                     else
1737                         return INVOKERESULT_GENERIC_ERROR;
1738                 }
1739                 return INVOKERESULT_NO_SUCH_METHOD;
1740             }
1741             case ID_marquee_refresh:
1742             {
1743                 if( argCount == 1)
1744                 {
1745                     if( NPVARIANT_IS_INT32( args[0] ) )
1746                     {
1747                         int i_refresh = NPVARIANT_TO_INT32( args[0] );
1748                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Refresh, i_refresh, &ex);
1749                             RETURN_ON_EXCEPTION(this,ex);
1750                         return INVOKERESULT_NO_ERROR;
1751                     }
1752                     else
1753                         return INVOKERESULT_GENERIC_ERROR;
1754                 }
1755                 return INVOKERESULT_NO_SUCH_METHOD;
1756             }
1757             case ID_marquee_size:
1758             {
1759                 if( argCount == 1)
1760                 {
1761                     if( NPVARIANT_IS_INT32( args[0] ) )
1762                     {
1763                         int i_size = NPVARIANT_TO_INT32( args[0] );
1764                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Size, i_size, &ex);
1765                             RETURN_ON_EXCEPTION(this,ex);
1766                         return INVOKERESULT_NO_ERROR;
1767                     }
1768                     else
1769                         return INVOKERESULT_GENERIC_ERROR;
1770                 }
1771                 return INVOKERESULT_NO_SUCH_METHOD;
1772             }
1773             case ID_marquee_text:
1774             {
1775                 if( argCount == 1)
1776                 {
1777                     if( NPVARIANT_IS_STRING( args[0] ) )
1778                     {
1779                         char *psz_text = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1780                         libvlc_video_set_marquee_option_as_string(p_md, libvlc_marquee_Text, psz_text, &ex);
1781                             RETURN_ON_EXCEPTION(this,ex);
1782                         free(psz_text);
1783                         return INVOKERESULT_NO_ERROR;
1784                     }
1785                     else
1786                         return INVOKERESULT_GENERIC_ERROR;
1787                 }
1788                 return INVOKERESULT_NO_SUCH_METHOD;
1789             }
1790             case ID_marquee_timeout:
1791             {
1792                 if( argCount == 1)
1793                 {
1794                     if( NPVARIANT_IS_INT32( args[0] ) )
1795                     {
1796                         int i_timeout = NPVARIANT_TO_INT32( args[0] );
1797                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Timeout, i_timeout, &ex);
1798                             RETURN_ON_EXCEPTION(this,ex);
1799                         return INVOKERESULT_NO_ERROR;
1800                     }
1801                     else
1802                         return INVOKERESULT_GENERIC_ERROR;
1803                 }
1804                 return INVOKERESULT_NO_SUCH_METHOD;
1805             }
1806             case ID_marquee_x:
1807             {
1808                 if( argCount == 1)
1809                 {
1810                     if( NPVARIANT_IS_INT32( args[0] ) )
1811                     {
1812                         int i_x = NPVARIANT_TO_INT32( args[0] );
1813                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_X, i_x, &ex);
1814                             RETURN_ON_EXCEPTION(this,ex);
1815                         return INVOKERESULT_NO_ERROR;
1816                     }
1817                     else
1818                         return INVOKERESULT_GENERIC_ERROR;
1819                 }
1820                 return INVOKERESULT_NO_SUCH_METHOD;
1821             }
1822             case ID_marquee_y:
1823             {
1824                 if( argCount == 1)
1825                 {
1826                     if( NPVARIANT_IS_INT32( args[0] ) )
1827                     {
1828                         int i_y = NPVARIANT_TO_INT32( args[0] );
1829                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Y, i_y, &ex);
1830                             RETURN_ON_EXCEPTION(this,ex);
1831                         return INVOKERESULT_NO_ERROR;
1832                     }
1833                     else
1834                         return INVOKERESULT_GENERIC_ERROR;
1835                 }
1836                 return INVOKERESULT_NO_SUCH_METHOD;
1837             }
1838             default:
1839                 return INVOKERESULT_NO_SUCH_METHOD;
1840         }
1841     }
1842     return INVOKERESULT_GENERIC_ERROR;
1843 }