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