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