]> git.sesse.net Git - vlc/blob - projects/mozilla/control/npolibvlc.cpp
fix mozilla plugin compilation.
[vlc] / projects / mozilla / control / npolibvlc.cpp
1 /*****************************************************************************
2  * npolibvlc.cpp: official Javascript APIs
3  *****************************************************************************
4  * Copyright (C) 2002-2009 the VideoLAN team
5  * Copyright (C) 2010 M2X BV
6  *
7  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
8  *          JP Dinger <jpd@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 /* Mozilla stuff */
32 #ifdef HAVE_MOZILLA_CONFIG_H
33 #   include <mozilla-config.h>
34 #endif
35
36 #include "vlcplugin.h"
37 #include "npolibvlc.h"
38
39 #include "position.h"
40
41 /*
42 ** Local helper macros and function
43 */
44 #define COUNTNAMES(a,b,c) const int a::b = sizeof(a::c)/sizeof(NPUTF8 *)
45 #define RETURN_ON_EXCEPTION(this,ex) \
46     do { if( libvlc_exception_raised(&ex) ) \
47     { \
48         NPN_SetException(this, libvlc_errmsg()); \
49         libvlc_exception_clear(&ex); \
50         return INVOKERESULT_GENERIC_ERROR; \
51     } } while(false)
52
53 /*
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);
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
620         switch( index )
621         {
622             case ID_playlistitems_count:
623             {
624                 int val = p_plugin->playlist_count();
625                 INT32_TO_NPVARIANT(val, result);
626                 return INVOKERESULT_NO_ERROR;
627             }
628             default:
629                 ;
630         }
631     }
632     return INVOKERESULT_GENERIC_ERROR;
633 }
634
635 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
636 {
637     "clear",
638     "remove",
639 };
640 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
641
642 enum LibvlcPlaylistItemsNPObjectMethodIds
643 {
644     ID_playlistitems_clear,
645     ID_playlistitems_remove,
646 };
647
648 RuntimeNPObject::InvokeResult
649 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
650                                     uint32_t argCount, NPVariant &result)
651 {
652     /* is plugin still running */
653     if( isPluginRunning() )
654     {
655         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
656         libvlc_exception_t ex;
657         libvlc_exception_init(&ex);
658
659         switch( index )
660         {
661             case ID_playlistitems_clear:
662                 if( argCount == 0 )
663                 {
664                     p_plugin->playlist_clear(&ex);
665                     RETURN_ON_EXCEPTION(this,ex);
666                     VOID_TO_NPVARIANT(result);
667                     return INVOKERESULT_NO_ERROR;
668                 }
669                 return INVOKERESULT_NO_SUCH_METHOD;
670             case ID_playlistitems_remove:
671                 if( (argCount == 1) && isNumberValue(args[0]) )
672                 {
673                     p_plugin->playlist_delete_item(numberValue(args[0]),&ex);
674                     RETURN_ON_EXCEPTION(this,ex);
675                     VOID_TO_NPVARIANT(result);
676                     return INVOKERESULT_NO_ERROR;
677                 }
678                 return INVOKERESULT_NO_SUCH_METHOD;
679             default:
680                 ;
681         }
682     }
683     return INVOKERESULT_GENERIC_ERROR;
684 }
685
686 /*
687 ** implementation of libvlc playlist object
688 */
689
690 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
691 {
692     // Why the isValid()?
693     if( isValid() && playlistItemsObj )
694         NPN_ReleaseObject(playlistItemsObj);
695 };
696
697 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
698 {
699     "itemCount", /* deprecated */
700     "isPlaying",
701     "items",
702 };
703 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
704
705 enum LibvlcPlaylistNPObjectPropertyIds
706 {
707     ID_playlist_itemcount,
708     ID_playlist_isplaying,
709     ID_playlist_items,
710 };
711
712 RuntimeNPObject::InvokeResult
713 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
714 {
715     /* is plugin still running */
716     if( isPluginRunning() )
717     {
718         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
719
720         switch( index )
721         {
722             case ID_playlist_itemcount: /* deprecated */
723             {
724                 int val = p_plugin->playlist_count();
725                 INT32_TO_NPVARIANT(val, result);
726                 return INVOKERESULT_NO_ERROR;
727             }
728             case ID_playlist_isplaying:
729             {
730                 int val = p_plugin->playlist_isplaying();
731                 BOOLEAN_TO_NPVARIANT(val, result);
732                 return INVOKERESULT_NO_ERROR;
733             }
734             case ID_playlist_items:
735             {
736                 InstantObj<LibvlcPlaylistItemsNPObject>( playlistItemsObj );
737                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
738                 return INVOKERESULT_NO_ERROR;
739             }
740             default:
741                 ;
742         }
743     }
744     return INVOKERESULT_GENERIC_ERROR;
745 }
746
747 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
748 {
749     "add",
750     "play",
751     "playItem",
752     "togglePause",
753     "stop",
754     "next",
755     "prev",
756     "clear", /* deprecated */
757     "removeItem", /* deprecated */
758 };
759 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
760
761 enum LibvlcPlaylistNPObjectMethodIds
762 {
763     ID_playlist_add,
764     ID_playlist_play,
765     ID_playlist_playItem,
766     ID_playlist_togglepause,
767     ID_playlist_stop,
768     ID_playlist_next,
769     ID_playlist_prev,
770     ID_playlist_clear,
771     ID_playlist_removeitem
772 };
773
774 RuntimeNPObject::InvokeResult
775 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
776                                uint32_t argCount, NPVariant &result)
777 {
778     /* is plugin still running */
779     if( isPluginRunning() )
780     {
781         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
782         libvlc_exception_t ex;
783         libvlc_exception_init(&ex);
784
785         switch( index )
786         {
787             // XXX FIXME this needs squashing into something much smaller
788             case ID_playlist_add:
789             {
790                 if( (argCount < 1) || (argCount > 3) )
791                     return INVOKERESULT_NO_SUCH_METHOD;
792                 if( !NPVARIANT_IS_STRING(args[0]) )
793                     return INVOKERESULT_NO_SUCH_METHOD;
794
795                 // grab URL
796                 if( NPVARIANT_IS_NULL(args[0]) )
797                     return INVOKERESULT_NO_SUCH_METHOD;
798
799                 char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
800                 if( !s )
801                     return INVOKERESULT_OUT_OF_MEMORY;
802
803                 char *url = p_plugin->getAbsoluteURL(s);
804                 if( url )
805                     free(s);
806                 else
807                     // problem with combining url, use argument
808                     url = s;
809
810                 char *name = NULL;
811
812                 // grab name if available
813                 if( argCount > 1 )
814                 {
815                     if( NPVARIANT_IS_NULL(args[1]) )
816                     {
817                         // do nothing
818                     }
819                     else if( NPVARIANT_IS_STRING(args[1]) )
820                     {
821                         name = stringValue(NPVARIANT_TO_STRING(args[1]));
822                     }
823                     else
824                     {
825                         free(url);
826                         return INVOKERESULT_INVALID_VALUE;
827                     }
828                 }
829
830                 int i_options = 0;
831                 char** ppsz_options = NULL;
832
833                 // grab options if available
834                 if( argCount > 2 )
835                 {
836                     if( NPVARIANT_IS_NULL(args[2]) )
837                     {
838                         // do nothing
839                     }
840                     else if( NPVARIANT_IS_STRING(args[2]) )
841                     {
842                         parseOptions(NPVARIANT_TO_STRING(args[2]),
843                                      &i_options, &ppsz_options);
844
845                     }
846                     else if( NPVARIANT_IS_OBJECT(args[2]) )
847                     {
848                         parseOptions(NPVARIANT_TO_OBJECT(args[2]),
849                                      &i_options, &ppsz_options);
850                     }
851                     else
852                     {
853                         free(url);
854                         free(name);
855                         return INVOKERESULT_INVALID_VALUE;
856                     }
857                 }
858
859                 int item = p_plugin->playlist_add_extended_untrusted(url, name,
860                       i_options, const_cast<const char **>(ppsz_options), &ex);
861                 free(url);
862                 free(name);
863                 for( int i=0; i< i_options; ++i )
864                 {
865                     free(ppsz_options[i]);
866                 }
867                 free(ppsz_options);
868
869                 RETURN_ON_EXCEPTION(this,ex);
870                 INT32_TO_NPVARIANT(item, result);
871                 return INVOKERESULT_NO_ERROR;
872             }
873             case ID_playlist_play:
874                 if( argCount == 0 )
875                 {
876                     p_plugin->playlist_play(&ex);
877                     RETURN_ON_EXCEPTION(this,ex);
878                     VOID_TO_NPVARIANT(result);
879                     return INVOKERESULT_NO_ERROR;
880                 }
881                 return INVOKERESULT_NO_SUCH_METHOD;
882             case ID_playlist_playItem:
883                 if( (argCount == 1) && isNumberValue(args[0]) )
884                 {
885                     p_plugin->playlist_play_item(numberValue(args[0]),&ex);
886                     RETURN_ON_EXCEPTION(this,ex);
887                     VOID_TO_NPVARIANT(result);
888                     return INVOKERESULT_NO_ERROR;
889                 }
890                 return INVOKERESULT_NO_SUCH_METHOD;
891             case ID_playlist_togglepause:
892                 if( argCount == 0 )
893                 {
894                     p_plugin->playlist_pause(&ex);
895                     RETURN_ON_EXCEPTION(this,ex);
896                     VOID_TO_NPVARIANT(result);
897                     return INVOKERESULT_NO_ERROR;
898                 }
899                 return INVOKERESULT_NO_SUCH_METHOD;
900             case ID_playlist_stop:
901                 if( argCount == 0 )
902                 {
903                     p_plugin->playlist_stop();
904                     VOID_TO_NPVARIANT(result);
905                     return INVOKERESULT_NO_ERROR;
906                 }
907                 return INVOKERESULT_NO_SUCH_METHOD;
908             case ID_playlist_next:
909                 if( argCount == 0 )
910                 {
911                     p_plugin->playlist_next(&ex);
912                     RETURN_ON_EXCEPTION(this,ex);
913                     VOID_TO_NPVARIANT(result);
914                     return INVOKERESULT_NO_ERROR;
915                 }
916                 return INVOKERESULT_NO_SUCH_METHOD;
917             case ID_playlist_prev:
918                 if( argCount == 0 )
919                 {
920                     p_plugin->playlist_prev(&ex);
921                     RETURN_ON_EXCEPTION(this,ex);
922                     VOID_TO_NPVARIANT(result);
923                     return INVOKERESULT_NO_ERROR;
924                 }
925                 return INVOKERESULT_NO_SUCH_METHOD;
926             case ID_playlist_clear: /* deprecated */
927                 if( argCount == 0 )
928                 {
929                     p_plugin->playlist_clear(&ex);
930                     RETURN_ON_EXCEPTION(this,ex);
931                     VOID_TO_NPVARIANT(result);
932                     return INVOKERESULT_NO_ERROR;
933                 }
934                 return INVOKERESULT_NO_SUCH_METHOD;
935             case ID_playlist_removeitem: /* deprecated */
936                 if( (argCount == 1) && isNumberValue(args[0]) )
937                 {
938                     p_plugin->playlist_delete_item(numberValue(args[0]), &ex);
939                     RETURN_ON_EXCEPTION(this,ex);
940                     VOID_TO_NPVARIANT(result);
941                     return INVOKERESULT_NO_ERROR;
942                 }
943                 return INVOKERESULT_NO_SUCH_METHOD;
944             default:
945                 ;
946         }
947     }
948     return INVOKERESULT_GENERIC_ERROR;
949 }
950
951 // XXX FIXME The new playlist_add creates a media instance and feeds it
952 // XXX FIXME these options one at a time, so this hunk of code does lots
953 // XXX FIXME of unnecessairy work. Break out something that can do one
954 // XXX FIXME option at a time and doesn't need to realloc().
955 // XXX FIXME Same for the other version of parseOptions.
956
957 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
958                                          int *i_options, char*** ppsz_options)
959 {
960     if( nps.utf8length )
961     {
962         char *s = stringValue(nps);
963         char *val = s;
964         if( val )
965         {
966             long capacity = 16;
967             char **options = (char **)malloc(capacity*sizeof(char *));
968             if( options )
969             {
970                 int nOptions = 0;
971
972                 char *end = val + nps.utf8length;
973                 while( val < end )
974                 {
975                     // skip leading blanks
976                     while( (val < end)
977                         && ((*val == ' ' ) || (*val == '\t')) )
978                         ++val;
979
980                     char *start = val;
981                     // skip till we get a blank character
982                     while( (val < end)
983                         && (*val != ' ' )
984                         && (*val != '\t') )
985                     {
986                         char c = *(val++);
987                         if( ('\'' == c) || ('"' == c) )
988                         {
989                             // skip till end of string
990                             while( (val < end) && (*(val++) != c ) );
991                         }
992                     }
993
994                     if( val > start )
995                     {
996                         if( nOptions == capacity )
997                         {
998                             capacity += 16;
999                             char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1000                             if( ! moreOptions )
1001                             {
1002                                 /* failed to allocate more memory */
1003                                 free(s);
1004                                 /* return what we got so far */
1005                                 *i_options = nOptions;
1006                                 *ppsz_options = options;
1007                                 return;
1008                             }
1009                             options = moreOptions;
1010                         }
1011                         *(val++) = '\0';
1012                         options[nOptions++] = strdup(start);
1013                     }
1014                     else
1015                         // must be end of string
1016                         break;
1017                 }
1018                 *i_options = nOptions;
1019                 *ppsz_options = options;
1020             }
1021             free(s);
1022         }
1023     }
1024 }
1025
1026 // XXX FIXME See comment at the other parseOptions variant.
1027 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
1028                                           char*** ppsz_options)
1029 {
1030     /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1031
1032     NPVariant value;
1033
1034     /* we are expecting to have a Javascript Array object */
1035     NPIdentifier propId = NPN_GetStringIdentifier("length");
1036     if( NPN_GetProperty(_instance, obj, propId, &value) )
1037     {
1038         int count = numberValue(value);
1039         NPN_ReleaseVariantValue(&value);
1040
1041         if( count )
1042         {
1043             long capacity = 16;
1044             char **options = (char **)malloc(capacity*sizeof(char *));
1045             if( options )
1046             {
1047                 int nOptions = 0;
1048
1049                 while( nOptions < count )
1050                 {
1051                     propId = NPN_GetIntIdentifier(nOptions);
1052                     if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1053                         /* return what we got so far */
1054                         break;
1055
1056                     if( ! NPVARIANT_IS_STRING(value) )
1057                     {
1058                         /* return what we got so far */
1059                         NPN_ReleaseVariantValue(&value);
1060                         break;
1061                     }
1062
1063                     if( nOptions == capacity )
1064                     {
1065                         capacity += 16;
1066                         char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1067                         if( ! moreOptions )
1068                         {
1069                             /* failed to allocate more memory */
1070                             NPN_ReleaseVariantValue(&value);
1071                             /* return what we got so far */
1072                             *i_options = nOptions;
1073                             *ppsz_options = options;
1074                             break;
1075                         }
1076                         options = moreOptions;
1077                     }
1078
1079                     options[nOptions++] = stringValue(value);
1080                     NPN_ReleaseVariantValue(&value);
1081                 }
1082                 *i_options = nOptions;
1083                 *ppsz_options = options;
1084             }
1085         }
1086     }
1087 }
1088
1089 /*
1090 ** implementation of libvlc subtitle object
1091 */
1092
1093 const NPUTF8 * const LibvlcSubtitleNPObject::propertyNames[] =
1094 {
1095     "track",
1096     "count",
1097 };
1098
1099 enum LibvlcSubtitleNPObjectPropertyIds
1100 {
1101     ID_subtitle_track,
1102     ID_subtitle_count,
1103 };
1104 COUNTNAMES(LibvlcSubtitleNPObject,propertyCount,propertyNames);
1105
1106 RuntimeNPObject::InvokeResult
1107 LibvlcSubtitleNPObject::getProperty(int index, NPVariant &result)
1108 {
1109     /* is plugin still running */
1110     if( isPluginRunning() )
1111     {
1112         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1113         libvlc_exception_t ex;
1114         libvlc_exception_init(&ex);
1115
1116         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1117         RETURN_ON_EXCEPTION(this,ex);
1118
1119         switch( index )
1120         {
1121             case ID_subtitle_track:
1122             {
1123                 /* get the current subtitle ID */
1124                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1125                 RETURN_ON_EXCEPTION(this,ex);
1126                 /* return it */
1127                 INT32_TO_NPVARIANT(i_spu, result);
1128                 return INVOKERESULT_NO_ERROR;
1129             }
1130             case ID_subtitle_count:
1131             {
1132                 /* get the number of subtitles available */
1133                 int i_spu = libvlc_video_get_spu_count(p_md, &ex);
1134                 RETURN_ON_EXCEPTION(this,ex);
1135                 /* return it */
1136                 INT32_TO_NPVARIANT(i_spu, result);
1137                 return INVOKERESULT_NO_ERROR;
1138             }
1139         }
1140     }
1141     return INVOKERESULT_GENERIC_ERROR;
1142 }
1143
1144 RuntimeNPObject::InvokeResult
1145 LibvlcSubtitleNPObject::setProperty(int index, const NPVariant &value)
1146 {
1147     /* is plugin still running */
1148     if( isPluginRunning() )
1149     {
1150         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1151         libvlc_exception_t ex;
1152         libvlc_exception_init(&ex);
1153
1154         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1155         RETURN_ON_EXCEPTION(this,ex);
1156
1157         switch( index )
1158         {
1159             case ID_subtitle_track:
1160             {
1161                 if( isNumberValue(value) )
1162                 {
1163                     /* set the new subtitle track to show */
1164                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1165                     RETURN_ON_EXCEPTION(this,ex);
1166
1167                     return INVOKERESULT_NO_ERROR;
1168                 }
1169                 return INVOKERESULT_INVALID_VALUE;
1170             }
1171         }
1172     }
1173     return INVOKERESULT_GENERIC_ERROR;
1174 }
1175
1176 const NPUTF8 * const LibvlcSubtitleNPObject::methodNames[] =
1177 {
1178     "description"
1179 };
1180 COUNTNAMES(LibvlcSubtitleNPObject,methodCount,methodNames);
1181
1182 enum LibvlcSubtitleNPObjectMethodIds
1183 {
1184     ID_subtitle_description
1185 };
1186
1187 RuntimeNPObject::InvokeResult
1188 LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
1189                             uint32_t argCount, NPVariant &result)
1190 {
1191     /* is plugin still running */
1192     if( isPluginRunning() )
1193     {
1194         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1195         libvlc_exception_t ex;
1196         libvlc_exception_init(&ex);
1197
1198         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1199         RETURN_ON_EXCEPTION(this,ex);
1200
1201         switch( index )
1202         {
1203             case ID_subtitle_description:
1204             {
1205                 if( argCount == 1)
1206                 {
1207                     char *psz_name;
1208                     int i_spuID, i_limit, i;
1209                     libvlc_track_description_t *p_spuDesc;
1210
1211                     /* get subtitles description */
1212                     p_spuDesc = libvlc_video_get_spu_description(p_md, &ex);
1213                     RETURN_ON_EXCEPTION(this,ex);
1214                     if( !p_spuDesc )
1215                         return INVOKERESULT_GENERIC_ERROR;
1216
1217                     /* get the number of subtitle available */
1218                     i_limit = libvlc_video_get_spu_count(p_md, &ex);
1219                     RETURN_ON_EXCEPTION(this,ex);
1220
1221                     /* check if a number is given by the user
1222                      * and get the subtitle number */
1223                     if( isNumberValue(args[0]) )
1224                         i_spuID = numberValue(args[0]);
1225                     else
1226                         return INVOKERESULT_INVALID_VALUE;
1227
1228                     /* if bad number is given return invalid value */
1229                     if ( ( i_spuID > ( i_limit -1 ) ) || ( i_spuID < 0 ) )
1230                         return INVOKERESULT_INVALID_VALUE;
1231
1232                     /* get the good spuDesc */
1233                     for( i = 0 ; i < i_spuID ; i++ )
1234                     {
1235                         p_spuDesc = p_spuDesc->p_next;
1236                     }
1237                     psz_name = p_spuDesc->psz_name;
1238
1239                     /* return the name of the track chosen */
1240                     return invokeResultString(psz_name, result);
1241                 }
1242                 return INVOKERESULT_NO_SUCH_METHOD;
1243             }
1244             default:
1245                 return INVOKERESULT_NO_SUCH_METHOD;
1246         }
1247     }
1248     return INVOKERESULT_GENERIC_ERROR;
1249 }
1250
1251 /*
1252 ** implementation of libvlc video object
1253 */
1254
1255 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1256 {
1257     "fullscreen",
1258     "height",
1259     "width",
1260     "aspectRatio",
1261     "subtitle",
1262     "crop",
1263     "teletext",
1264     "marquee",
1265     "logo"
1266 };
1267
1268 enum LibvlcVideoNPObjectPropertyIds
1269 {
1270     ID_video_fullscreen,
1271     ID_video_height,
1272     ID_video_width,
1273     ID_video_aspectratio,
1274     ID_video_subtitle,
1275     ID_video_crop,
1276     ID_video_teletext,
1277     ID_video_marquee,
1278     ID_video_logo
1279 };
1280 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1281
1282 RuntimeNPObject::InvokeResult
1283 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1284 {
1285     /* is plugin still running */
1286     if( isPluginRunning() )
1287     {
1288         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1289         libvlc_exception_t ex;
1290         libvlc_exception_init(&ex);
1291
1292         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1293         RETURN_ON_EXCEPTION(this,ex);
1294
1295         switch( index )
1296         {
1297             case ID_video_fullscreen:
1298             {
1299                 int val = p_plugin->get_fullscreen(&ex);
1300                 RETURN_ON_EXCEPTION(this,ex);
1301                 BOOLEAN_TO_NPVARIANT(val, result);
1302                 return INVOKERESULT_NO_ERROR;
1303             }
1304             case ID_video_height:
1305             {
1306                 int val = libvlc_video_get_height(p_md, &ex);
1307                 RETURN_ON_EXCEPTION(this,ex);
1308                 INT32_TO_NPVARIANT(val, result);
1309                 return INVOKERESULT_NO_ERROR;
1310             }
1311             case ID_video_width:
1312             {
1313                 int val = libvlc_video_get_width(p_md, &ex);
1314                 RETURN_ON_EXCEPTION(this,ex);
1315                 INT32_TO_NPVARIANT(val, result);
1316                 return INVOKERESULT_NO_ERROR;
1317             }
1318             case ID_video_aspectratio:
1319             {
1320                 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1321                 RETURN_ON_EXCEPTION(this,ex);
1322                 if( !psz_aspect )
1323                     return INVOKERESULT_GENERIC_ERROR;
1324
1325                 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1326                 return INVOKERESULT_NO_ERROR;
1327             }
1328             case ID_video_subtitle:
1329             {
1330                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1331                 RETURN_ON_EXCEPTION(this,ex);
1332                 INT32_TO_NPVARIANT(i_spu, result);
1333                 return INVOKERESULT_NO_ERROR;
1334             }
1335             case ID_video_crop:
1336             {
1337                 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1338                 RETURN_ON_EXCEPTION(this,ex);
1339                 if( !psz_geometry )
1340                     return INVOKERESULT_GENERIC_ERROR;
1341
1342                 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1343                 return INVOKERESULT_NO_ERROR;
1344             }
1345             case ID_video_teletext:
1346             {
1347 /*                int i_page = libvlc_video_get_teletext(p_md, &ex);
1348                 RETURN_ON_EXCEPTION(this,ex);
1349                 INT32_TO_NPVARIANT(i_page, result);
1350                 return INVOKERESULT_NO_ERROR;
1351 */
1352                 return INVOKERESULT_NO_SUCH_METHOD;
1353             }
1354             case ID_video_marquee:
1355             {
1356                 InstantObj<LibvlcMarqueeNPObject>( marqueeObj );
1357                 OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1358                 return INVOKERESULT_NO_ERROR;
1359             }
1360             case ID_video_logo:
1361             {
1362                 InstantObj<LibvlcLogoNPObject>( logoObj );
1363                 OBJECT_TO_NPVARIANT(NPN_RetainObject(logoObj), result);
1364                 return INVOKERESULT_NO_ERROR;
1365             }
1366         }
1367     }
1368     return INVOKERESULT_GENERIC_ERROR;
1369 }
1370
1371 RuntimeNPObject::InvokeResult
1372 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1373 {
1374     /* is plugin still running */
1375     if( isPluginRunning() )
1376     {
1377         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1378         libvlc_exception_t ex;
1379         libvlc_exception_init(&ex);
1380
1381         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1382         RETURN_ON_EXCEPTION(this,ex);
1383
1384         switch( index )
1385         {
1386             case ID_video_fullscreen:
1387             {
1388                 if( ! NPVARIANT_IS_BOOLEAN(value) )
1389                 {
1390                     return INVOKERESULT_INVALID_VALUE;
1391                 }
1392
1393                 int val = NPVARIANT_TO_BOOLEAN(value);
1394                 p_plugin->set_fullscreen(val, &ex);
1395                 RETURN_ON_EXCEPTION(this,ex);
1396                 return INVOKERESULT_NO_ERROR;
1397             }
1398             case ID_video_aspectratio:
1399             {
1400                 char *psz_aspect = NULL;
1401
1402                 if( ! NPVARIANT_IS_STRING(value) )
1403                 {
1404                     return INVOKERESULT_INVALID_VALUE;
1405                 }
1406
1407                 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1408                 if( !psz_aspect )
1409                 {
1410                     return INVOKERESULT_GENERIC_ERROR;
1411                 }
1412
1413                 libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1414                 free(psz_aspect);
1415                 RETURN_ON_EXCEPTION(this,ex);
1416
1417                 return INVOKERESULT_NO_ERROR;
1418             }
1419             case ID_video_subtitle:
1420             {
1421                 if( isNumberValue(value) )
1422                 {
1423                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1424                     RETURN_ON_EXCEPTION(this,ex);
1425
1426                     return INVOKERESULT_NO_ERROR;
1427                 }
1428                 return INVOKERESULT_INVALID_VALUE;
1429             }
1430             case ID_video_crop:
1431             {
1432                 char *psz_geometry = NULL;
1433
1434                 if( ! NPVARIANT_IS_STRING(value) )
1435                 {
1436                     return INVOKERESULT_INVALID_VALUE;
1437                 }
1438
1439                 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1440                 if( !psz_geometry )
1441                 {
1442                     return INVOKERESULT_GENERIC_ERROR;
1443                 }
1444
1445                 libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
1446                 free(psz_geometry);
1447                 RETURN_ON_EXCEPTION(this,ex);
1448
1449                 return INVOKERESULT_NO_ERROR;
1450             }
1451             case ID_video_teletext:
1452             {
1453                 if( isNumberValue(value) )
1454                 {
1455 /*
1456                     libvlc_video_set_teletext(p_md, numberValue(value), &ex);
1457                     RETURN_ON_EXCEPTION(this,ex);
1458
1459                     return INVOKERESULT_NO_ERROR;
1460 */
1461                     return INVOKERESULT_NO_SUCH_METHOD;
1462                 }
1463                 return INVOKERESULT_INVALID_VALUE;
1464             }
1465         }
1466     }
1467     return INVOKERESULT_GENERIC_ERROR;
1468 }
1469
1470 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1471 {
1472     "toggleFullscreen",
1473     "toggleTeletext",
1474     "deinterlaceEnable",
1475     "deinterlaceDisable"
1476 };
1477 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1478
1479 enum LibvlcVideoNPObjectMethodIds
1480 {
1481     ID_video_togglefullscreen,
1482     ID_video_toggleteletext,
1483     ID_video_deinterlaceenable,
1484     ID_video_deinterlacedisable
1485 };
1486
1487 RuntimeNPObject::InvokeResult
1488 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1489                             uint32_t argCount, NPVariant &result)
1490 {
1491     /* is plugin still running */
1492     if( isPluginRunning() )
1493     {
1494         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1495         libvlc_exception_t ex;
1496         libvlc_exception_init(&ex);
1497
1498         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1499         RETURN_ON_EXCEPTION(this,ex);
1500
1501         switch( index )
1502         {
1503             case ID_video_togglefullscreen:
1504             {
1505                 if( argCount == 0 )
1506                 {
1507                     p_plugin->toggle_fullscreen(&ex);
1508                     RETURN_ON_EXCEPTION(this,ex);
1509                     VOID_TO_NPVARIANT(result);
1510                     return INVOKERESULT_NO_ERROR;
1511                 }
1512                 return INVOKERESULT_NO_SUCH_METHOD;
1513             }
1514             case ID_video_toggleteletext:
1515             {
1516                 if( argCount == 0 )
1517                 {
1518                     libvlc_toggle_teletext(p_md, &ex);
1519                     RETURN_ON_EXCEPTION(this,ex);
1520                     VOID_TO_NPVARIANT(result);
1521                     return INVOKERESULT_NO_ERROR;
1522                 }
1523                 return INVOKERESULT_NO_SUCH_METHOD;
1524             }
1525             case ID_video_deinterlacedisable:
1526             {
1527                 libvlc_video_set_deinterlace(p_md, 0, "", &ex);
1528                 RETURN_ON_EXCEPTION(this,ex);
1529                 return INVOKERESULT_NO_ERROR;
1530             }
1531             case ID_video_deinterlaceenable:
1532             {
1533                 if(argCount == 1)
1534                 {
1535                     if( NPVARIANT_IS_STRING( args[0] ) )
1536                     {
1537                         /* get deinterlace mode from the user */
1538                         char *psz_mode = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1539                         /* enable deinterlace filter if possible */
1540                         libvlc_video_set_deinterlace(p_md, 1, psz_mode, &ex);
1541                         free(psz_mode);
1542                         RETURN_ON_EXCEPTION(this,ex);
1543                         return INVOKERESULT_NO_ERROR;
1544                     }
1545                     else
1546                     {
1547                         return INVOKERESULT_INVALID_VALUE;
1548                     }
1549                 }
1550             }
1551             default:
1552                 return INVOKERESULT_NO_SUCH_METHOD;
1553         }
1554     }
1555     return INVOKERESULT_GENERIC_ERROR;
1556 }
1557
1558 /*
1559 ** implementation of libvlc marquee object
1560 */
1561
1562 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1563 {
1564     "color",
1565     "opacity",
1566     "position",
1567     "refresh",
1568     "size",
1569     "text",
1570     "timeout",
1571     "x",
1572     "y",
1573 };
1574
1575 enum LibvlcMarqueeNPObjectPropertyIds
1576 {
1577     ID_marquee_color,
1578     ID_marquee_opacity,
1579     ID_marquee_position,
1580     ID_marquee_refresh,
1581     ID_marquee_size,
1582     ID_marquee_text,
1583     ID_marquee_timeout,
1584     ID_marquee_x,
1585     ID_marquee_y,
1586 };
1587
1588 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
1589
1590 static const unsigned char marquee_idx[] = {
1591     libvlc_marquee_Color,
1592     libvlc_marquee_Opacity,
1593     libvlc_marquee_Position,
1594     libvlc_marquee_Refresh,
1595     libvlc_marquee_Size,
1596     0,
1597     libvlc_marquee_Timeout,
1598     libvlc_marquee_X,
1599     libvlc_marquee_Y,
1600 };
1601
1602 RuntimeNPObject::InvokeResult
1603 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1604 {
1605     char *psz;
1606
1607     if( !isPluginRunning() )
1608         return INVOKERESULT_GENERIC_ERROR;
1609
1610     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1611     libvlc_exception_t ex;
1612     libvlc_exception_init(&ex);
1613
1614     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1615     RETURN_ON_EXCEPTION(this,ex);
1616
1617     switch( index )
1618     {
1619     case ID_marquee_color:
1620     case ID_marquee_opacity:
1621     case ID_marquee_refresh:
1622     case ID_marquee_timeout:
1623     case ID_marquee_size:
1624     case ID_marquee_x:
1625     case ID_marquee_y:
1626         INT32_TO_NPVARIANT(
1627             libvlc_video_get_marquee_int(p_md, marquee_idx[index], &ex),
1628             result );
1629         RETURN_ON_EXCEPTION(this,ex);
1630         return INVOKERESULT_NO_ERROR;
1631
1632     case ID_marquee_position:
1633         STRINGZ_TO_NPVARIANT( position_bynumber(
1634             libvlc_video_get_marquee_int(p_md, libvlc_marquee_Position, &ex) ),
1635             result );
1636
1637         RETURN_ON_EXCEPTION(this,ex);
1638         break;
1639
1640     case ID_marquee_text:
1641         psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text, &ex);
1642         if( psz )
1643         {
1644             STRINGZ_TO_NPVARIANT(psz, result);
1645             return INVOKERESULT_NO_ERROR;
1646         }
1647         break;
1648     }
1649     return INVOKERESULT_GENERIC_ERROR;
1650 }
1651
1652 RuntimeNPObject::InvokeResult
1653 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1654 {
1655     size_t i;
1656
1657     if( !isPluginRunning() )
1658         return INVOKERESULT_GENERIC_ERROR;
1659
1660     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1661     libvlc_exception_t ex;
1662     libvlc_exception_init(&ex);
1663     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1664     RETURN_ON_EXCEPTION(this,ex);
1665
1666     switch( index )
1667     {
1668     case ID_marquee_color:
1669     case ID_marquee_opacity:
1670     case ID_marquee_refresh:
1671     case ID_marquee_timeout:
1672     case ID_marquee_x:
1673     case ID_marquee_y:
1674         if( NPVARIANT_IS_INT32( value ) )
1675         {
1676             libvlc_video_set_marquee_int(p_md, marquee_idx[index],
1677                                          NPVARIANT_TO_INT32( value ), &ex);
1678             RETURN_ON_EXCEPTION(this,ex);
1679             return INVOKERESULT_NO_ERROR;
1680         }
1681         break;
1682
1683     case ID_marquee_position:
1684         if( !NPVARIANT_IS_STRING(value) ||
1685             !position_byname( NPVARIANT_TO_STRING(value).utf8characters, i ) )
1686             return INVOKERESULT_INVALID_VALUE;
1687
1688         libvlc_video_set_marquee_int(p_md, libvlc_marquee_Position, i, &ex);
1689         RETURN_ON_EXCEPTION(this,ex);
1690         return INVOKERESULT_NO_ERROR;
1691
1692     case ID_marquee_text:
1693         if( NPVARIANT_IS_STRING( value ) )
1694         {
1695             char *psz_text = stringValue( NPVARIANT_TO_STRING( value ) );
1696             libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
1697                                             psz_text, &ex);
1698             free(psz_text);
1699             RETURN_ON_EXCEPTION(this,ex);
1700             return INVOKERESULT_NO_ERROR;
1701         }
1702         break;
1703     }
1704     return INVOKERESULT_NO_SUCH_METHOD;
1705 }
1706
1707 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1708 {
1709     "enable",
1710     "disable",
1711 };
1712 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1713
1714 enum LibvlcMarqueeNPObjectMethodIds
1715 {
1716     ID_marquee_enable,
1717     ID_marquee_disable,
1718 };
1719
1720 RuntimeNPObject::InvokeResult
1721 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1722                             uint32_t argCount, NPVariant &result)
1723 {
1724     if( !isPluginRunning() )
1725         return INVOKERESULT_GENERIC_ERROR;
1726
1727     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1728     libvlc_exception_t ex;
1729     libvlc_exception_init(&ex);
1730
1731     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1732     RETURN_ON_EXCEPTION(this,ex);
1733
1734     switch( index )
1735     {
1736     case ID_marquee_enable:
1737     case ID_marquee_disable:
1738         libvlc_video_set_marquee_int(p_md, libvlc_marquee_Enable,
1739                                      index!=ID_marquee_disable, &ex);
1740         RETURN_ON_EXCEPTION(this,ex);
1741         VOID_TO_NPVARIANT(result);
1742         return INVOKERESULT_NO_ERROR;
1743     }
1744     return INVOKERESULT_NO_SUCH_METHOD;
1745 }
1746
1747 const NPUTF8 * const LibvlcLogoNPObject::propertyNames[] = {
1748     "delay",
1749     "repeat",
1750     "opacity",
1751     "position",
1752     "x",
1753     "y",
1754 };
1755 enum LibvlcLogoNPObjectPropertyIds {
1756     ID_logo_delay,
1757     ID_logo_repeat,
1758     ID_logo_opacity,
1759     ID_logo_position,
1760     ID_logo_x,
1761     ID_logo_y,
1762 };
1763 COUNTNAMES(LibvlcLogoNPObject,propertyCount,propertyNames);
1764 static const unsigned char logo_idx[] = {
1765     libvlc_logo_delay,
1766     libvlc_logo_repeat,
1767     libvlc_logo_opacity,
1768     0,
1769     libvlc_logo_x,
1770     libvlc_logo_y,
1771 };
1772
1773 RuntimeNPObject::InvokeResult
1774 LibvlcLogoNPObject::getProperty(int index, NPVariant &result)
1775 {
1776     if( !isPluginRunning() )
1777         return INVOKERESULT_GENERIC_ERROR;
1778
1779     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1780     libvlc_exception_t ex;
1781     libvlc_exception_init(&ex);
1782     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1783     RETURN_ON_EXCEPTION(this,ex);
1784
1785     switch( index )
1786     {
1787     case ID_logo_delay:
1788     case ID_logo_repeat:
1789     case ID_logo_opacity:
1790     case ID_logo_x:
1791     case ID_logo_y:
1792
1793         INT32_TO_NPVARIANT(
1794             libvlc_video_get_logo_int(p_md, logo_idx[index], &ex), result);
1795
1796         RETURN_ON_EXCEPTION(this,ex);
1797         break;
1798
1799     case ID_logo_position:
1800         STRINGZ_TO_NPVARIANT( position_bynumber(
1801             libvlc_video_get_logo_int(p_md, libvlc_logo_position, &ex) ),
1802             result );
1803
1804         RETURN_ON_EXCEPTION(this,ex);
1805         break;
1806     default:
1807         return INVOKERESULT_GENERIC_ERROR;
1808     }
1809     return INVOKERESULT_NO_ERROR;
1810 }
1811
1812 RuntimeNPObject::InvokeResult
1813 LibvlcLogoNPObject::setProperty(int index, const NPVariant &value)
1814 {
1815     size_t i;
1816
1817     if( !isPluginRunning() )
1818         return INVOKERESULT_GENERIC_ERROR;
1819
1820     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1821     libvlc_exception_t ex;
1822     libvlc_exception_init(&ex);
1823
1824     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1825     RETURN_ON_EXCEPTION(this,ex);
1826
1827     switch( index )
1828     {
1829     case ID_logo_delay:
1830     case ID_logo_repeat:
1831     case ID_logo_opacity:
1832     case ID_logo_x:
1833     case ID_logo_y:
1834         if( !NPVARIANT_IS_INT32(value) )
1835             return INVOKERESULT_INVALID_VALUE;
1836
1837         libvlc_video_set_logo_int(p_md, logo_idx[index],
1838                                   NPVARIANT_TO_INT32( value ), &ex);
1839
1840         RETURN_ON_EXCEPTION(this,ex);
1841         break;
1842
1843     case ID_logo_position:
1844         if( !NPVARIANT_IS_STRING(value) ||
1845             !position_byname( NPVARIANT_TO_STRING(value).utf8characters, i ) )
1846             return INVOKERESULT_INVALID_VALUE;
1847
1848         libvlc_video_set_logo_int(p_md, libvlc_logo_position, i, &ex);
1849
1850         RETURN_ON_EXCEPTION(this,ex);
1851         break;
1852     default:
1853         return INVOKERESULT_GENERIC_ERROR;
1854     }
1855     return INVOKERESULT_NO_ERROR;
1856 }
1857
1858
1859 const NPUTF8 * const LibvlcLogoNPObject::methodNames[] = {
1860     "enable",
1861     "disable",
1862     "file",
1863 };
1864 enum LibvlcLogoNPObjectMethodIds {
1865     ID_logo_enable,
1866     ID_logo_disable,
1867     ID_logo_file,
1868 };
1869 COUNTNAMES(LibvlcLogoNPObject,methodCount,methodNames);
1870
1871 RuntimeNPObject::InvokeResult
1872 LibvlcLogoNPObject::invoke(int index, const NPVariant *args,
1873                            uint32_t argCount, NPVariant &result)
1874 {
1875     char *buf, *h;
1876     size_t i, len;
1877
1878     if( !isPluginRunning() )
1879         return INVOKERESULT_GENERIC_ERROR;
1880
1881     libvlc_exception_t ex;
1882     libvlc_exception_init(&ex);
1883     libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD(&ex);
1884     RETURN_ON_EXCEPTION(this,ex);
1885
1886     switch( index )
1887     {
1888     case ID_logo_enable:
1889     case ID_logo_disable:
1890         if( argCount != 0 )
1891             return INVOKERESULT_GENERIC_ERROR;
1892
1893         libvlc_video_set_logo_int(p_md, libvlc_logo_enable,
1894                                   index != ID_logo_disable, &ex);
1895         RETURN_ON_EXCEPTION(this,ex);
1896         VOID_TO_NPVARIANT(result);
1897         break;
1898
1899     case ID_logo_file:
1900         if( argCount == 0 )
1901             return INVOKERESULT_GENERIC_ERROR;
1902
1903         for( len=0,i=0;i<argCount;++i )
1904         {
1905             if( !NPVARIANT_IS_STRING(args[i]) )
1906                 return INVOKERESULT_INVALID_VALUE;
1907             len+=NPVARIANT_TO_STRING(args[i]).utf8length+1;
1908         }
1909
1910         buf = (char *)malloc( len+1 );
1911         if( !buf )
1912             return INVOKERESULT_OUT_OF_MEMORY;
1913
1914         for( h=buf,i=0;i<argCount;++i )
1915         {
1916             if(i) *h++=';';
1917             len=NPVARIANT_TO_STRING(args[i]).utf8length;
1918             memcpy(h,NPVARIANT_TO_STRING(args[i]).utf8characters,len);
1919             h+=len;
1920         }
1921         *h='\0';
1922
1923         libvlc_video_set_logo_string(p_md, libvlc_logo_file, buf, &ex);
1924         free( buf );
1925         RETURN_ON_EXCEPTION(this,ex);
1926         VOID_TO_NPVARIANT(result);
1927         break;
1928     }
1929     return INVOKERESULT_NO_ERROR;
1930 }
1931