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