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