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