Moz-Plugin: Marquee JS Bindings
[vlc.git] / projects / mozilla / control / npolibvlc.cpp
1 /*****************************************************************************
2  * npolibvlc.cpp: official Javascript APIs
3  *****************************************************************************
4  * Copyright (C) 2002-2009 the VideoLAN team
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *          JP Dinger <jpd@m2x.nl>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "config.h"
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29
30 /* Mozilla stuff */
31 #ifdef HAVE_MOZILLA_CONFIG_H
32 #   include <mozilla-config.h>
33 #endif
34
35 #include "vlcplugin.h"
36 #include "npolibvlc.h"
37
38 /*
39 ** Local helper macros and function
40 */
41 #define COUNTNAMES(a,b,c) const int a::b = sizeof(a::c)/sizeof(NPUTF8 *)
42 #define RETURN_ON_EXCEPTION(this,ex) \
43     do { if( libvlc_exception_raised(&ex) ) \
44     { \
45         NPN_SetException(this, libvlc_exception_get_message(&ex)); \
46         libvlc_exception_clear(&ex); \
47         return INVOKERESULT_GENERIC_ERROR; \
48     } } while(false)
49
50 /*
51 ** implementation of libvlc root object
52 */
53
54 LibvlcRootNPObject::~LibvlcRootNPObject()
55 {
56     /*
57     ** When the plugin is destroyed, firefox takes it upon itself to
58     ** destroy all 'live' script objects and ignores refcounting.
59     ** Therefore we cannot safely assume that refcounting will control
60     ** lifespan of objects. Hence they are only lazily created on
61     ** request, so that firefox can take ownership, and are not released
62     ** when the plugin is destroyed.
63     */
64     if( isValid() )
65     {
66         if( audioObj    ) NPN_ReleaseObject(audioObj);
67         if( inputObj    ) NPN_ReleaseObject(inputObj);
68         if( playlistObj ) NPN_ReleaseObject(playlistObj);
69         if( videoObj    ) NPN_ReleaseObject(videoObj);
70     }
71 }
72
73 const NPUTF8 * const LibvlcRootNPObject::propertyNames[] =
74 {
75     "audio",
76     "input",
77     "playlist",
78     "subtitle",
79     "video",
80     "VersionInfo",
81 };
82 COUNTNAMES(LibvlcRootNPObject,propertyCount,propertyNames);
83
84 enum LibvlcRootNPObjectPropertyIds
85 {
86     ID_root_audio = 0,
87     ID_root_input,
88     ID_root_playlist,
89     ID_root_subtitle,
90     ID_root_video,
91     ID_root_VersionInfo,
92 };
93
94 RuntimeNPObject::InvokeResult
95 LibvlcRootNPObject::getProperty(int index, NPVariant &result)
96 {
97     /* is plugin still running */
98     if( isPluginRunning() )
99     {
100         switch( index )
101         {
102             case ID_root_audio:
103                 // create child object in lazyman fashion to avoid
104                 // ownership problem with firefox
105                 if( ! audioObj )
106                     audioObj = NPN_CreateObject(_instance,
107                              RuntimeNPClass<LibvlcAudioNPObject>::getClass());
108                 OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result);
109                 return INVOKERESULT_NO_ERROR;
110             case ID_root_input:
111                 // create child object in lazyman fashion to avoid
112                 // ownership problem with firefox
113                 if( ! inputObj )
114                     inputObj = NPN_CreateObject(_instance,
115                              RuntimeNPClass<LibvlcInputNPObject>::getClass());
116                 OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), result);
117                 return INVOKERESULT_NO_ERROR;
118             case ID_root_playlist:
119                 // create child object in lazyman fashion to avoid
120                 // ownership problem with firefox
121                 if( ! playlistObj )
122                     playlistObj = NPN_CreateObject(_instance,
123                           RuntimeNPClass<LibvlcPlaylistNPObject>::getClass());
124                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), result);
125                 return INVOKERESULT_NO_ERROR;
126             case ID_root_subtitle:
127                 // create child object in lazyman fashion to avoid
128                 // ownership problem with firefox
129                 if( ! subtitleObj )
130                     subtitleObj = NPN_CreateObject(_instance,
131                              RuntimeNPClass<LibvlcSubtitleNPObject>::getClass());
132                 OBJECT_TO_NPVARIANT(NPN_RetainObject(subtitleObj), result);
133                 return INVOKERESULT_NO_ERROR;
134             case ID_root_video:
135                 // create child object in lazyman fashion to avoid
136                 // ownership problem with firefox
137                 if( ! videoObj )
138                     videoObj = NPN_CreateObject(_instance,
139                              RuntimeNPClass<LibvlcVideoNPObject>::getClass());
140                 OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result);
141                 return INVOKERESULT_NO_ERROR;
142             case ID_root_VersionInfo:
143                 return invokeResultString(libvlc_get_version(),result);
144             default:
145                 ;
146         }
147     }
148     return INVOKERESULT_GENERIC_ERROR;
149 }
150
151 const NPUTF8 * const LibvlcRootNPObject::methodNames[] =
152 {
153     "versionInfo",
154 };
155 COUNTNAMES(LibvlcRootNPObject,methodCount,methodNames);
156
157 enum LibvlcRootNPObjectMethodIds
158 {
159     ID_root_versionInfo,
160 };
161
162 RuntimeNPObject::InvokeResult LibvlcRootNPObject::invoke(int index,
163                   const NPVariant *args, uint32_t argCount, NPVariant &result)
164 {
165     /* is plugin still running */
166     if( isPluginRunning() )
167     {
168         libvlc_exception_t ex;
169         libvlc_exception_init(&ex);
170
171         switch( index )
172         {
173             case ID_root_versionInfo:
174                 if( 0 != argCount )
175                     return INVOKERESULT_NO_SUCH_METHOD;
176                 return invokeResultString(libvlc_get_version(),result);
177             default:
178                 ;
179         }
180     }
181     return INVOKERESULT_GENERIC_ERROR;
182 }
183
184 /*
185 ** implementation of libvlc audio object
186 */
187
188 const NPUTF8 * const LibvlcAudioNPObject::propertyNames[] =
189 {
190     "mute",
191     "volume",
192     "track",
193     "count",
194     "channel",
195 };
196 COUNTNAMES(LibvlcAudioNPObject,propertyCount,propertyNames);
197
198 enum LibvlcAudioNPObjectPropertyIds
199 {
200     ID_audio_mute,
201     ID_audio_volume,
202     ID_audio_track,
203     ID_audio_count,
204     ID_audio_channel,
205 };
206
207 RuntimeNPObject::InvokeResult
208 LibvlcAudioNPObject::getProperty(int index, NPVariant &result)
209 {
210     /* is plugin still running */
211     if( isPluginRunning() )
212     {
213         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
214         libvlc_exception_t ex;
215         libvlc_exception_init(&ex);
216
217         switch( index )
218         {
219             case ID_audio_mute:
220             {
221                 bool muted = libvlc_audio_get_mute(p_plugin->getVLC(), &ex);
222                 RETURN_ON_EXCEPTION(this,ex);
223                 BOOLEAN_TO_NPVARIANT(muted, result);
224                 return INVOKERESULT_NO_ERROR;
225             }
226             case ID_audio_volume:
227             {
228                 int volume = libvlc_audio_get_volume(p_plugin->getVLC(), &ex);
229                 RETURN_ON_EXCEPTION(this,ex);
230                 INT32_TO_NPVARIANT(volume, result);
231                 return INVOKERESULT_NO_ERROR;
232             }
233             case ID_audio_track:
234             {
235                 libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
236                 RETURN_ON_EXCEPTION(this,ex);
237                 int track = libvlc_audio_get_track(p_md, &ex);
238                 RETURN_ON_EXCEPTION(this,ex);
239                 INT32_TO_NPVARIANT(track, result);
240                 return INVOKERESULT_NO_ERROR;
241             }
242             case ID_audio_count:
243             {
244                 libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
245                 RETURN_ON_EXCEPTION(this,ex);
246                 // get the number of audio track available
247                 int i_track = libvlc_audio_get_track_count(p_md, &ex);
248                 RETURN_ON_EXCEPTION(this,ex);
249                 // return it
250                 INT32_TO_NPVARIANT(i_track, result);
251                 return INVOKERESULT_NO_ERROR;
252             }
253             case ID_audio_channel:
254             {
255                 int channel = libvlc_audio_get_channel(p_plugin->getVLC(), &ex);
256                 RETURN_ON_EXCEPTION(this,ex);
257                 INT32_TO_NPVARIANT(channel, result);
258                 return INVOKERESULT_NO_ERROR;
259             }
260             default:
261                 ;
262         }
263     }
264     return INVOKERESULT_GENERIC_ERROR;
265 }
266
267 RuntimeNPObject::InvokeResult
268 LibvlcAudioNPObject::setProperty(int index, const NPVariant &value)
269 {
270     /* is plugin still running */
271     if( isPluginRunning() )
272     {
273         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
274         libvlc_exception_t ex;
275         libvlc_exception_init(&ex);
276
277         switch( index )
278         {
279             case ID_audio_mute:
280                 if( NPVARIANT_IS_BOOLEAN(value) )
281                 {
282                     libvlc_audio_set_mute(p_plugin->getVLC(),
283                                           NPVARIANT_TO_BOOLEAN(value), &ex);
284                     RETURN_ON_EXCEPTION(this,ex);
285                     return INVOKERESULT_NO_ERROR;
286                 }
287                 return INVOKERESULT_INVALID_VALUE;
288             case ID_audio_volume:
289                 if( isNumberValue(value) )
290                 {
291                     libvlc_audio_set_volume(p_plugin->getVLC(),
292                                             numberValue(value), &ex);
293                     RETURN_ON_EXCEPTION(this,ex);
294                     return INVOKERESULT_NO_ERROR;
295                 }
296                 return INVOKERESULT_INVALID_VALUE;
297             case ID_audio_track:
298                 if( isNumberValue(value) )
299                 {
300                     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
301                     RETURN_ON_EXCEPTION(this,ex);
302                     libvlc_audio_set_track(p_md, numberValue(value), &ex);
303                     RETURN_ON_EXCEPTION(this,ex);
304                     return INVOKERESULT_NO_ERROR;
305                 }
306                 return INVOKERESULT_INVALID_VALUE;
307             case ID_audio_channel:
308                 if( isNumberValue(value) )
309                 {
310                     libvlc_audio_set_channel(p_plugin->getVLC(),
311                                              numberValue(value), &ex);
312                     RETURN_ON_EXCEPTION(this,ex);
313                     return INVOKERESULT_NO_ERROR;
314                 }
315                 return INVOKERESULT_INVALID_VALUE;
316             default:
317                 ;
318         }
319     }
320     return INVOKERESULT_GENERIC_ERROR;
321 }
322
323 const NPUTF8 * const LibvlcAudioNPObject::methodNames[] =
324 {
325     "toggleMute",
326     "description",
327 };
328 COUNTNAMES(LibvlcAudioNPObject,methodCount,methodNames);
329
330 enum LibvlcAudioNPObjectMethodIds
331 {
332     ID_audio_togglemute,
333     ID_audio_description,
334 };
335
336 RuntimeNPObject::InvokeResult
337 LibvlcAudioNPObject::invoke(int index, const NPVariant *args,
338                             uint32_t argCount, NPVariant &result)
339 {
340     /* is plugin still running */
341     if( isPluginRunning() )
342     {
343         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
344         libvlc_exception_t ex;
345         libvlc_exception_init(&ex);
346
347         switch( index )
348         {
349             case ID_audio_togglemute:
350                 if( argCount == 0 )
351                 {
352                     libvlc_audio_toggle_mute(p_plugin->getVLC(), &ex);
353                     RETURN_ON_EXCEPTION(this,ex);
354                     VOID_TO_NPVARIANT(result);
355                     return INVOKERESULT_NO_ERROR;
356                 }
357                 return INVOKERESULT_NO_SUCH_METHOD;
358             case ID_audio_description:
359             {
360                 if( argCount == 1)
361                 {
362                     char *psz_name;
363                     int i_trackID, i_limit, i;
364                     libvlc_track_description_t *p_trackDesc;
365
366                     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
367                     RETURN_ON_EXCEPTION(this,ex);
368
369                     /* get tracks description */
370                     p_trackDesc = libvlc_audio_get_track_description(p_md, &ex);
371                     RETURN_ON_EXCEPTION(this,ex);
372                     if( !p_trackDesc )
373                         return INVOKERESULT_GENERIC_ERROR;
374
375                     /* get the number of track available */
376                     i_limit = libvlc_audio_get_track_count(p_md, &ex);
377                     RETURN_ON_EXCEPTION(this,ex);
378
379                     /* check if a number is given by the user
380                      * and get the track number */
381                     if( isNumberValue(args[0]) )
382                         i_trackID = numberValue(args[0]);
383                     else
384                         return INVOKERESULT_INVALID_VALUE;
385
386                     /* if bad number is given return invalid value */
387                     if ( ( i_trackID > ( i_limit - 1 ) ) || ( i_trackID < 0 ) )
388                         return INVOKERESULT_INVALID_VALUE;
389
390                     /* get the good trackDesc */
391                     for( i = 0 ; i < i_trackID ; i++ )
392                     {
393                         p_trackDesc = p_trackDesc->p_next;
394                     }
395                     psz_name = p_trackDesc->psz_name;
396
397                     /* display the name of the track chosen */
398                     return invokeResultString( psz_name, result );
399                 }
400                 return INVOKERESULT_NO_SUCH_METHOD;
401             }
402             default:
403                 ;
404         }
405     }
406     return INVOKERESULT_GENERIC_ERROR;
407 }
408
409 /*
410 ** implementation of libvlc input object
411 */
412
413 const NPUTF8 * const LibvlcInputNPObject::propertyNames[] =
414 {
415     "length",
416     "position",
417     "time",
418     "state",
419     "rate",
420     "fps",
421     "hasVout",
422 };
423 COUNTNAMES(LibvlcInputNPObject,propertyCount,propertyNames);
424
425 enum LibvlcInputNPObjectPropertyIds
426 {
427     ID_input_length,
428     ID_input_position,
429     ID_input_time,
430     ID_input_state,
431     ID_input_rate,
432     ID_input_fps,
433     ID_input_hasvout,
434 };
435
436 RuntimeNPObject::InvokeResult
437 LibvlcInputNPObject::getProperty(int index, NPVariant &result)
438 {
439     /* is plugin still running */
440     if( isPluginRunning() )
441     {
442         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
443         libvlc_exception_t ex;
444         libvlc_exception_init(&ex);
445
446         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
447         if( libvlc_exception_raised(&ex) )
448         {
449             if( index != ID_input_state )
450             {
451                 NPN_SetException(this, libvlc_exception_get_message(&ex));
452                 libvlc_exception_clear(&ex);
453                 return INVOKERESULT_GENERIC_ERROR;
454             }
455             else
456             {
457                 /* for input state, return CLOSED rather than an exception */
458                 INT32_TO_NPVARIANT(0, result);
459                 libvlc_exception_clear(&ex);
460                 return INVOKERESULT_NO_ERROR;
461             }
462         }
463
464         switch( index )
465         {
466             case ID_input_length:
467             {
468                 double val = (double)libvlc_media_player_get_length(p_md, &ex);
469                 RETURN_ON_EXCEPTION(this,ex);
470                 DOUBLE_TO_NPVARIANT(val, result);
471                 return INVOKERESULT_NO_ERROR;
472             }
473             case ID_input_position:
474             {
475                 double val = libvlc_media_player_get_position(p_md, &ex);
476                 RETURN_ON_EXCEPTION(this,ex);
477                 DOUBLE_TO_NPVARIANT(val, result);
478                 return INVOKERESULT_NO_ERROR;
479             }
480             case ID_input_time:
481             {
482                 double val = (double)libvlc_media_player_get_time(p_md, &ex);
483                 RETURN_ON_EXCEPTION(this,ex);
484                 DOUBLE_TO_NPVARIANT(val, result);
485                 return INVOKERESULT_NO_ERROR;
486             }
487             case ID_input_state:
488             {
489                 int val = libvlc_media_player_get_state(p_md, &ex);
490                 RETURN_ON_EXCEPTION(this,ex);
491                 INT32_TO_NPVARIANT(val, result);
492                 return INVOKERESULT_NO_ERROR;
493             }
494             case ID_input_rate:
495             {
496                 float val = libvlc_media_player_get_rate(p_md, &ex);
497                 RETURN_ON_EXCEPTION(this,ex);
498                 DOUBLE_TO_NPVARIANT(val, result);
499                 return INVOKERESULT_NO_ERROR;
500             }
501             case ID_input_fps:
502             {
503                 double val = libvlc_media_player_get_fps(p_md, &ex);
504                 RETURN_ON_EXCEPTION(this,ex);
505                 DOUBLE_TO_NPVARIANT(val, result);
506                 return INVOKERESULT_NO_ERROR;
507             }
508             case ID_input_hasvout:
509             {
510                 bool val = p_plugin->player_has_vout(&ex);
511                 RETURN_ON_EXCEPTION(this,ex);
512                 BOOLEAN_TO_NPVARIANT(val, result);
513                 return INVOKERESULT_NO_ERROR;
514             }
515             default:
516                 ;
517         }
518     }
519     return INVOKERESULT_GENERIC_ERROR;
520 }
521
522 RuntimeNPObject::InvokeResult
523 LibvlcInputNPObject::setProperty(int index, const NPVariant &value)
524 {
525     /* is plugin still running */
526     if( isPluginRunning() )
527     {
528         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
529         libvlc_exception_t ex;
530         libvlc_exception_init(&ex);
531
532         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
533         RETURN_ON_EXCEPTION(this,ex);
534
535         switch( index )
536         {
537             case ID_input_position:
538             {
539                 if( ! NPVARIANT_IS_DOUBLE(value) )
540                 {
541                     return INVOKERESULT_INVALID_VALUE;
542                 }
543
544                 float val = (float)NPVARIANT_TO_DOUBLE(value);
545                 libvlc_media_player_set_position(p_md, val, &ex);
546                 RETURN_ON_EXCEPTION(this,ex);
547                 return INVOKERESULT_NO_ERROR;
548             }
549             case ID_input_time:
550             {
551                 int64_t val;
552                 if( NPVARIANT_IS_INT32(value) )
553                     val = (int64_t)NPVARIANT_TO_INT32(value);
554                 else if( NPVARIANT_IS_DOUBLE(value) )
555                     val = (int64_t)NPVARIANT_TO_DOUBLE(value);
556                 else
557                 {
558                     return INVOKERESULT_INVALID_VALUE;
559                 }
560
561                 libvlc_media_player_set_time(p_md, val, &ex);
562                 RETURN_ON_EXCEPTION(this,ex);
563                 return INVOKERESULT_NO_ERROR;
564             }
565             case ID_input_rate:
566             {
567                 float val;
568                 if( NPVARIANT_IS_INT32(value) )
569                     val = (float)NPVARIANT_TO_INT32(value);
570                 else if( NPVARIANT_IS_DOUBLE(value) )
571                     val = (float)NPVARIANT_TO_DOUBLE(value);
572                 else
573                 {
574                     return INVOKERESULT_INVALID_VALUE;
575                 }
576
577                 libvlc_media_player_set_rate(p_md, val, &ex);
578                 RETURN_ON_EXCEPTION(this,ex);
579                 return INVOKERESULT_NO_ERROR;
580             }
581             default:
582                 ;
583         }
584     }
585     return INVOKERESULT_GENERIC_ERROR;
586 }
587
588 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =
589 {
590     /* no methods */
591 };
592
593 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
594
595 /*
596 ** implementation of libvlc playlist items object
597 */
598
599 const NPUTF8 * const LibvlcPlaylistItemsNPObject::propertyNames[] =
600 {
601     "count",
602 };
603 COUNTNAMES(LibvlcPlaylistItemsNPObject,propertyCount,propertyNames);
604
605 enum LibvlcPlaylistItemsNPObjectPropertyIds
606 {
607     ID_playlistitems_count,
608 };
609
610 RuntimeNPObject::InvokeResult
611 LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
612 {
613     /* is plugin still running */
614     if( isPluginRunning() )
615     {
616         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
617         libvlc_exception_t ex;
618         libvlc_exception_init(&ex);
619
620         switch( index )
621         {
622             case ID_playlistitems_count:
623             {
624                 int val = p_plugin->playlist_count(&ex);
625                 RETURN_ON_EXCEPTION(this,ex);
626                 INT32_TO_NPVARIANT(val, result);
627                 return INVOKERESULT_NO_ERROR;
628             }
629             default:
630                 ;
631         }
632     }
633     return INVOKERESULT_GENERIC_ERROR;
634 }
635
636 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
637 {
638     "clear",
639     "remove",
640 };
641 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
642
643 enum LibvlcPlaylistItemsNPObjectMethodIds
644 {
645     ID_playlistitems_clear,
646     ID_playlistitems_remove,
647 };
648
649 RuntimeNPObject::InvokeResult
650 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
651                                     uint32_t argCount, NPVariant &result)
652 {
653     /* is plugin still running */
654     if( isPluginRunning() )
655     {
656         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
657         libvlc_exception_t ex;
658         libvlc_exception_init(&ex);
659
660         switch( index )
661         {
662             case ID_playlistitems_clear:
663                 if( argCount == 0 )
664                 {
665                     p_plugin->playlist_clear(&ex);
666                     RETURN_ON_EXCEPTION(this,ex);
667                     VOID_TO_NPVARIANT(result);
668                     return INVOKERESULT_NO_ERROR;
669                 }
670                 return INVOKERESULT_NO_SUCH_METHOD;
671             case ID_playlistitems_remove:
672                 if( (argCount == 1) && isNumberValue(args[0]) )
673                 {
674                     p_plugin->playlist_delete_item(numberValue(args[0]),&ex);
675                     RETURN_ON_EXCEPTION(this,ex);
676                     VOID_TO_NPVARIANT(result);
677                     return INVOKERESULT_NO_ERROR;
678                 }
679                 return INVOKERESULT_NO_SUCH_METHOD;
680             default:
681                 ;
682         }
683     }
684     return INVOKERESULT_GENERIC_ERROR;
685 }
686
687 /*
688 ** implementation of libvlc playlist object
689 */
690
691 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
692 {
693     // Why the isValid()?
694     if( isValid() && playlistItemsObj )
695         NPN_ReleaseObject(playlistItemsObj);
696 };
697
698 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
699 {
700     "itemCount", /* deprecated */
701     "isPlaying",
702     "items",
703 };
704 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
705
706 enum LibvlcPlaylistNPObjectPropertyIds
707 {
708     ID_playlist_itemcount,
709     ID_playlist_isplaying,
710     ID_playlist_items,
711 };
712
713 RuntimeNPObject::InvokeResult
714 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
715 {
716     /* is plugin still running */
717     if( isPluginRunning() )
718     {
719         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
720         libvlc_exception_t ex;
721         libvlc_exception_init(&ex);
722
723         switch( index )
724         {
725             case ID_playlist_itemcount: /* deprecated */
726             {
727                 int val = p_plugin->playlist_count(&ex);
728                 RETURN_ON_EXCEPTION(this,ex);
729                 INT32_TO_NPVARIANT(val, result);
730                 return INVOKERESULT_NO_ERROR;
731             }
732             case ID_playlist_isplaying:
733             {
734                 int val = p_plugin->playlist_isplaying(&ex);
735                 RETURN_ON_EXCEPTION(this,ex);
736                 BOOLEAN_TO_NPVARIANT(val, result);
737                 return INVOKERESULT_NO_ERROR;
738             }
739             case ID_playlist_items:
740             {
741                 // create child object in lazyman fashion to avoid
742                 // ownership problem with firefox
743                 if( ! playlistItemsObj )
744                     playlistItemsObj =
745                         NPN_CreateObject(_instance, RuntimeNPClass<
746                         LibvlcPlaylistItemsNPObject>::getClass());
747                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
748                 return INVOKERESULT_NO_ERROR;
749             }
750             default:
751                 ;
752         }
753     }
754     return INVOKERESULT_GENERIC_ERROR;
755 }
756
757 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
758 {
759     "add",
760     "play",
761     "playItem",
762     "togglePause",
763     "stop",
764     "next",
765     "prev",
766     "clear", /* deprecated */
767     "removeItem", /* deprecated */
768 };
769 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
770
771 enum LibvlcPlaylistNPObjectMethodIds
772 {
773     ID_playlist_add,
774     ID_playlist_play,
775     ID_playlist_playItem,
776     ID_playlist_togglepause,
777     ID_playlist_stop,
778     ID_playlist_next,
779     ID_playlist_prev,
780     ID_playlist_clear,
781     ID_playlist_removeitem
782 };
783
784 RuntimeNPObject::InvokeResult
785 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
786                                uint32_t argCount, NPVariant &result)
787 {
788     /* is plugin still running */
789     if( isPluginRunning() )
790     {
791         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
792         libvlc_exception_t ex;
793         libvlc_exception_init(&ex);
794
795         switch( index )
796         {
797             // XXX FIXME this needs squashing into something much smaller
798             case ID_playlist_add:
799             {
800                 if( (argCount < 1) || (argCount > 3) )
801                     return INVOKERESULT_NO_SUCH_METHOD;
802                 if( !NPVARIANT_IS_STRING(args[0]) )
803                     return INVOKERESULT_NO_SUCH_METHOD;
804
805                 // grab URL
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                 }
1089                 *i_options = nOptions;
1090                 *ppsz_options = options;
1091             }
1092         }
1093     }
1094 }
1095
1096 /*
1097 ** implementation of libvlc subtitle object
1098 */
1099
1100 const NPUTF8 * const LibvlcSubtitleNPObject::propertyNames[] =
1101 {
1102     "track",
1103     "count",
1104 };
1105
1106 enum LibvlcSubtitleNPObjectPropertyIds
1107 {
1108     ID_subtitle_track,
1109     ID_subtitle_count,
1110 };
1111 COUNTNAMES(LibvlcSubtitleNPObject,propertyCount,propertyNames);
1112
1113 RuntimeNPObject::InvokeResult
1114 LibvlcSubtitleNPObject::getProperty(int index, NPVariant &result)
1115 {
1116     /* is plugin still running */
1117     if( isPluginRunning() )
1118     {
1119         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1120         libvlc_exception_t ex;
1121         libvlc_exception_init(&ex);
1122
1123         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1124         RETURN_ON_EXCEPTION(this,ex);
1125
1126         switch( index )
1127         {
1128             case ID_subtitle_track:
1129             {
1130                 /* get the current subtitle ID */
1131                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1132                 RETURN_ON_EXCEPTION(this,ex);
1133                 /* return it */
1134                 INT32_TO_NPVARIANT(i_spu, result);
1135                 return INVOKERESULT_NO_ERROR;
1136             }
1137             case ID_subtitle_count:
1138             {
1139                 /* get the number of subtitles available */
1140                 int i_spu = libvlc_video_get_spu_count(p_md, &ex);
1141                 RETURN_ON_EXCEPTION(this,ex);
1142                 /* return it */
1143                 INT32_TO_NPVARIANT(i_spu, result);
1144                 return INVOKERESULT_NO_ERROR;
1145             }
1146         }
1147     }
1148     return INVOKERESULT_GENERIC_ERROR;
1149 }
1150
1151 RuntimeNPObject::InvokeResult
1152 LibvlcSubtitleNPObject::setProperty(int index, const NPVariant &value)
1153 {
1154     /* is plugin still running */
1155     if( isPluginRunning() )
1156     {
1157         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1158         libvlc_exception_t ex;
1159         libvlc_exception_init(&ex);
1160
1161         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1162         RETURN_ON_EXCEPTION(this,ex);
1163
1164         switch( index )
1165         {
1166             case ID_subtitle_track:
1167             {
1168                 if( isNumberValue(value) )
1169                 {
1170                     /* set the new subtitle track to show */
1171                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1172                     RETURN_ON_EXCEPTION(this,ex);
1173
1174                     return INVOKERESULT_NO_ERROR;
1175                 }
1176                 return INVOKERESULT_INVALID_VALUE;
1177             }
1178         }
1179     }
1180     return INVOKERESULT_GENERIC_ERROR;
1181 }
1182
1183 const NPUTF8 * const LibvlcSubtitleNPObject::methodNames[] =
1184 {
1185     "description"
1186 };
1187 COUNTNAMES(LibvlcSubtitleNPObject,methodCount,methodNames);
1188
1189 enum LibvlcSubtitleNPObjectMethodIds
1190 {
1191     ID_subtitle_description
1192 };
1193
1194 RuntimeNPObject::InvokeResult
1195 LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
1196                             uint32_t argCount, NPVariant &result)
1197 {
1198     /* is plugin still running */
1199     if( isPluginRunning() )
1200     {
1201         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1202         libvlc_exception_t ex;
1203         libvlc_exception_init(&ex);
1204
1205         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1206         RETURN_ON_EXCEPTION(this,ex);
1207
1208         switch( index )
1209         {
1210             case ID_subtitle_description:
1211             {
1212                 if( argCount == 1)
1213                 {
1214                     char *psz_name;
1215                     int i_spuID, i_limit, i;
1216                     libvlc_track_description_t *p_spuDesc;
1217
1218                     /* get subtitles description */
1219                     p_spuDesc = libvlc_video_get_spu_description(p_md, &ex);
1220                     RETURN_ON_EXCEPTION(this,ex);
1221                     if( !p_spuDesc )
1222                         return INVOKERESULT_GENERIC_ERROR;
1223
1224                     /* get the number of subtitle available */
1225                     i_limit = libvlc_video_get_spu_count(p_md, &ex);
1226                     RETURN_ON_EXCEPTION(this,ex);
1227
1228                     /* check if a number is given by the user
1229                      * and get the subtitle number */
1230                     if( isNumberValue(args[0]) )
1231                         i_spuID = numberValue(args[0]);
1232                     else
1233                         return INVOKERESULT_INVALID_VALUE;
1234
1235                     /* if bad number is given return invalid value */
1236                     if ( ( i_spuID > ( i_limit -1 ) ) || ( i_spuID < 0 ) )
1237                         return INVOKERESULT_INVALID_VALUE;
1238
1239                     /* get the good spuDesc */
1240                     for( i = 0 ; i < i_spuID ; i++ )
1241                     {
1242                         p_spuDesc = p_spuDesc->p_next;
1243                     }
1244                     psz_name = p_spuDesc->psz_name;
1245
1246                     /* return the name of the track chosen */
1247                     return invokeResultString(psz_name, result);
1248                 }
1249                 return INVOKERESULT_NO_SUCH_METHOD;
1250             }
1251             default:
1252                 return INVOKERESULT_NO_SUCH_METHOD;
1253         }
1254     }
1255     return INVOKERESULT_GENERIC_ERROR;
1256 }
1257
1258 /*
1259 ** implementation of libvlc video object
1260 */
1261
1262 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1263 {
1264     "fullscreen",
1265     "height",
1266     "width",
1267     "aspectRatio",
1268     "subtitle",
1269     "crop",
1270     "teletext",
1271     "marquee"
1272 };
1273
1274 enum LibvlcVideoNPObjectPropertyIds
1275 {
1276     ID_video_fullscreen,
1277     ID_video_height,
1278     ID_video_width,
1279     ID_video_aspectratio,
1280     ID_video_subtitle,
1281     ID_video_crop,
1282     ID_video_teletext,
1283     ID_video_marquee
1284 };
1285 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1286
1287 RuntimeNPObject::InvokeResult
1288 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1289 {
1290     /* is plugin still running */
1291     if( isPluginRunning() )
1292     {
1293         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1294         libvlc_exception_t ex;
1295         libvlc_exception_init(&ex);
1296
1297         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1298         RETURN_ON_EXCEPTION(this,ex);
1299
1300         switch( index )
1301         {
1302             case ID_video_fullscreen:
1303             {
1304                 int val = p_plugin->get_fullscreen(&ex);
1305                 RETURN_ON_EXCEPTION(this,ex);
1306                 BOOLEAN_TO_NPVARIANT(val, result);
1307                 return INVOKERESULT_NO_ERROR;
1308             }
1309             case ID_video_height:
1310             {
1311                 int val = libvlc_video_get_height(p_md, &ex);
1312                 RETURN_ON_EXCEPTION(this,ex);
1313                 INT32_TO_NPVARIANT(val, result);
1314                 return INVOKERESULT_NO_ERROR;
1315             }
1316             case ID_video_width:
1317             {
1318                 int val = libvlc_video_get_width(p_md, &ex);
1319                 RETURN_ON_EXCEPTION(this,ex);
1320                 INT32_TO_NPVARIANT(val, result);
1321                 return INVOKERESULT_NO_ERROR;
1322             }
1323             case ID_video_aspectratio:
1324             {
1325                 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1326                 RETURN_ON_EXCEPTION(this,ex);
1327                 if( !psz_aspect )
1328                     return INVOKERESULT_GENERIC_ERROR;
1329
1330                 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1331                 return INVOKERESULT_NO_ERROR;
1332             }
1333             case ID_video_subtitle:
1334             {
1335                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1336                 RETURN_ON_EXCEPTION(this,ex);
1337                 INT32_TO_NPVARIANT(i_spu, result);
1338                 return INVOKERESULT_NO_ERROR;
1339             }
1340             case ID_video_crop:
1341             {
1342                 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1343                 RETURN_ON_EXCEPTION(this,ex);
1344                 if( !psz_geometry )
1345                     return INVOKERESULT_GENERIC_ERROR;
1346
1347                 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1348                 return INVOKERESULT_NO_ERROR;
1349             }
1350             case ID_video_teletext:
1351             {
1352                 int i_page = libvlc_video_get_teletext(p_md, &ex);
1353                 RETURN_ON_EXCEPTION(this,ex);
1354                 INT32_TO_NPVARIANT(i_page, result);
1355                 return INVOKERESULT_NO_ERROR;
1356             }
1357             case ID_video_marquee:
1358             {
1359                 if( ! marqueeObj )
1360                     marqueeObj = NPN_CreateObject(_instance,
1361                              RuntimeNPClass<LibvlcMarqueeNPObject>::getClass());
1362                OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1363                 return INVOKERESULT_NO_ERROR;
1364             }
1365         }
1366     }
1367     return INVOKERESULT_GENERIC_ERROR;
1368 }
1369
1370 RuntimeNPObject::InvokeResult
1371 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1372 {
1373     /* is plugin still running */
1374     if( isPluginRunning() )
1375     {
1376         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1377         libvlc_exception_t ex;
1378         libvlc_exception_init(&ex);
1379
1380         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1381         RETURN_ON_EXCEPTION(this,ex);
1382
1383         switch( index )
1384         {
1385             case ID_video_fullscreen:
1386             {
1387                 if( ! NPVARIANT_IS_BOOLEAN(value) )
1388                 {
1389                     return INVOKERESULT_INVALID_VALUE;
1390                 }
1391
1392                 int val = NPVARIANT_TO_BOOLEAN(value);
1393                 p_plugin->set_fullscreen(val, &ex);
1394                 RETURN_ON_EXCEPTION(this,ex);
1395                 return INVOKERESULT_NO_ERROR;
1396             }
1397             case ID_video_aspectratio:
1398             {
1399                 char *psz_aspect = NULL;
1400
1401                 if( ! NPVARIANT_IS_STRING(value) )
1402                 {
1403                     return INVOKERESULT_INVALID_VALUE;
1404                 }
1405
1406                 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1407                 if( !psz_aspect )
1408                 {
1409                     return INVOKERESULT_GENERIC_ERROR;
1410                 }
1411
1412                 libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1413                 free(psz_aspect);
1414                 RETURN_ON_EXCEPTION(this,ex);
1415
1416                 return INVOKERESULT_NO_ERROR;
1417             }
1418             case ID_video_subtitle:
1419             {
1420                 if( isNumberValue(value) )
1421                 {
1422                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1423                     RETURN_ON_EXCEPTION(this,ex);
1424
1425                     return INVOKERESULT_NO_ERROR;
1426                 }
1427                 return INVOKERESULT_INVALID_VALUE;
1428             }
1429             case ID_video_crop:
1430             {
1431                 char *psz_geometry = NULL;
1432
1433                 if( ! NPVARIANT_IS_STRING(value) )
1434                 {
1435                     return INVOKERESULT_INVALID_VALUE;
1436                 }
1437
1438                 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1439                 if( !psz_geometry )
1440                 {
1441                     return INVOKERESULT_GENERIC_ERROR;
1442                 }
1443
1444                 libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
1445                 free(psz_geometry);
1446                 RETURN_ON_EXCEPTION(this,ex);
1447
1448                 return INVOKERESULT_NO_ERROR;
1449             }
1450             case ID_video_teletext:
1451             {
1452                 if( isNumberValue(value) )
1453                 {
1454                     libvlc_video_set_teletext(p_md, numberValue(value), &ex);
1455                     RETURN_ON_EXCEPTION(this,ex);
1456
1457                     return INVOKERESULT_NO_ERROR;
1458                 }
1459                 return INVOKERESULT_INVALID_VALUE;
1460             }
1461         }
1462     }
1463     return INVOKERESULT_GENERIC_ERROR;
1464 }
1465
1466 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1467 {
1468     "toggleFullscreen",
1469     "toggleTeletext",
1470     "deinterlaceEnable",
1471     "deinterlaceDisable"
1472 };
1473 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1474
1475 enum LibvlcVideoNPObjectMethodIds
1476 {
1477     ID_video_togglefullscreen,
1478     ID_video_toggleteletext,
1479     ID_video_deinterlaceenable,
1480     ID_video_deinterlacedisable
1481 };
1482
1483 RuntimeNPObject::InvokeResult
1484 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1485                             uint32_t argCount, NPVariant &result)
1486 {
1487     /* is plugin still running */
1488     if( isPluginRunning() )
1489     {
1490         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1491         libvlc_exception_t ex;
1492         libvlc_exception_init(&ex);
1493
1494         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1495         RETURN_ON_EXCEPTION(this,ex);
1496
1497         switch( index )
1498         {
1499             case ID_video_togglefullscreen:
1500             {
1501                 if( argCount == 0 )
1502                 {
1503                     p_plugin->toggle_fullscreen(&ex);
1504                     RETURN_ON_EXCEPTION(this,ex);
1505                     VOID_TO_NPVARIANT(result);
1506                     return INVOKERESULT_NO_ERROR;
1507                 }
1508                 return INVOKERESULT_NO_SUCH_METHOD;
1509             }
1510             case ID_video_toggleteletext:
1511             {
1512                 if( argCount == 0 )
1513                 {
1514                     libvlc_toggle_teletext(p_md, &ex);
1515                     RETURN_ON_EXCEPTION(this,ex);
1516                     VOID_TO_NPVARIANT(result);
1517                     return INVOKERESULT_NO_ERROR;
1518                 }
1519                 return INVOKERESULT_NO_SUCH_METHOD;
1520             }
1521             case ID_video_deinterlacedisable:
1522             {
1523                 libvlc_video_set_deinterlace(p_md, 0, "", &ex);
1524                 RETURN_ON_EXCEPTION(this,ex);
1525                 return INVOKERESULT_NO_ERROR;
1526             }
1527             case ID_video_deinterlaceenable:
1528             {
1529                 if(argCount == 1)
1530                 {
1531                     if( NPVARIANT_IS_STRING( args[0] ) )
1532                     {
1533                         /* get deinterlace mode from the user */
1534                         char *psz_mode = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1535                         /* enable deinterlace filter if possible */
1536                         libvlc_video_set_deinterlace(p_md, 1, psz_mode, &ex);
1537                         free(psz_mode);
1538                         RETURN_ON_EXCEPTION(this,ex);
1539                         return INVOKERESULT_NO_ERROR;
1540                     }
1541                     else
1542                     {
1543                         return INVOKERESULT_INVALID_VALUE;
1544                     }
1545                 }
1546             }
1547             default:
1548                 return INVOKERESULT_NO_SUCH_METHOD;
1549         }
1550     }
1551     return INVOKERESULT_GENERIC_ERROR;
1552 }
1553
1554 /*
1555 ** implementation of libvlc marquee object
1556 */
1557
1558 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1559 {
1560 };
1561
1562 enum LibvlcMarqueeNPObjectPropertyIds
1563 {
1564 };
1565 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
1566
1567 RuntimeNPObject::InvokeResult
1568 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1569 {
1570     /* is plugin still running */
1571     if( isPluginRunning() )
1572     {
1573         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1574         libvlc_exception_t ex;
1575         libvlc_exception_init(&ex);
1576
1577         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1578         RETURN_ON_EXCEPTION(this,ex);
1579
1580         switch( index )
1581         {
1582         }
1583     }
1584     return INVOKERESULT_GENERIC_ERROR;
1585 }
1586
1587 RuntimeNPObject::InvokeResult
1588 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1589 {
1590     /* is plugin still running */
1591     if( isPluginRunning() )
1592     {
1593         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1594         libvlc_exception_t ex;
1595         libvlc_exception_init(&ex);
1596
1597         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1598         RETURN_ON_EXCEPTION(this,ex);
1599
1600         switch( index )
1601         {
1602         }
1603     }
1604     return INVOKERESULT_GENERIC_ERROR;
1605 }
1606
1607 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1608 {
1609     "enable",
1610     "disable",
1611     "color",
1612     "opacity",
1613     "position",
1614     "refresh",
1615     "size",
1616     "text",
1617     "timeout",
1618     "x",
1619     "y"
1620 };
1621 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1622
1623 enum LibvlcMarqueeNPObjectMethodIds
1624 {
1625     ID_marquee_enable,
1626     ID_marquee_disable,
1627     ID_marquee_color,
1628     ID_marquee_opacity,
1629     ID_marquee_position,
1630     ID_marquee_refresh,
1631     ID_marquee_size,
1632     ID_marquee_text,
1633     ID_marquee_timeout,
1634     ID_marquee_x,
1635     ID_marquee_y
1636 };
1637
1638 RuntimeNPObject::InvokeResult
1639 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1640                             uint32_t argCount, NPVariant &result)
1641 {
1642     /* is plugin still running */
1643     if( isPluginRunning() )
1644     {
1645         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1646         libvlc_exception_t ex;
1647         libvlc_exception_init(&ex);
1648
1649         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1650         RETURN_ON_EXCEPTION(this,ex);
1651
1652         switch( index )
1653         {
1654             case ID_marquee_enable:
1655             {
1656                 libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Enabled, true, &ex);
1657                     RETURN_ON_EXCEPTION(this,ex);
1658                 return INVOKERESULT_NO_ERROR;
1659             }
1660             case ID_marquee_disable:
1661             {
1662                 libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Enabled, false, &ex);
1663                     RETURN_ON_EXCEPTION(this,ex);
1664                 return INVOKERESULT_NO_ERROR;
1665             }
1666             case ID_marquee_color:
1667             {
1668                 if( argCount == 1)
1669                 {
1670                     if( NPVARIANT_IS_INT32( args[0] ) )
1671                     {
1672                         int i_color = NPVARIANT_TO_INT32( args[0] );
1673                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Color, i_color, &ex);
1674                             RETURN_ON_EXCEPTION(this,ex);
1675                         return INVOKERESULT_NO_ERROR;
1676                     }
1677                     else
1678                         return INVOKERESULT_GENERIC_ERROR;
1679                 }
1680                 return INVOKERESULT_NO_SUCH_METHOD;
1681             }
1682             case ID_marquee_opacity:
1683             {
1684                 if( argCount == 1)
1685                 {
1686                     if( NPVARIANT_IS_INT32( args[0] ) )
1687                     {
1688                         int i_opacity = NPVARIANT_TO_INT32( args[0] );
1689                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Opacity, i_opacity, &ex);
1690                             RETURN_ON_EXCEPTION(this,ex);
1691                         return INVOKERESULT_NO_ERROR;
1692                     }
1693                     else
1694                         return INVOKERESULT_GENERIC_ERROR;
1695                 }
1696                 return INVOKERESULT_NO_SUCH_METHOD;
1697             }
1698             case ID_marquee_position:
1699             {
1700                 if( argCount == 1)
1701                 {
1702                     if( NPVARIANT_IS_INT32( args[0] ) )
1703                     {
1704                         int i_position = NPVARIANT_TO_INT32( args[0] );
1705                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Position, i_position, &ex);
1706                             RETURN_ON_EXCEPTION(this,ex);
1707                         return INVOKERESULT_NO_ERROR;
1708                     }
1709                     else
1710                         return INVOKERESULT_GENERIC_ERROR;
1711                 }
1712                 return INVOKERESULT_NO_SUCH_METHOD;
1713             }
1714             case ID_marquee_refresh:
1715             {
1716                 if( argCount == 1)
1717                 {
1718                     if( NPVARIANT_IS_INT32( args[0] ) )
1719                     {
1720                         int i_refresh = NPVARIANT_TO_INT32( args[0] );
1721                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Refresh, i_refresh, &ex);
1722                             RETURN_ON_EXCEPTION(this,ex);
1723                         return INVOKERESULT_NO_ERROR;
1724                     }
1725                     else
1726                         return INVOKERESULT_GENERIC_ERROR;
1727                 }
1728                 return INVOKERESULT_NO_SUCH_METHOD;
1729             }
1730             case ID_marquee_size:
1731             {
1732                 if( argCount == 1)
1733                 {
1734                     if( NPVARIANT_IS_INT32( args[0] ) )
1735                     {
1736                         int i_size = NPVARIANT_TO_INT32( args[0] );
1737                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Size, i_size, &ex);
1738                             RETURN_ON_EXCEPTION(this,ex);
1739                         return INVOKERESULT_NO_ERROR;
1740                     }
1741                     else
1742                         return INVOKERESULT_GENERIC_ERROR;
1743                 }
1744                 return INVOKERESULT_NO_SUCH_METHOD;
1745             }
1746             case ID_marquee_text:
1747             {
1748                 if( argCount == 1)
1749                 {
1750                     if( NPVARIANT_IS_STRING( args[0] ) )
1751                     {
1752                         char *psz_text = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1753                         libvlc_video_set_marquee_option_as_string(p_md, libvlc_marquee_Text, psz_text, &ex);
1754                             RETURN_ON_EXCEPTION(this,ex);
1755                         free(psz_text);
1756                         return INVOKERESULT_NO_ERROR;
1757                     }
1758                     else
1759                         return INVOKERESULT_GENERIC_ERROR;
1760                 }
1761                 return INVOKERESULT_NO_SUCH_METHOD;
1762             }
1763             case ID_marquee_timeout:
1764             {
1765                 if( argCount == 1)
1766                 {
1767                     if( NPVARIANT_IS_INT32( args[0] ) )
1768                     {
1769                         int i_timeout = NPVARIANT_TO_INT32( args[0] );
1770                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Timeout, i_timeout, &ex);
1771                             RETURN_ON_EXCEPTION(this,ex);
1772                         return INVOKERESULT_NO_ERROR;
1773                     }
1774                     else
1775                         return INVOKERESULT_GENERIC_ERROR;
1776                 }
1777                 return INVOKERESULT_NO_SUCH_METHOD;
1778             }
1779             case ID_marquee_x:
1780             {
1781                 if( argCount == 1)
1782                 {
1783                     if( NPVARIANT_IS_INT32( args[0] ) )
1784                     {
1785                         int i_x = NPVARIANT_TO_INT32( args[0] );
1786                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_X, i_x, &ex);
1787                             RETURN_ON_EXCEPTION(this,ex);
1788                         return INVOKERESULT_NO_ERROR;
1789                     }
1790                     else
1791                         return INVOKERESULT_GENERIC_ERROR;
1792                 }
1793                 return INVOKERESULT_NO_SUCH_METHOD;
1794             }
1795             case ID_marquee_y:
1796             {
1797                 if( argCount == 1)
1798                 {
1799                     if( NPVARIANT_IS_INT32( args[0] ) )
1800                     {
1801                         int i_y = NPVARIANT_TO_INT32( args[0] );
1802                         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Y, i_y, &ex);
1803                             RETURN_ON_EXCEPTION(this,ex);
1804                         return INVOKERESULT_NO_ERROR;
1805                     }
1806                     else
1807                         return INVOKERESULT_GENERIC_ERROR;
1808                 }
1809                 return INVOKERESULT_NO_SUCH_METHOD;
1810             }
1811             default:
1812                 return INVOKERESULT_NO_SUCH_METHOD;
1813         }
1814     }
1815     return INVOKERESULT_GENERIC_ERROR;
1816 }