]> git.sesse.net Git - vlc/blob - projects/mozilla/control/npolibvlc.cpp
b412de3bcbfc2164c9d05b934bb614d07c7be469
[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 LibvlcVideoNPObject::~LibvlcVideoNPObject()
1256 {
1257     if( isValid() )
1258     {
1259         if( marqueeObj ) NPN_ReleaseObject(marqueeObj);
1260         if( logoObj    ) NPN_ReleaseObject(logoObj);
1261         if( deintObj   ) NPN_ReleaseObject(deintObj);
1262     }
1263 }
1264
1265 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1266 {
1267     "fullscreen",
1268     "height",
1269     "width",
1270     "aspectRatio",
1271     "subtitle",
1272     "crop",
1273     "teletext",
1274     "marquee",
1275     "logo",
1276     "deinterlace",
1277 };
1278
1279 enum LibvlcVideoNPObjectPropertyIds
1280 {
1281     ID_video_fullscreen,
1282     ID_video_height,
1283     ID_video_width,
1284     ID_video_aspectratio,
1285     ID_video_subtitle,
1286     ID_video_crop,
1287     ID_video_teletext,
1288     ID_video_marquee,
1289     ID_video_logo,
1290     ID_video_deinterlace,
1291 };
1292 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1293
1294 RuntimeNPObject::InvokeResult
1295 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1296 {
1297     /* is plugin still running */
1298     if( isPluginRunning() )
1299     {
1300         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1301         libvlc_exception_t ex;
1302         libvlc_exception_init(&ex);
1303
1304         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1305         RETURN_ON_EXCEPTION(this,ex);
1306
1307         switch( index )
1308         {
1309             case ID_video_fullscreen:
1310             {
1311                 int val = p_plugin->get_fullscreen(&ex);
1312                 RETURN_ON_EXCEPTION(this,ex);
1313                 BOOLEAN_TO_NPVARIANT(val, result);
1314                 return INVOKERESULT_NO_ERROR;
1315             }
1316             case ID_video_height:
1317             {
1318                 int val = libvlc_video_get_height(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_width:
1324             {
1325                 int val = libvlc_video_get_width(p_md, &ex);
1326                 RETURN_ON_EXCEPTION(this,ex);
1327                 INT32_TO_NPVARIANT(val, result);
1328                 return INVOKERESULT_NO_ERROR;
1329             }
1330             case ID_video_aspectratio:
1331             {
1332                 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1333                 RETURN_ON_EXCEPTION(this,ex);
1334                 if( !psz_aspect )
1335                     return INVOKERESULT_GENERIC_ERROR;
1336
1337                 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1338                 return INVOKERESULT_NO_ERROR;
1339             }
1340             case ID_video_subtitle:
1341             {
1342                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1343                 RETURN_ON_EXCEPTION(this,ex);
1344                 INT32_TO_NPVARIANT(i_spu, result);
1345                 return INVOKERESULT_NO_ERROR;
1346             }
1347             case ID_video_crop:
1348             {
1349                 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1350                 RETURN_ON_EXCEPTION(this,ex);
1351                 if( !psz_geometry )
1352                     return INVOKERESULT_GENERIC_ERROR;
1353
1354                 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1355                 return INVOKERESULT_NO_ERROR;
1356             }
1357             case ID_video_teletext:
1358             {
1359 /*                int i_page = libvlc_video_get_teletext(p_md, &ex);
1360                 RETURN_ON_EXCEPTION(this,ex);
1361                 INT32_TO_NPVARIANT(i_page, result);
1362                 return INVOKERESULT_NO_ERROR;
1363 */
1364                 return INVOKERESULT_NO_SUCH_METHOD;
1365             }
1366             case ID_video_marquee:
1367             {
1368                 InstantObj<LibvlcMarqueeNPObject>( marqueeObj );
1369                 OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1370                 return INVOKERESULT_NO_ERROR;
1371             }
1372             case ID_video_logo:
1373             {
1374                 InstantObj<LibvlcLogoNPObject>( logoObj );
1375                 OBJECT_TO_NPVARIANT(NPN_RetainObject(logoObj), result);
1376                 return INVOKERESULT_NO_ERROR;
1377             }
1378             case ID_video_deinterlace:
1379             {
1380                 InstantObj<LibvlcDeinterlaceNPObject>( deintObj );
1381                 OBJECT_TO_NPVARIANT(NPN_RetainObject(deintObj), result);
1382                 return INVOKERESULT_NO_ERROR;
1383             }
1384         }
1385     }
1386     return INVOKERESULT_GENERIC_ERROR;
1387 }
1388
1389 RuntimeNPObject::InvokeResult
1390 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1391 {
1392     /* is plugin still running */
1393     if( isPluginRunning() )
1394     {
1395         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1396         libvlc_exception_t ex;
1397         libvlc_exception_init(&ex);
1398
1399         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1400         RETURN_ON_EXCEPTION(this,ex);
1401
1402         switch( index )
1403         {
1404             case ID_video_fullscreen:
1405             {
1406                 if( ! NPVARIANT_IS_BOOLEAN(value) )
1407                 {
1408                     return INVOKERESULT_INVALID_VALUE;
1409                 }
1410
1411                 int val = NPVARIANT_TO_BOOLEAN(value);
1412                 p_plugin->set_fullscreen(val, &ex);
1413                 RETURN_ON_EXCEPTION(this,ex);
1414                 return INVOKERESULT_NO_ERROR;
1415             }
1416             case ID_video_aspectratio:
1417             {
1418                 char *psz_aspect = NULL;
1419
1420                 if( ! NPVARIANT_IS_STRING(value) )
1421                 {
1422                     return INVOKERESULT_INVALID_VALUE;
1423                 }
1424
1425                 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1426                 if( !psz_aspect )
1427                 {
1428                     return INVOKERESULT_GENERIC_ERROR;
1429                 }
1430
1431                 libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1432                 free(psz_aspect);
1433                 RETURN_ON_EXCEPTION(this,ex);
1434
1435                 return INVOKERESULT_NO_ERROR;
1436             }
1437             case ID_video_subtitle:
1438             {
1439                 if( isNumberValue(value) )
1440                 {
1441                     libvlc_video_set_spu(p_md, numberValue(value), &ex);
1442                     RETURN_ON_EXCEPTION(this,ex);
1443
1444                     return INVOKERESULT_NO_ERROR;
1445                 }
1446                 return INVOKERESULT_INVALID_VALUE;
1447             }
1448             case ID_video_crop:
1449             {
1450                 char *psz_geometry = NULL;
1451
1452                 if( ! NPVARIANT_IS_STRING(value) )
1453                 {
1454                     return INVOKERESULT_INVALID_VALUE;
1455                 }
1456
1457                 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1458                 if( !psz_geometry )
1459                 {
1460                     return INVOKERESULT_GENERIC_ERROR;
1461                 }
1462
1463                 libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
1464                 free(psz_geometry);
1465                 RETURN_ON_EXCEPTION(this,ex);
1466
1467                 return INVOKERESULT_NO_ERROR;
1468             }
1469             case ID_video_teletext:
1470             {
1471                 if( isNumberValue(value) )
1472                 {
1473 /*
1474                     libvlc_video_set_teletext(p_md, numberValue(value), &ex);
1475                     RETURN_ON_EXCEPTION(this,ex);
1476
1477                     return INVOKERESULT_NO_ERROR;
1478 */
1479                     return INVOKERESULT_NO_SUCH_METHOD;
1480                 }
1481                 return INVOKERESULT_INVALID_VALUE;
1482             }
1483         }
1484     }
1485     return INVOKERESULT_GENERIC_ERROR;
1486 }
1487
1488 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1489 {
1490     "toggleFullscreen",
1491     "toggleTeletext",
1492 };
1493 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1494
1495 enum LibvlcVideoNPObjectMethodIds
1496 {
1497     ID_video_togglefullscreen,
1498     ID_video_toggleteletext,
1499 };
1500
1501 RuntimeNPObject::InvokeResult
1502 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1503                             uint32_t argCount, NPVariant &result)
1504 {
1505     /* is plugin still running */
1506     if( isPluginRunning() )
1507     {
1508         VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1509         libvlc_exception_t ex;
1510         libvlc_exception_init(&ex);
1511
1512         libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1513         RETURN_ON_EXCEPTION(this,ex);
1514
1515         switch( index )
1516         {
1517             case ID_video_togglefullscreen:
1518             {
1519                 if( argCount == 0 )
1520                 {
1521                     p_plugin->toggle_fullscreen(&ex);
1522                     RETURN_ON_EXCEPTION(this,ex);
1523                     VOID_TO_NPVARIANT(result);
1524                     return INVOKERESULT_NO_ERROR;
1525                 }
1526                 return INVOKERESULT_NO_SUCH_METHOD;
1527             }
1528             case ID_video_toggleteletext:
1529             {
1530                 if( argCount == 0 )
1531                 {
1532                     libvlc_toggle_teletext(p_md, &ex);
1533                     RETURN_ON_EXCEPTION(this,ex);
1534                     VOID_TO_NPVARIANT(result);
1535                     return INVOKERESULT_NO_ERROR;
1536                 }
1537                 return INVOKERESULT_NO_SUCH_METHOD;
1538             }
1539             default:
1540                 return INVOKERESULT_NO_SUCH_METHOD;
1541         }
1542     }
1543     return INVOKERESULT_GENERIC_ERROR;
1544 }
1545
1546 /*
1547 ** implementation of libvlc marquee object
1548 */
1549
1550 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1551 {
1552     "color",
1553     "opacity",
1554     "position",
1555     "refresh",
1556     "size",
1557     "text",
1558     "timeout",
1559     "x",
1560     "y",
1561 };
1562
1563 enum LibvlcMarqueeNPObjectPropertyIds
1564 {
1565     ID_marquee_color,
1566     ID_marquee_opacity,
1567     ID_marquee_position,
1568     ID_marquee_refresh,
1569     ID_marquee_size,
1570     ID_marquee_text,
1571     ID_marquee_timeout,
1572     ID_marquee_x,
1573     ID_marquee_y,
1574 };
1575
1576 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
1577
1578 static const unsigned char marquee_idx[] = {
1579     libvlc_marquee_Color,
1580     libvlc_marquee_Opacity,
1581     libvlc_marquee_Position,
1582     libvlc_marquee_Refresh,
1583     libvlc_marquee_Size,
1584     0,
1585     libvlc_marquee_Timeout,
1586     libvlc_marquee_X,
1587     libvlc_marquee_Y,
1588 };
1589
1590 RuntimeNPObject::InvokeResult
1591 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1592 {
1593     char *psz;
1594
1595     if( !isPluginRunning() )
1596         return INVOKERESULT_GENERIC_ERROR;
1597
1598     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1599     libvlc_exception_t ex;
1600     libvlc_exception_init(&ex);
1601
1602     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1603     RETURN_ON_EXCEPTION(this,ex);
1604
1605     switch( index )
1606     {
1607     case ID_marquee_color:
1608     case ID_marquee_opacity:
1609     case ID_marquee_refresh:
1610     case ID_marquee_timeout:
1611     case ID_marquee_size:
1612     case ID_marquee_x:
1613     case ID_marquee_y:
1614         INT32_TO_NPVARIANT(
1615             libvlc_video_get_marquee_int(p_md, marquee_idx[index], &ex),
1616             result );
1617         RETURN_ON_EXCEPTION(this,ex);
1618         return INVOKERESULT_NO_ERROR;
1619
1620     case ID_marquee_position:
1621         STRINGZ_TO_NPVARIANT( position_bynumber(
1622             libvlc_video_get_marquee_int(p_md, libvlc_marquee_Position, &ex) ),
1623             result );
1624
1625         RETURN_ON_EXCEPTION(this,ex);
1626         break;
1627
1628     case ID_marquee_text:
1629         psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text, &ex);
1630         if( psz )
1631         {
1632             STRINGZ_TO_NPVARIANT(psz, result);
1633             return INVOKERESULT_NO_ERROR;
1634         }
1635         break;
1636     }
1637     return INVOKERESULT_GENERIC_ERROR;
1638 }
1639
1640 RuntimeNPObject::InvokeResult
1641 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1642 {
1643     size_t i;
1644
1645     if( !isPluginRunning() )
1646         return INVOKERESULT_GENERIC_ERROR;
1647
1648     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1649     libvlc_exception_t ex;
1650     libvlc_exception_init(&ex);
1651     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1652     RETURN_ON_EXCEPTION(this,ex);
1653
1654     switch( index )
1655     {
1656     case ID_marquee_color:
1657     case ID_marquee_opacity:
1658     case ID_marquee_refresh:
1659     case ID_marquee_timeout:
1660     case ID_marquee_x:
1661     case ID_marquee_y:
1662         if( NPVARIANT_IS_INT32( value ) )
1663         {
1664             libvlc_video_set_marquee_int(p_md, marquee_idx[index],
1665                                          NPVARIANT_TO_INT32( value ), &ex);
1666             RETURN_ON_EXCEPTION(this,ex);
1667             return INVOKERESULT_NO_ERROR;
1668         }
1669         break;
1670
1671     case ID_marquee_position:
1672         if( !NPVARIANT_IS_STRING(value) ||
1673             !position_byname( NPVARIANT_TO_STRING(value).utf8characters, i ) )
1674             return INVOKERESULT_INVALID_VALUE;
1675
1676         libvlc_video_set_marquee_int(p_md, libvlc_marquee_Position, i, &ex);
1677         RETURN_ON_EXCEPTION(this,ex);
1678         return INVOKERESULT_NO_ERROR;
1679
1680     case ID_marquee_text:
1681         if( NPVARIANT_IS_STRING( value ) )
1682         {
1683             char *psz_text = stringValue( NPVARIANT_TO_STRING( value ) );
1684             libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
1685                                             psz_text, &ex);
1686             free(psz_text);
1687             RETURN_ON_EXCEPTION(this,ex);
1688             return INVOKERESULT_NO_ERROR;
1689         }
1690         break;
1691     }
1692     return INVOKERESULT_NO_SUCH_METHOD;
1693 }
1694
1695 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1696 {
1697     "enable",
1698     "disable",
1699 };
1700 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1701
1702 enum LibvlcMarqueeNPObjectMethodIds
1703 {
1704     ID_marquee_enable,
1705     ID_marquee_disable,
1706 };
1707
1708 RuntimeNPObject::InvokeResult
1709 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1710                             uint32_t argCount, NPVariant &result)
1711 {
1712     if( !isPluginRunning() )
1713         return INVOKERESULT_GENERIC_ERROR;
1714
1715     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1716     libvlc_exception_t ex;
1717     libvlc_exception_init(&ex);
1718
1719     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1720     RETURN_ON_EXCEPTION(this,ex);
1721
1722     switch( index )
1723     {
1724     case ID_marquee_enable:
1725     case ID_marquee_disable:
1726         libvlc_video_set_marquee_int(p_md, libvlc_marquee_Enable,
1727                                      index!=ID_marquee_disable, &ex);
1728         RETURN_ON_EXCEPTION(this,ex);
1729         VOID_TO_NPVARIANT(result);
1730         return INVOKERESULT_NO_ERROR;
1731     }
1732     return INVOKERESULT_NO_SUCH_METHOD;
1733 }
1734
1735 const NPUTF8 * const LibvlcLogoNPObject::propertyNames[] = {
1736     "delay",
1737     "repeat",
1738     "opacity",
1739     "position",
1740     "x",
1741     "y",
1742 };
1743 enum LibvlcLogoNPObjectPropertyIds {
1744     ID_logo_delay,
1745     ID_logo_repeat,
1746     ID_logo_opacity,
1747     ID_logo_position,
1748     ID_logo_x,
1749     ID_logo_y,
1750 };
1751 COUNTNAMES(LibvlcLogoNPObject,propertyCount,propertyNames);
1752 static const unsigned char logo_idx[] = {
1753     libvlc_logo_delay,
1754     libvlc_logo_repeat,
1755     libvlc_logo_opacity,
1756     0,
1757     libvlc_logo_x,
1758     libvlc_logo_y,
1759 };
1760
1761 RuntimeNPObject::InvokeResult
1762 LibvlcLogoNPObject::getProperty(int index, NPVariant &result)
1763 {
1764     if( !isPluginRunning() )
1765         return INVOKERESULT_GENERIC_ERROR;
1766
1767     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1768     libvlc_exception_t ex;
1769     libvlc_exception_init(&ex);
1770     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1771     RETURN_ON_EXCEPTION(this,ex);
1772
1773     switch( index )
1774     {
1775     case ID_logo_delay:
1776     case ID_logo_repeat:
1777     case ID_logo_opacity:
1778     case ID_logo_x:
1779     case ID_logo_y:
1780
1781         INT32_TO_NPVARIANT(
1782             libvlc_video_get_logo_int(p_md, logo_idx[index], &ex), result);
1783
1784         RETURN_ON_EXCEPTION(this,ex);
1785         break;
1786
1787     case ID_logo_position:
1788         STRINGZ_TO_NPVARIANT( position_bynumber(
1789             libvlc_video_get_logo_int(p_md, libvlc_logo_position, &ex) ),
1790             result );
1791
1792         RETURN_ON_EXCEPTION(this,ex);
1793         break;
1794     default:
1795         return INVOKERESULT_GENERIC_ERROR;
1796     }
1797     return INVOKERESULT_NO_ERROR;
1798 }
1799
1800 RuntimeNPObject::InvokeResult
1801 LibvlcLogoNPObject::setProperty(int index, const NPVariant &value)
1802 {
1803     size_t i;
1804
1805     if( !isPluginRunning() )
1806         return INVOKERESULT_GENERIC_ERROR;
1807
1808     VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1809     libvlc_exception_t ex;
1810     libvlc_exception_init(&ex);
1811
1812     libvlc_media_player_t *p_md = p_plugin->getMD(&ex);
1813     RETURN_ON_EXCEPTION(this,ex);
1814
1815     switch( index )
1816     {
1817     case ID_logo_delay:
1818     case ID_logo_repeat:
1819     case ID_logo_opacity:
1820     case ID_logo_x:
1821     case ID_logo_y:
1822         if( !NPVARIANT_IS_INT32(value) )
1823             return INVOKERESULT_INVALID_VALUE;
1824
1825         libvlc_video_set_logo_int(p_md, logo_idx[index],
1826                                   NPVARIANT_TO_INT32( value ), &ex);
1827
1828         RETURN_ON_EXCEPTION(this,ex);
1829         break;
1830
1831     case ID_logo_position:
1832         if( !NPVARIANT_IS_STRING(value) ||
1833             !position_byname( NPVARIANT_TO_STRING(value).utf8characters, i ) )
1834             return INVOKERESULT_INVALID_VALUE;
1835
1836         libvlc_video_set_logo_int(p_md, libvlc_logo_position, i, &ex);
1837
1838         RETURN_ON_EXCEPTION(this,ex);
1839         break;
1840     default:
1841         return INVOKERESULT_GENERIC_ERROR;
1842     }
1843     return INVOKERESULT_NO_ERROR;
1844 }
1845
1846
1847 const NPUTF8 * const LibvlcLogoNPObject::methodNames[] = {
1848     "enable",
1849     "disable",
1850     "file",
1851 };
1852 enum LibvlcLogoNPObjectMethodIds {
1853     ID_logo_enable,
1854     ID_logo_disable,
1855     ID_logo_file,
1856 };
1857 COUNTNAMES(LibvlcLogoNPObject,methodCount,methodNames);
1858
1859 RuntimeNPObject::InvokeResult
1860 LibvlcLogoNPObject::invoke(int index, const NPVariant *args,
1861                            uint32_t argCount, NPVariant &result)
1862 {
1863     char *buf, *h;
1864     size_t i, len;
1865
1866     if( !isPluginRunning() )
1867         return INVOKERESULT_GENERIC_ERROR;
1868
1869     libvlc_exception_t ex;
1870     libvlc_exception_init(&ex);
1871     libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD(&ex);
1872     RETURN_ON_EXCEPTION(this,ex);
1873
1874     switch( index )
1875     {
1876     case ID_logo_enable:
1877     case ID_logo_disable:
1878         if( argCount != 0 )
1879             return INVOKERESULT_GENERIC_ERROR;
1880
1881         libvlc_video_set_logo_int(p_md, libvlc_logo_enable,
1882                                   index != ID_logo_disable, &ex);
1883         RETURN_ON_EXCEPTION(this,ex);
1884         VOID_TO_NPVARIANT(result);
1885         break;
1886
1887     case ID_logo_file:
1888         if( argCount == 0 )
1889             return INVOKERESULT_GENERIC_ERROR;
1890
1891         for( len=0,i=0;i<argCount;++i )
1892         {
1893             if( !NPVARIANT_IS_STRING(args[i]) )
1894                 return INVOKERESULT_INVALID_VALUE;
1895             len+=NPVARIANT_TO_STRING(args[i]).utf8length+1;
1896         }
1897
1898         buf = (char *)malloc( len+1 );
1899         if( !buf )
1900             return INVOKERESULT_OUT_OF_MEMORY;
1901
1902         for( h=buf,i=0;i<argCount;++i )
1903         {
1904             if(i) *h++=';';
1905             len=NPVARIANT_TO_STRING(args[i]).utf8length;
1906             memcpy(h,NPVARIANT_TO_STRING(args[i]).utf8characters,len);
1907             h+=len;
1908         }
1909         *h='\0';
1910
1911         libvlc_video_set_logo_string(p_md, libvlc_logo_file, buf, &ex);
1912         free( buf );
1913         RETURN_ON_EXCEPTION(this,ex);
1914         VOID_TO_NPVARIANT(result);
1915         break;
1916     default:
1917         return INVOKERESULT_NO_SUCH_METHOD;
1918     }
1919     return INVOKERESULT_NO_ERROR;
1920 }
1921
1922
1923 const NPUTF8 * const LibvlcDeinterlaceNPObject::propertyNames[] = {
1924 };
1925 enum LibvlcDeinterlaceNPObjectPropertyIds {
1926 };
1927 COUNTNAMES(LibvlcDeinterlaceNPObject,propertyCount,propertyNames);
1928
1929 RuntimeNPObject::InvokeResult
1930 LibvlcDeinterlaceNPObject::getProperty(int index, NPVariant &result)
1931 {
1932     return INVOKERESULT_GENERIC_ERROR;
1933 }
1934
1935 RuntimeNPObject::InvokeResult
1936 LibvlcDeinterlaceNPObject::setProperty(int index, const NPVariant &value)
1937 {
1938     return INVOKERESULT_GENERIC_ERROR;
1939 }
1940
1941
1942 const NPUTF8 * const LibvlcDeinterlaceNPObject::methodNames[] = {
1943     "enable",
1944     "disable",
1945 };
1946 enum LibvlcDeinterlaceNPObjectMethodIds {
1947     ID_deint_enable,
1948     ID_deint_disable,
1949 };
1950 COUNTNAMES(LibvlcDeinterlaceNPObject,methodCount,methodNames);
1951
1952 RuntimeNPObject::InvokeResult
1953 LibvlcDeinterlaceNPObject::invoke(int index, const NPVariant *args,
1954                            uint32_t argCount, NPVariant &result)
1955 {
1956     char *psz;
1957
1958     if( !isPluginRunning() )
1959         return INVOKERESULT_GENERIC_ERROR;
1960
1961     libvlc_exception_t ex;
1962     libvlc_exception_init(&ex);
1963     libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD(&ex);
1964     RETURN_ON_EXCEPTION(this,ex);
1965
1966     switch( index )
1967     {
1968     case ID_deint_disable:
1969         libvlc_video_set_deinterlace(p_md, 0, "", &ex);
1970         RETURN_ON_EXCEPTION(this,ex);
1971         break;
1972
1973     case ID_deint_enable:
1974         if( argCount != 1 || !NPVARIANT_IS_STRING( args[0] ) )
1975             return INVOKERESULT_INVALID_VALUE;
1976
1977         psz = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1978         libvlc_video_set_deinterlace(p_md, 1, psz, &ex);
1979         free(psz);
1980         RETURN_ON_EXCEPTION(this,ex);
1981         break;
1982
1983     default:
1984         return INVOKERESULT_NO_SUCH_METHOD;
1985     }
1986     return INVOKERESULT_NO_ERROR;
1987 }
1988