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