1 /*****************************************************************************
2 * npolibvlc.cpp: official Javascript APIs
3 *****************************************************************************
4 * Copyright (C) 2002-2009 the VideoLAN team
5 * Copyright (C) 2010 M2X BV
7 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
8 * JP Dinger <jpd@videolan.org>
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.
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.
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 *****************************************************************************/
31 #include "vlcplugin.h"
32 #include "npolibvlc.h"
37 ** Local helper macros and function
39 #define COUNTNAMES(a,b,c) const int a::b = sizeof(a::c)/sizeof(NPUTF8 *)
40 #define RETURN_ON_ERROR \
42 NPN_SetException(this, libvlc_errmsg()); \
43 return INVOKERESULT_GENERIC_ERROR; \
46 #define ERROR_EVENT_NOT_FOUND "ERROR: One or more events could not be found."
47 #define ERROR_API_VERSION "ERROR: NPAPI version not high enough. (Gecko >= 1.9 needed)"
49 // Make a copy of an NPVariant.
50 NPVariant copyNPVariant(const NPVariant& original)
54 if (NPVARIANT_IS_STRING(original))
55 STRINGZ_TO_NPVARIANT(strdup(NPVARIANT_TO_STRING(original).UTF8Characters), res);
56 else if (NPVARIANT_IS_INT32(original))
57 INT32_TO_NPVARIANT(NPVARIANT_TO_INT32(original), res);
58 else if (NPVARIANT_IS_DOUBLE(original))
59 DOUBLE_TO_NPVARIANT(NPVARIANT_TO_DOUBLE(original), res);
60 else if (NPVARIANT_IS_OBJECT(original))
62 NPObject *obj = NPVARIANT_TO_OBJECT(original);
63 NPN_RetainObject(obj);
64 OBJECT_TO_NPVARIANT(obj, res);
66 else if (NPVARIANT_IS_BOOLEAN(original))
67 BOOLEAN_TO_NPVARIANT(NPVARIANT_TO_BOOLEAN(original), res);
73 ** implementation of libvlc root object
76 LibvlcRootNPObject::~LibvlcRootNPObject()
79 ** When the plugin is destroyed, firefox takes it upon itself to
80 ** destroy all 'live' script objects and ignores refcounting.
81 ** Therefore we cannot safely assume that refcounting will control
82 ** lifespan of objects. Hence they are only lazily created on
83 ** request, so that firefox can take ownership, and are not released
84 ** when the plugin is destroyed.
88 if( audioObj ) NPN_ReleaseObject(audioObj);
89 if( inputObj ) NPN_ReleaseObject(inputObj);
90 if( playlistObj ) NPN_ReleaseObject(playlistObj);
91 if( subtitleObj ) NPN_ReleaseObject(subtitleObj);
92 if( videoObj ) NPN_ReleaseObject(videoObj);
96 const NPUTF8 * const LibvlcRootNPObject::propertyNames[] =
105 COUNTNAMES(LibvlcRootNPObject,propertyCount,propertyNames);
107 enum LibvlcRootNPObjectPropertyIds
117 RuntimeNPObject::InvokeResult
118 LibvlcRootNPObject::getProperty(int index, NPVariant &result)
120 /* is plugin still running */
121 if( isPluginRunning() )
126 InstantObj<LibvlcAudioNPObject>( audioObj );
127 OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result);
128 return INVOKERESULT_NO_ERROR;
130 InstantObj<LibvlcInputNPObject>( inputObj );
131 OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), result);
132 return INVOKERESULT_NO_ERROR;
133 case ID_root_playlist:
134 InstantObj<LibvlcPlaylistNPObject>( playlistObj );
135 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), result);
136 return INVOKERESULT_NO_ERROR;
137 case ID_root_subtitle:
138 InstantObj<LibvlcSubtitleNPObject>( subtitleObj );
139 OBJECT_TO_NPVARIANT(NPN_RetainObject(subtitleObj), result);
140 return INVOKERESULT_NO_ERROR;
142 InstantObj<LibvlcVideoNPObject>( videoObj );
143 OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result);
144 return INVOKERESULT_NO_ERROR;
145 case ID_root_VersionInfo:
146 return invokeResultString(libvlc_get_version(),result);
151 return INVOKERESULT_GENERIC_ERROR;
154 const NPUTF8 * const LibvlcRootNPObject::methodNames[] =
158 "removeEventListener",
160 COUNTNAMES(LibvlcRootNPObject,methodCount,methodNames);
162 enum LibvlcRootNPObjectMethodIds
165 ID_root_addeventlistener,
166 ID_root_removeeventlistener,
169 RuntimeNPObject::InvokeResult LibvlcRootNPObject::invoke(int index,
170 const NPVariant *args, uint32_t argCount, NPVariant &result)
172 /* is plugin still running */
173 if( !isPluginRunning() )
174 return INVOKERESULT_GENERIC_ERROR;
178 case ID_root_versionInfo:
180 return INVOKERESULT_NO_SUCH_METHOD;
181 return invokeResultString(libvlc_get_version(),result);
183 case ID_root_addeventlistener:
184 case ID_root_removeeventlistener:
185 if( (3 != argCount) ||
186 !NPVARIANT_IS_STRING(args[0]) ||
187 !NPVARIANT_IS_OBJECT(args[1]) ||
188 !NPVARIANT_IS_BOOLEAN(args[2]) )
191 if( !VlcPlugin::canUseEventListener() )
193 NPN_SetException(this, ERROR_API_VERSION);
194 return INVOKERESULT_GENERIC_ERROR;
197 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
200 if( ID_root_addeventlistener == index )
202 NPN_RetainObject( NPVARIANT_TO_OBJECT(args[1]) );
203 b = p_plugin->events.insert( NPVARIANT_TO_STRING(args[0]),
204 NPVARIANT_TO_OBJECT(args[1]),
205 NPVARIANT_TO_BOOLEAN(args[2]) );
207 NPN_ReleaseObject( NPVARIANT_TO_OBJECT(args[1]) );
211 b = p_plugin->events.remove( NPVARIANT_TO_STRING(args[0]),
212 NPVARIANT_TO_OBJECT(args[1]),
213 NPVARIANT_TO_BOOLEAN(args[2]) );
215 NPN_ReleaseObject( NPVARIANT_TO_OBJECT(args[1]) );
217 VOID_TO_NPVARIANT(result);
219 return b ? INVOKERESULT_NO_ERROR : INVOKERESULT_GENERIC_ERROR;
221 return INVOKERESULT_NO_SUCH_METHOD;
225 ** implementation of libvlc audio object
228 const NPUTF8 * const LibvlcAudioNPObject::propertyNames[] =
236 COUNTNAMES(LibvlcAudioNPObject,propertyCount,propertyNames);
238 enum LibvlcAudioNPObjectPropertyIds
247 RuntimeNPObject::InvokeResult
248 LibvlcAudioNPObject::getProperty(int index, NPVariant &result)
250 /* is plugin still running */
251 if( isPluginRunning() )
253 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
255 libvlc_media_player_t *p_md = p_plugin->getMD();
263 bool muted = libvlc_audio_get_mute(p_md);
264 BOOLEAN_TO_NPVARIANT(muted, result);
265 return INVOKERESULT_NO_ERROR;
267 case ID_audio_volume:
269 int volume = libvlc_audio_get_volume(p_md);
270 INT32_TO_NPVARIANT(volume, result);
271 return INVOKERESULT_NO_ERROR;
275 int track = libvlc_audio_get_track(p_md);
276 INT32_TO_NPVARIANT(track, result);
277 return INVOKERESULT_NO_ERROR;
281 // get the number of audio track available
282 int i_track = libvlc_audio_get_track_count(p_md);
284 INT32_TO_NPVARIANT(i_track, result);
285 return INVOKERESULT_NO_ERROR;
287 case ID_audio_channel:
289 int channel = libvlc_audio_get_channel(p_md);
290 INT32_TO_NPVARIANT(channel, result);
291 return INVOKERESULT_NO_ERROR;
297 return INVOKERESULT_GENERIC_ERROR;
300 RuntimeNPObject::InvokeResult
301 LibvlcAudioNPObject::setProperty(int index, const NPVariant &value)
303 /* is plugin still running */
304 if( isPluginRunning() )
306 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
308 libvlc_media_player_t *p_md = p_plugin->getMD();
315 if( NPVARIANT_IS_BOOLEAN(value) )
317 libvlc_audio_set_mute(p_md,
318 NPVARIANT_TO_BOOLEAN(value));
319 return INVOKERESULT_NO_ERROR;
321 return INVOKERESULT_INVALID_VALUE;
322 case ID_audio_volume:
323 if( isNumberValue(value) )
325 libvlc_audio_set_volume(p_md, numberValue(value));
326 return INVOKERESULT_NO_ERROR;
328 return INVOKERESULT_INVALID_VALUE;
330 if( isNumberValue(value) )
332 libvlc_audio_set_track(p_md, numberValue(value));
333 return INVOKERESULT_NO_ERROR;
335 return INVOKERESULT_INVALID_VALUE;
336 case ID_audio_channel:
337 if( isNumberValue(value) )
339 libvlc_audio_set_channel(p_md, numberValue(value));
340 return INVOKERESULT_NO_ERROR;
342 return INVOKERESULT_INVALID_VALUE;
347 return INVOKERESULT_GENERIC_ERROR;
350 const NPUTF8 * const LibvlcAudioNPObject::methodNames[] =
355 COUNTNAMES(LibvlcAudioNPObject,methodCount,methodNames);
357 enum LibvlcAudioNPObjectMethodIds
360 ID_audio_description,
363 RuntimeNPObject::InvokeResult
364 LibvlcAudioNPObject::invoke(int index, const NPVariant *args,
365 uint32_t argCount, NPVariant &result)
367 /* is plugin still running */
368 if( isPluginRunning() )
370 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
371 libvlc_media_player_t *p_md = p_plugin->getMD();
377 case ID_audio_togglemute:
380 libvlc_audio_toggle_mute(p_md);
381 VOID_TO_NPVARIANT(result);
382 return INVOKERESULT_NO_ERROR;
384 return INVOKERESULT_NO_SUCH_METHOD;
385 case ID_audio_description:
390 int i_trackID, i_limit, i;
391 libvlc_track_description_t *p_trackDesc;
393 /* get tracks description */
394 p_trackDesc = libvlc_audio_get_track_description(p_md);
396 return INVOKERESULT_GENERIC_ERROR;
398 /* get the number of track available */
399 i_limit = libvlc_audio_get_track_count(p_md);
401 /* check if a number is given by the user
402 * and get the track number */
403 if( isNumberValue(args[0]) )
404 i_trackID = numberValue(args[0]);
406 return INVOKERESULT_INVALID_VALUE;
408 /* if bad number is given return invalid value */
409 if ( ( i_trackID > ( i_limit - 1 ) ) || ( i_trackID < 0 ) )
410 return INVOKERESULT_INVALID_VALUE;
412 /* get the good trackDesc */
413 for( i = 0 ; i < i_trackID ; i++ )
415 p_trackDesc = p_trackDesc->p_next;
417 psz_name = p_trackDesc->psz_name;
419 /* display the name of the track chosen */
420 return invokeResultString( psz_name, result );
422 return INVOKERESULT_NO_SUCH_METHOD;
428 return INVOKERESULT_GENERIC_ERROR;
432 ** implementation of libvlc input object
435 const NPUTF8 * const LibvlcInputNPObject::propertyNames[] =
445 COUNTNAMES(LibvlcInputNPObject,propertyCount,propertyNames);
447 enum LibvlcInputNPObjectPropertyIds
458 RuntimeNPObject::InvokeResult
459 LibvlcInputNPObject::getProperty(int index, NPVariant &result)
461 /* is plugin still running */
462 if( isPluginRunning() )
464 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
465 libvlc_media_player_t *p_md = p_plugin->getMD();
468 if( index != ID_input_state )
472 /* for input state, return CLOSED rather than an exception */
473 INT32_TO_NPVARIANT(0, result);
474 return INVOKERESULT_NO_ERROR;
480 case ID_input_length:
482 double val = (double)libvlc_media_player_get_length(p_md);
483 DOUBLE_TO_NPVARIANT(val, result);
484 return INVOKERESULT_NO_ERROR;
486 case ID_input_position:
488 double val = libvlc_media_player_get_position(p_md);
489 DOUBLE_TO_NPVARIANT(val, result);
490 return INVOKERESULT_NO_ERROR;
494 double val = (double)libvlc_media_player_get_time(p_md);
495 DOUBLE_TO_NPVARIANT(val, result);
496 return INVOKERESULT_NO_ERROR;
500 int val = libvlc_media_player_get_state(p_md);
501 INT32_TO_NPVARIANT(val, result);
502 return INVOKERESULT_NO_ERROR;
506 float val = libvlc_media_player_get_rate(p_md);
507 DOUBLE_TO_NPVARIANT(val, result);
508 return INVOKERESULT_NO_ERROR;
512 double val = libvlc_media_player_get_fps(p_md);
513 DOUBLE_TO_NPVARIANT(val, result);
514 return INVOKERESULT_NO_ERROR;
516 case ID_input_hasvout:
518 bool val = p_plugin->player_has_vout();
519 BOOLEAN_TO_NPVARIANT(val, result);
520 return INVOKERESULT_NO_ERROR;
526 return INVOKERESULT_GENERIC_ERROR;
529 RuntimeNPObject::InvokeResult
530 LibvlcInputNPObject::setProperty(int index, const NPVariant &value)
532 /* is plugin still running */
533 if( isPluginRunning() )
535 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
536 libvlc_media_player_t *p_md = p_plugin->getMD();
542 case ID_input_position:
544 if( ! NPVARIANT_IS_DOUBLE(value) )
546 return INVOKERESULT_INVALID_VALUE;
549 float val = (float)NPVARIANT_TO_DOUBLE(value);
550 libvlc_media_player_set_position(p_md, val);
551 return INVOKERESULT_NO_ERROR;
556 if( NPVARIANT_IS_INT32(value) )
557 val = (int64_t)NPVARIANT_TO_INT32(value);
558 else if( NPVARIANT_IS_DOUBLE(value) )
559 val = (int64_t)NPVARIANT_TO_DOUBLE(value);
562 return INVOKERESULT_INVALID_VALUE;
565 libvlc_media_player_set_time(p_md, val);
566 return INVOKERESULT_NO_ERROR;
571 if( NPVARIANT_IS_INT32(value) )
572 val = (float)NPVARIANT_TO_INT32(value);
573 else if( NPVARIANT_IS_DOUBLE(value) )
574 val = (float)NPVARIANT_TO_DOUBLE(value);
577 return INVOKERESULT_INVALID_VALUE;
580 libvlc_media_player_set_rate(p_md, val);
581 return INVOKERESULT_NO_ERROR;
587 return INVOKERESULT_GENERIC_ERROR;
590 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =
595 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
597 enum LibvlcInputNPObjectMethodIds
602 RuntimeNPObject::InvokeResult
603 LibvlcInputNPObject::invoke(int index, const NPVariant *args,
604 uint32_t argCount, NPVariant &result)
606 /* is plugin still running */
607 if( isPluginRunning() )
612 return INVOKERESULT_NO_SUCH_METHOD;
617 return INVOKERESULT_GENERIC_ERROR;
621 ** implementation of libvlc playlist items object
624 const NPUTF8 * const LibvlcPlaylistItemsNPObject::propertyNames[] =
628 COUNTNAMES(LibvlcPlaylistItemsNPObject,propertyCount,propertyNames);
630 enum LibvlcPlaylistItemsNPObjectPropertyIds
632 ID_playlistitems_count,
635 RuntimeNPObject::InvokeResult
636 LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
638 /* is plugin still running */
639 if( isPluginRunning() )
641 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
645 case ID_playlistitems_count:
647 int val = p_plugin->playlist_count();
648 INT32_TO_NPVARIANT(val, result);
649 return INVOKERESULT_NO_ERROR;
655 return INVOKERESULT_GENERIC_ERROR;
658 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
663 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
665 enum LibvlcPlaylistItemsNPObjectMethodIds
667 ID_playlistitems_clear,
668 ID_playlistitems_remove,
671 RuntimeNPObject::InvokeResult
672 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
673 uint32_t argCount, NPVariant &result)
675 /* is plugin still running */
676 if( isPluginRunning() )
678 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
682 case ID_playlistitems_clear:
685 p_plugin->playlist_clear();
686 VOID_TO_NPVARIANT(result);
687 return INVOKERESULT_NO_ERROR;
689 return INVOKERESULT_NO_SUCH_METHOD;
690 case ID_playlistitems_remove:
691 if( (argCount == 1) && isNumberValue(args[0]) )
693 if( !p_plugin->playlist_delete_item(numberValue(args[0])) )
694 return INVOKERESULT_GENERIC_ERROR;
695 VOID_TO_NPVARIANT(result);
696 return INVOKERESULT_NO_ERROR;
698 return INVOKERESULT_NO_SUCH_METHOD;
703 return INVOKERESULT_GENERIC_ERROR;
707 ** implementation of libvlc playlist object
710 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
712 // Why the isValid()?
713 if( isValid() && playlistItemsObj )
714 NPN_ReleaseObject(playlistItemsObj);
717 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
719 "itemCount", /* deprecated */
723 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
725 enum LibvlcPlaylistNPObjectPropertyIds
727 ID_playlist_itemcount,
728 ID_playlist_isplaying,
732 RuntimeNPObject::InvokeResult
733 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
735 /* is plugin still running */
736 if( isPluginRunning() )
738 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
742 case ID_playlist_itemcount: /* deprecated */
744 int val = p_plugin->playlist_count();
745 INT32_TO_NPVARIANT(val, result);
746 return INVOKERESULT_NO_ERROR;
748 case ID_playlist_isplaying:
750 int val = p_plugin->playlist_isplaying();
751 BOOLEAN_TO_NPVARIANT(val, result);
752 return INVOKERESULT_NO_ERROR;
754 case ID_playlist_items:
756 InstantObj<LibvlcPlaylistItemsNPObject>( playlistItemsObj );
757 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
758 return INVOKERESULT_NO_ERROR;
764 return INVOKERESULT_GENERIC_ERROR;
767 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
776 "clear", /* deprecated */
777 "removeItem", /* deprecated */
779 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
781 enum LibvlcPlaylistNPObjectMethodIds
785 ID_playlist_playItem,
786 ID_playlist_togglepause,
791 ID_playlist_removeitem
794 RuntimeNPObject::InvokeResult
795 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
796 uint32_t argCount, NPVariant &result)
798 /* is plugin still running */
799 if( isPluginRunning() )
801 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
805 // XXX FIXME this needs squashing into something much smaller
806 case ID_playlist_add:
808 if( (argCount < 1) || (argCount > 3) )
809 return INVOKERESULT_NO_SUCH_METHOD;
810 if( !NPVARIANT_IS_STRING(args[0]) )
811 return INVOKERESULT_NO_SUCH_METHOD;
814 if( NPVARIANT_IS_NULL(args[0]) )
815 return INVOKERESULT_NO_SUCH_METHOD;
817 char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
819 return INVOKERESULT_OUT_OF_MEMORY;
821 char *url = p_plugin->getAbsoluteURL(s);
825 // problem with combining url, use argument
830 // grab name if available
833 if( NPVARIANT_IS_NULL(args[1]) )
837 else if( NPVARIANT_IS_STRING(args[1]) )
839 name = stringValue(NPVARIANT_TO_STRING(args[1]));
844 return INVOKERESULT_INVALID_VALUE;
849 char** ppsz_options = NULL;
851 // grab options if available
854 if( NPVARIANT_IS_NULL(args[2]) )
858 else if( NPVARIANT_IS_STRING(args[2]) )
860 parseOptions(NPVARIANT_TO_STRING(args[2]),
861 &i_options, &ppsz_options);
864 else if( NPVARIANT_IS_OBJECT(args[2]) )
866 parseOptions(NPVARIANT_TO_OBJECT(args[2]),
867 &i_options, &ppsz_options);
873 return INVOKERESULT_INVALID_VALUE;
877 int item = p_plugin->playlist_add_extended_untrusted(url, name,
878 i_options, const_cast<const char **>(ppsz_options));
884 for( int i=0; i< i_options; ++i )
886 free(ppsz_options[i]);
890 INT32_TO_NPVARIANT(item, result);
891 return INVOKERESULT_NO_ERROR;
893 case ID_playlist_play:
896 p_plugin->playlist_play();
897 VOID_TO_NPVARIANT(result);
898 return INVOKERESULT_NO_ERROR;
900 return INVOKERESULT_NO_SUCH_METHOD;
901 case ID_playlist_playItem:
902 if( (argCount == 1) && isNumberValue(args[0]) )
904 p_plugin->playlist_play_item(numberValue(args[0]));
905 VOID_TO_NPVARIANT(result);
906 return INVOKERESULT_NO_ERROR;
908 return INVOKERESULT_NO_SUCH_METHOD;
909 case ID_playlist_togglepause:
912 p_plugin->playlist_pause();
913 VOID_TO_NPVARIANT(result);
914 return INVOKERESULT_NO_ERROR;
916 return INVOKERESULT_NO_SUCH_METHOD;
917 case ID_playlist_stop:
920 p_plugin->playlist_stop();
921 VOID_TO_NPVARIANT(result);
922 return INVOKERESULT_NO_ERROR;
924 return INVOKERESULT_NO_SUCH_METHOD;
925 case ID_playlist_next:
928 p_plugin->playlist_next();
929 VOID_TO_NPVARIANT(result);
930 return INVOKERESULT_NO_ERROR;
932 return INVOKERESULT_NO_SUCH_METHOD;
933 case ID_playlist_prev:
936 p_plugin->playlist_prev();
937 VOID_TO_NPVARIANT(result);
938 return INVOKERESULT_NO_ERROR;
940 return INVOKERESULT_NO_SUCH_METHOD;
941 case ID_playlist_clear: /* deprecated */
944 p_plugin->playlist_clear();
945 VOID_TO_NPVARIANT(result);
946 return INVOKERESULT_NO_ERROR;
948 return INVOKERESULT_NO_SUCH_METHOD;
949 case ID_playlist_removeitem: /* deprecated */
950 if( (argCount == 1) && isNumberValue(args[0]) )
952 if( !p_plugin->playlist_delete_item(numberValue(args[0])) )
953 return INVOKERESULT_GENERIC_ERROR;
954 VOID_TO_NPVARIANT(result);
955 return INVOKERESULT_NO_ERROR;
957 return INVOKERESULT_NO_SUCH_METHOD;
962 return INVOKERESULT_GENERIC_ERROR;
965 // XXX FIXME The new playlist_add creates a media instance and feeds it
966 // XXX FIXME these options one at a time, so this hunk of code does lots
967 // XXX FIXME of unnecessairy work. Break out something that can do one
968 // XXX FIXME option at a time and doesn't need to realloc().
969 // XXX FIXME Same for the other version of parseOptions.
971 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
972 int *i_options, char*** ppsz_options)
976 char *s = stringValue(nps);
981 char **options = (char **)malloc(capacity*sizeof(char *));
986 char *end = val + nps.UTF8Length;
989 // skip leading blanks
991 && ((*val == ' ' ) || (*val == '\t')) )
995 // skip till we get a blank character
1001 if( ('\'' == c) || ('"' == c) )
1003 // skip till end of string
1004 while( (val < end) && (*(val++) != c ) );
1010 if( nOptions == capacity )
1013 char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1016 /* failed to allocate more memory */
1018 /* return what we got so far */
1019 *i_options = nOptions;
1020 *ppsz_options = options;
1023 options = moreOptions;
1026 options[nOptions++] = strdup(start);
1029 // must be end of string
1032 *i_options = nOptions;
1033 *ppsz_options = options;
1040 // XXX FIXME See comment at the other parseOptions variant.
1041 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
1042 char*** ppsz_options)
1044 /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1048 /* we are expecting to have a Javascript Array object */
1049 NPIdentifier propId = NPN_GetStringIdentifier("length");
1050 if( NPN_GetProperty(_instance, obj, propId, &value) )
1052 int count = numberValue(value);
1053 NPN_ReleaseVariantValue(&value);
1058 char **options = (char **)malloc(capacity*sizeof(char *));
1063 while( nOptions < count )
1065 propId = NPN_GetIntIdentifier(nOptions);
1066 if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1067 /* return what we got so far */
1070 if( ! NPVARIANT_IS_STRING(value) )
1072 /* return what we got so far */
1073 NPN_ReleaseVariantValue(&value);
1077 if( nOptions == capacity )
1080 char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1083 /* failed to allocate more memory */
1084 NPN_ReleaseVariantValue(&value);
1085 /* return what we got so far */
1086 *i_options = nOptions;
1087 *ppsz_options = options;
1090 options = moreOptions;
1093 options[nOptions++] = stringValue(value);
1094 NPN_ReleaseVariantValue(&value);
1096 *i_options = nOptions;
1097 *ppsz_options = options;
1104 ** implementation of libvlc subtitle object
1107 const NPUTF8 * const LibvlcSubtitleNPObject::propertyNames[] =
1113 enum LibvlcSubtitleNPObjectPropertyIds
1118 COUNTNAMES(LibvlcSubtitleNPObject,propertyCount,propertyNames);
1120 RuntimeNPObject::InvokeResult
1121 LibvlcSubtitleNPObject::getProperty(int index, NPVariant &result)
1123 /* is plugin still running */
1124 if( isPluginRunning() )
1126 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1127 libvlc_media_player_t *p_md = p_plugin->getMD();
1133 case ID_subtitle_track:
1135 /* get the current subtitle ID */
1136 int i_spu = libvlc_video_get_spu(p_md);
1138 INT32_TO_NPVARIANT(i_spu, result);
1139 return INVOKERESULT_NO_ERROR;
1141 case ID_subtitle_count:
1143 /* get the number of subtitles available */
1144 int i_spu = libvlc_video_get_spu_count(p_md);
1146 INT32_TO_NPVARIANT(i_spu, result);
1147 return INVOKERESULT_NO_ERROR;
1151 return INVOKERESULT_GENERIC_ERROR;
1154 RuntimeNPObject::InvokeResult
1155 LibvlcSubtitleNPObject::setProperty(int index, const NPVariant &value)
1157 /* is plugin still running */
1158 if( isPluginRunning() )
1160 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1161 libvlc_media_player_t *p_md = p_plugin->getMD();
1167 case ID_subtitle_track:
1169 if( isNumberValue(value) )
1171 /* set the new subtitle track to show */
1172 libvlc_video_set_spu(p_md, numberValue(value));
1174 return INVOKERESULT_NO_ERROR;
1176 return INVOKERESULT_INVALID_VALUE;
1180 return INVOKERESULT_GENERIC_ERROR;
1183 const NPUTF8 * const LibvlcSubtitleNPObject::methodNames[] =
1187 COUNTNAMES(LibvlcSubtitleNPObject,methodCount,methodNames);
1189 enum LibvlcSubtitleNPObjectMethodIds
1191 ID_subtitle_description
1194 RuntimeNPObject::InvokeResult
1195 LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
1196 uint32_t argCount, NPVariant &result)
1198 /* is plugin still running */
1199 if( isPluginRunning() )
1201 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1202 libvlc_media_player_t *p_md = p_plugin->getMD();
1208 case ID_subtitle_description:
1213 int i_spuID, i_limit, i;
1214 libvlc_track_description_t *p_spuDesc;
1216 /* get subtitles description */
1217 p_spuDesc = libvlc_video_get_spu_description(p_md);
1219 return INVOKERESULT_GENERIC_ERROR;
1221 /* get the number of subtitle available */
1222 i_limit = libvlc_video_get_spu_count(p_md);
1224 /* check if a number is given by the user
1225 * and get the subtitle number */
1226 if( isNumberValue(args[0]) )
1227 i_spuID = numberValue(args[0]);
1229 return INVOKERESULT_INVALID_VALUE;
1231 /* if bad number is given return invalid value */
1232 if ( ( i_spuID > ( i_limit -1 ) ) || ( i_spuID < 0 ) )
1233 return INVOKERESULT_INVALID_VALUE;
1235 /* get the good spuDesc */
1236 for( i = 0 ; i < i_spuID ; i++ )
1238 p_spuDesc = p_spuDesc->p_next;
1240 psz_name = p_spuDesc->psz_name;
1242 /* return the name of the track chosen */
1243 return invokeResultString(psz_name, result);
1245 return INVOKERESULT_NO_SUCH_METHOD;
1248 return INVOKERESULT_NO_SUCH_METHOD;
1251 return INVOKERESULT_GENERIC_ERROR;
1255 ** implementation of libvlc video object
1258 LibvlcVideoNPObject::~LibvlcVideoNPObject()
1262 if( marqueeObj ) NPN_ReleaseObject(marqueeObj);
1263 if( logoObj ) NPN_ReleaseObject(logoObj);
1264 if( deintObj ) NPN_ReleaseObject(deintObj);
1268 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1282 enum LibvlcVideoNPObjectPropertyIds
1284 ID_video_fullscreen,
1287 ID_video_aspectratio,
1293 ID_video_deinterlace,
1295 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1297 RuntimeNPObject::InvokeResult
1298 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1300 /* is plugin still running */
1301 if( isPluginRunning() )
1303 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1304 libvlc_media_player_t *p_md = p_plugin->getMD();
1310 case ID_video_fullscreen:
1312 int val = p_plugin->get_fullscreen();
1313 BOOLEAN_TO_NPVARIANT(val, result);
1314 return INVOKERESULT_NO_ERROR;
1316 case ID_video_height:
1318 int val = libvlc_video_get_height(p_md);
1319 INT32_TO_NPVARIANT(val, result);
1320 return INVOKERESULT_NO_ERROR;
1322 case ID_video_width:
1324 int val = libvlc_video_get_width(p_md);
1325 INT32_TO_NPVARIANT(val, result);
1326 return INVOKERESULT_NO_ERROR;
1328 case ID_video_aspectratio:
1330 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md);
1332 return INVOKERESULT_GENERIC_ERROR;
1334 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1335 return INVOKERESULT_NO_ERROR;
1337 case ID_video_subtitle:
1339 int i_spu = libvlc_video_get_spu(p_md);
1340 INT32_TO_NPVARIANT(i_spu, result);
1341 return INVOKERESULT_NO_ERROR;
1345 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md);
1347 return INVOKERESULT_GENERIC_ERROR;
1349 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1350 return INVOKERESULT_NO_ERROR;
1352 case ID_video_teletext:
1354 int i_page = libvlc_video_get_teletext(p_md);
1356 return INVOKERESULT_GENERIC_ERROR;
1357 INT32_TO_NPVARIANT(i_page, result);
1358 return INVOKERESULT_NO_ERROR;
1360 case ID_video_marquee:
1362 InstantObj<LibvlcMarqueeNPObject>( marqueeObj );
1363 OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1364 return INVOKERESULT_NO_ERROR;
1368 InstantObj<LibvlcLogoNPObject>( logoObj );
1369 OBJECT_TO_NPVARIANT(NPN_RetainObject(logoObj), result);
1370 return INVOKERESULT_NO_ERROR;
1372 case ID_video_deinterlace:
1374 InstantObj<LibvlcDeinterlaceNPObject>( deintObj );
1375 OBJECT_TO_NPVARIANT(NPN_RetainObject(deintObj), result);
1376 return INVOKERESULT_NO_ERROR;
1380 return INVOKERESULT_GENERIC_ERROR;
1383 RuntimeNPObject::InvokeResult
1384 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1386 /* is plugin still running */
1387 if( isPluginRunning() )
1389 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1390 libvlc_media_player_t *p_md = p_plugin->getMD();
1396 case ID_video_fullscreen:
1398 if( ! NPVARIANT_IS_BOOLEAN(value) )
1400 return INVOKERESULT_INVALID_VALUE;
1403 int val = NPVARIANT_TO_BOOLEAN(value);
1404 p_plugin->set_fullscreen(val);
1405 return INVOKERESULT_NO_ERROR;
1407 case ID_video_aspectratio:
1409 char *psz_aspect = NULL;
1411 if( ! NPVARIANT_IS_STRING(value) )
1413 return INVOKERESULT_INVALID_VALUE;
1416 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1419 return INVOKERESULT_GENERIC_ERROR;
1422 libvlc_video_set_aspect_ratio(p_md, psz_aspect);
1425 return INVOKERESULT_NO_ERROR;
1427 case ID_video_subtitle:
1429 if( isNumberValue(value) )
1431 libvlc_video_set_spu(p_md, numberValue(value));
1433 return INVOKERESULT_NO_ERROR;
1435 return INVOKERESULT_INVALID_VALUE;
1439 char *psz_geometry = NULL;
1441 if( ! NPVARIANT_IS_STRING(value) )
1443 return INVOKERESULT_INVALID_VALUE;
1446 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1449 return INVOKERESULT_GENERIC_ERROR;
1452 libvlc_video_set_crop_geometry(p_md, psz_geometry);
1455 return INVOKERESULT_NO_ERROR;
1457 case ID_video_teletext:
1459 if( isNumberValue(value) )
1461 libvlc_video_set_teletext(p_md, numberValue(value));
1462 return INVOKERESULT_NO_ERROR;
1464 return INVOKERESULT_INVALID_VALUE;
1468 return INVOKERESULT_GENERIC_ERROR;
1471 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1476 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1478 enum LibvlcVideoNPObjectMethodIds
1480 ID_video_togglefullscreen,
1481 ID_video_toggleteletext,
1484 RuntimeNPObject::InvokeResult
1485 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1486 uint32_t argCount, NPVariant &result)
1488 /* is plugin still running */
1489 if( isPluginRunning() )
1491 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1492 libvlc_media_player_t *p_md = p_plugin->getMD();
1498 case ID_video_togglefullscreen:
1502 p_plugin->toggle_fullscreen();
1503 VOID_TO_NPVARIANT(result);
1504 return INVOKERESULT_NO_ERROR;
1506 return INVOKERESULT_NO_SUCH_METHOD;
1508 case ID_video_toggleteletext:
1512 libvlc_toggle_teletext(p_md);
1513 VOID_TO_NPVARIANT(result);
1514 return INVOKERESULT_NO_ERROR;
1516 return INVOKERESULT_NO_SUCH_METHOD;
1519 return INVOKERESULT_NO_SUCH_METHOD;
1522 return INVOKERESULT_GENERIC_ERROR;
1526 ** implementation of libvlc marquee object
1529 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1542 enum LibvlcMarqueeNPObjectPropertyIds
1546 ID_marquee_position,
1555 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
1557 static const unsigned char marquee_idx[] = {
1558 libvlc_marquee_Color,
1559 libvlc_marquee_Opacity,
1560 libvlc_marquee_Position,
1561 libvlc_marquee_Refresh,
1562 libvlc_marquee_Size,
1564 libvlc_marquee_Timeout,
1569 RuntimeNPObject::InvokeResult
1570 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1574 if( !isPluginRunning() )
1575 return INVOKERESULT_GENERIC_ERROR;
1577 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1578 libvlc_media_player_t *p_md = p_plugin->getMD();
1584 case ID_marquee_color:
1585 case ID_marquee_opacity:
1586 case ID_marquee_refresh:
1587 case ID_marquee_timeout:
1588 case ID_marquee_size:
1592 libvlc_video_get_marquee_int(p_md, marquee_idx[index]),
1594 return INVOKERESULT_NO_ERROR;
1596 case ID_marquee_position:
1597 STRINGZ_TO_NPVARIANT( position_bynumber(
1598 libvlc_video_get_marquee_int(p_md, libvlc_marquee_Position) ),
1603 case ID_marquee_text:
1604 psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text);
1607 STRINGZ_TO_NPVARIANT(psz, result);
1608 return INVOKERESULT_NO_ERROR;
1612 return INVOKERESULT_GENERIC_ERROR;
1615 RuntimeNPObject::InvokeResult
1616 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1620 if( !isPluginRunning() )
1621 return INVOKERESULT_GENERIC_ERROR;
1623 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1624 libvlc_media_player_t *p_md = p_plugin->getMD();
1630 case ID_marquee_color:
1631 case ID_marquee_opacity:
1632 case ID_marquee_refresh:
1633 case ID_marquee_timeout:
1636 if( NPVARIANT_IS_INT32( value ) )
1638 libvlc_video_set_marquee_int(p_md, marquee_idx[index],
1639 NPVARIANT_TO_INT32( value ));
1640 return INVOKERESULT_NO_ERROR;
1644 case ID_marquee_position:
1645 if( !NPVARIANT_IS_STRING(value) ||
1646 !position_byname( NPVARIANT_TO_STRING(value).UTF8Characters, i ) )
1647 return INVOKERESULT_INVALID_VALUE;
1649 libvlc_video_set_marquee_int(p_md, libvlc_marquee_Position, i);
1650 return INVOKERESULT_NO_ERROR;
1652 case ID_marquee_text:
1653 if( NPVARIANT_IS_STRING( value ) )
1655 char *psz_text = stringValue( NPVARIANT_TO_STRING( value ) );
1656 libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
1659 return INVOKERESULT_NO_ERROR;
1663 return INVOKERESULT_NO_SUCH_METHOD;
1666 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1671 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1673 enum LibvlcMarqueeNPObjectMethodIds
1679 RuntimeNPObject::InvokeResult
1680 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1681 uint32_t argCount, NPVariant &result)
1683 if( !isPluginRunning() )
1684 return INVOKERESULT_GENERIC_ERROR;
1686 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1687 libvlc_media_player_t *p_md = p_plugin->getMD();
1693 case ID_marquee_enable:
1694 case ID_marquee_disable:
1695 libvlc_video_set_marquee_int(p_md, libvlc_marquee_Enable,
1696 index!=ID_marquee_disable);
1697 VOID_TO_NPVARIANT(result);
1698 return INVOKERESULT_NO_ERROR;
1700 return INVOKERESULT_NO_SUCH_METHOD;
1703 const NPUTF8 * const LibvlcLogoNPObject::propertyNames[] = {
1711 enum LibvlcLogoNPObjectPropertyIds {
1719 COUNTNAMES(LibvlcLogoNPObject,propertyCount,propertyNames);
1720 static const unsigned char logo_idx[] = {
1723 libvlc_logo_opacity,
1729 RuntimeNPObject::InvokeResult
1730 LibvlcLogoNPObject::getProperty(int index, NPVariant &result)
1732 if( !isPluginRunning() )
1733 return INVOKERESULT_GENERIC_ERROR;
1735 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1736 libvlc_media_player_t *p_md = p_plugin->getMD();
1743 case ID_logo_repeat:
1744 case ID_logo_opacity:
1749 libvlc_video_get_logo_int(p_md, logo_idx[index]), result);
1752 case ID_logo_position:
1753 STRINGZ_TO_NPVARIANT( position_bynumber(
1754 libvlc_video_get_logo_int(p_md, libvlc_logo_position) ),
1758 return INVOKERESULT_GENERIC_ERROR;
1760 return INVOKERESULT_NO_ERROR;
1763 RuntimeNPObject::InvokeResult
1764 LibvlcLogoNPObject::setProperty(int index, const NPVariant &value)
1768 if( !isPluginRunning() )
1769 return INVOKERESULT_GENERIC_ERROR;
1771 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1772 libvlc_media_player_t *p_md = p_plugin->getMD();
1779 case ID_logo_repeat:
1780 case ID_logo_opacity:
1783 if( !NPVARIANT_IS_INT32(value) )
1784 return INVOKERESULT_INVALID_VALUE;
1786 libvlc_video_set_logo_int(p_md, logo_idx[index],
1787 NPVARIANT_TO_INT32( value ));
1790 case ID_logo_position:
1791 if( !NPVARIANT_IS_STRING(value) ||
1792 !position_byname( NPVARIANT_TO_STRING(value).UTF8Characters, i ) )
1793 return INVOKERESULT_INVALID_VALUE;
1795 libvlc_video_set_logo_int(p_md, libvlc_logo_position, i);
1798 return INVOKERESULT_GENERIC_ERROR;
1800 return INVOKERESULT_NO_ERROR;
1804 const NPUTF8 * const LibvlcLogoNPObject::methodNames[] = {
1809 enum LibvlcLogoNPObjectMethodIds {
1814 COUNTNAMES(LibvlcLogoNPObject,methodCount,methodNames);
1816 RuntimeNPObject::InvokeResult
1817 LibvlcLogoNPObject::invoke(int index, const NPVariant *args,
1818 uint32_t argCount, NPVariant &result)
1823 if( !isPluginRunning() )
1824 return INVOKERESULT_GENERIC_ERROR;
1826 libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD();
1832 case ID_logo_enable:
1833 case ID_logo_disable:
1835 return INVOKERESULT_GENERIC_ERROR;
1837 libvlc_video_set_logo_int(p_md, libvlc_logo_enable,
1838 index != ID_logo_disable);
1839 VOID_TO_NPVARIANT(result);
1844 return INVOKERESULT_GENERIC_ERROR;
1846 for( len=0,i=0;i<argCount;++i )
1848 if( !NPVARIANT_IS_STRING(args[i]) )
1849 return INVOKERESULT_INVALID_VALUE;
1850 len+=NPVARIANT_TO_STRING(args[i]).UTF8Length+1;
1853 buf = (char *)malloc( len+1 );
1855 return INVOKERESULT_OUT_OF_MEMORY;
1857 for( h=buf,i=0;i<argCount;++i )
1860 len=NPVARIANT_TO_STRING(args[i]).UTF8Length;
1861 memcpy(h,NPVARIANT_TO_STRING(args[i]).UTF8Characters,len);
1866 libvlc_video_set_logo_string(p_md, libvlc_logo_file, buf);
1868 VOID_TO_NPVARIANT(result);
1871 return INVOKERESULT_NO_SUCH_METHOD;
1873 return INVOKERESULT_NO_ERROR;
1877 const NPUTF8 * const LibvlcDeinterlaceNPObject::propertyNames[] = {
1879 enum LibvlcDeinterlaceNPObjectPropertyIds {
1881 COUNTNAMES(LibvlcDeinterlaceNPObject,propertyCount,propertyNames);
1883 RuntimeNPObject::InvokeResult
1884 LibvlcDeinterlaceNPObject::getProperty(int index, NPVariant &result)
1886 return INVOKERESULT_GENERIC_ERROR;
1889 RuntimeNPObject::InvokeResult
1890 LibvlcDeinterlaceNPObject::setProperty(int index, const NPVariant &value)
1892 return INVOKERESULT_GENERIC_ERROR;
1896 const NPUTF8 * const LibvlcDeinterlaceNPObject::methodNames[] = {
1900 enum LibvlcDeinterlaceNPObjectMethodIds {
1904 COUNTNAMES(LibvlcDeinterlaceNPObject,methodCount,methodNames);
1906 RuntimeNPObject::InvokeResult
1907 LibvlcDeinterlaceNPObject::invoke(int index, const NPVariant *args,
1908 uint32_t argCount, NPVariant &result)
1912 if( !isPluginRunning() )
1913 return INVOKERESULT_GENERIC_ERROR;
1915 libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD();
1921 case ID_deint_disable:
1922 libvlc_video_set_deinterlace(p_md, NULL);
1925 case ID_deint_enable:
1926 if( argCount != 1 || !NPVARIANT_IS_STRING( args[0] ) )
1927 return INVOKERESULT_INVALID_VALUE;
1929 psz = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1930 libvlc_video_set_deinterlace(p_md, psz);
1935 return INVOKERESULT_NO_SUCH_METHOD;
1937 return INVOKERESULT_NO_ERROR;