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 NPObject *listener = NPVARIANT_TO_OBJECT(args[1]);
198 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
201 if(ID_root_removeeventlistener!=index)
202 b = p_plugin->events.insert(NPVARIANT_TO_STRING(args[0]),
203 listener, NPVARIANT_TO_BOOLEAN(args[2]));
205 b = p_plugin->events.remove(NPVARIANT_TO_STRING(args[0]),
206 listener, NPVARIANT_TO_BOOLEAN(args[2]));
208 VOID_TO_NPVARIANT(result);
210 return b ? INVOKERESULT_NO_ERROR : INVOKERESULT_GENERIC_ERROR;
212 return INVOKERESULT_NO_SUCH_METHOD;
216 ** implementation of libvlc audio object
219 const NPUTF8 * const LibvlcAudioNPObject::propertyNames[] =
227 COUNTNAMES(LibvlcAudioNPObject,propertyCount,propertyNames);
229 enum LibvlcAudioNPObjectPropertyIds
238 RuntimeNPObject::InvokeResult
239 LibvlcAudioNPObject::getProperty(int index, NPVariant &result)
241 /* is plugin still running */
242 if( isPluginRunning() )
244 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
246 libvlc_media_player_t *p_md = p_plugin->getMD();
254 bool muted = libvlc_audio_get_mute(p_md);
255 BOOLEAN_TO_NPVARIANT(muted, result);
256 return INVOKERESULT_NO_ERROR;
258 case ID_audio_volume:
260 int volume = libvlc_audio_get_volume(p_md);
261 INT32_TO_NPVARIANT(volume, result);
262 return INVOKERESULT_NO_ERROR;
266 int track = libvlc_audio_get_track(p_md);
267 INT32_TO_NPVARIANT(track, result);
268 return INVOKERESULT_NO_ERROR;
272 // get the number of audio track available
273 int i_track = libvlc_audio_get_track_count(p_md);
275 INT32_TO_NPVARIANT(i_track, result);
276 return INVOKERESULT_NO_ERROR;
278 case ID_audio_channel:
280 int channel = libvlc_audio_get_channel(p_md);
281 INT32_TO_NPVARIANT(channel, result);
282 return INVOKERESULT_NO_ERROR;
288 return INVOKERESULT_GENERIC_ERROR;
291 RuntimeNPObject::InvokeResult
292 LibvlcAudioNPObject::setProperty(int index, const NPVariant &value)
294 /* is plugin still running */
295 if( isPluginRunning() )
297 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
299 libvlc_media_player_t *p_md = p_plugin->getMD();
306 if( NPVARIANT_IS_BOOLEAN(value) )
308 libvlc_audio_set_mute(p_md,
309 NPVARIANT_TO_BOOLEAN(value));
310 return INVOKERESULT_NO_ERROR;
312 return INVOKERESULT_INVALID_VALUE;
313 case ID_audio_volume:
314 if( isNumberValue(value) )
316 libvlc_audio_set_volume(p_md, numberValue(value));
317 return INVOKERESULT_NO_ERROR;
319 return INVOKERESULT_INVALID_VALUE;
321 if( isNumberValue(value) )
323 libvlc_audio_set_track(p_md, numberValue(value));
324 return INVOKERESULT_NO_ERROR;
326 return INVOKERESULT_INVALID_VALUE;
327 case ID_audio_channel:
328 if( isNumberValue(value) )
330 libvlc_audio_set_channel(p_md, numberValue(value));
331 return INVOKERESULT_NO_ERROR;
333 return INVOKERESULT_INVALID_VALUE;
338 return INVOKERESULT_GENERIC_ERROR;
341 const NPUTF8 * const LibvlcAudioNPObject::methodNames[] =
346 COUNTNAMES(LibvlcAudioNPObject,methodCount,methodNames);
348 enum LibvlcAudioNPObjectMethodIds
351 ID_audio_description,
354 RuntimeNPObject::InvokeResult
355 LibvlcAudioNPObject::invoke(int index, const NPVariant *args,
356 uint32_t argCount, NPVariant &result)
358 /* is plugin still running */
359 if( isPluginRunning() )
361 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
362 libvlc_media_player_t *p_md = p_plugin->getMD();
368 case ID_audio_togglemute:
371 libvlc_audio_toggle_mute(p_md);
372 VOID_TO_NPVARIANT(result);
373 return INVOKERESULT_NO_ERROR;
375 return INVOKERESULT_NO_SUCH_METHOD;
376 case ID_audio_description:
381 int i_trackID, i_limit, i;
382 libvlc_track_description_t *p_trackDesc;
384 /* get tracks description */
385 p_trackDesc = libvlc_audio_get_track_description(p_md);
387 return INVOKERESULT_GENERIC_ERROR;
389 /* get the number of track available */
390 i_limit = libvlc_audio_get_track_count(p_md);
392 /* check if a number is given by the user
393 * and get the track number */
394 if( isNumberValue(args[0]) )
395 i_trackID = numberValue(args[0]);
397 return INVOKERESULT_INVALID_VALUE;
399 /* if bad number is given return invalid value */
400 if ( ( i_trackID > ( i_limit - 1 ) ) || ( i_trackID < 0 ) )
401 return INVOKERESULT_INVALID_VALUE;
403 /* get the good trackDesc */
404 for( i = 0 ; i < i_trackID ; i++ )
406 p_trackDesc = p_trackDesc->p_next;
408 psz_name = p_trackDesc->psz_name;
410 /* display the name of the track chosen */
411 return invokeResultString( psz_name, result );
413 return INVOKERESULT_NO_SUCH_METHOD;
419 return INVOKERESULT_GENERIC_ERROR;
423 ** implementation of libvlc input object
426 const NPUTF8 * const LibvlcInputNPObject::propertyNames[] =
436 COUNTNAMES(LibvlcInputNPObject,propertyCount,propertyNames);
438 enum LibvlcInputNPObjectPropertyIds
449 RuntimeNPObject::InvokeResult
450 LibvlcInputNPObject::getProperty(int index, NPVariant &result)
452 /* is plugin still running */
453 if( isPluginRunning() )
455 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
456 libvlc_media_player_t *p_md = p_plugin->getMD();
459 if( index != ID_input_state )
463 /* for input state, return CLOSED rather than an exception */
464 INT32_TO_NPVARIANT(0, result);
465 return INVOKERESULT_NO_ERROR;
471 case ID_input_length:
473 double val = (double)libvlc_media_player_get_length(p_md);
474 DOUBLE_TO_NPVARIANT(val, result);
475 return INVOKERESULT_NO_ERROR;
477 case ID_input_position:
479 double val = libvlc_media_player_get_position(p_md);
480 DOUBLE_TO_NPVARIANT(val, result);
481 return INVOKERESULT_NO_ERROR;
485 double val = (double)libvlc_media_player_get_time(p_md);
486 DOUBLE_TO_NPVARIANT(val, result);
487 return INVOKERESULT_NO_ERROR;
491 int val = libvlc_media_player_get_state(p_md);
492 INT32_TO_NPVARIANT(val, result);
493 return INVOKERESULT_NO_ERROR;
497 float val = libvlc_media_player_get_rate(p_md);
498 DOUBLE_TO_NPVARIANT(val, result);
499 return INVOKERESULT_NO_ERROR;
503 double val = libvlc_media_player_get_fps(p_md);
504 DOUBLE_TO_NPVARIANT(val, result);
505 return INVOKERESULT_NO_ERROR;
507 case ID_input_hasvout:
509 bool val = p_plugin->player_has_vout();
510 BOOLEAN_TO_NPVARIANT(val, result);
511 return INVOKERESULT_NO_ERROR;
517 return INVOKERESULT_GENERIC_ERROR;
520 RuntimeNPObject::InvokeResult
521 LibvlcInputNPObject::setProperty(int index, const NPVariant &value)
523 /* is plugin still running */
524 if( isPluginRunning() )
526 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
527 libvlc_media_player_t *p_md = p_plugin->getMD();
533 case ID_input_position:
535 if( ! NPVARIANT_IS_DOUBLE(value) )
537 return INVOKERESULT_INVALID_VALUE;
540 float val = (float)NPVARIANT_TO_DOUBLE(value);
541 libvlc_media_player_set_position(p_md, val);
542 return INVOKERESULT_NO_ERROR;
547 if( NPVARIANT_IS_INT32(value) )
548 val = (int64_t)NPVARIANT_TO_INT32(value);
549 else if( NPVARIANT_IS_DOUBLE(value) )
550 val = (int64_t)NPVARIANT_TO_DOUBLE(value);
553 return INVOKERESULT_INVALID_VALUE;
556 libvlc_media_player_set_time(p_md, val);
557 return INVOKERESULT_NO_ERROR;
562 if( NPVARIANT_IS_INT32(value) )
563 val = (float)NPVARIANT_TO_INT32(value);
564 else if( NPVARIANT_IS_DOUBLE(value) )
565 val = (float)NPVARIANT_TO_DOUBLE(value);
568 return INVOKERESULT_INVALID_VALUE;
571 libvlc_media_player_set_rate(p_md, val);
572 return INVOKERESULT_NO_ERROR;
578 return INVOKERESULT_GENERIC_ERROR;
581 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =
586 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
588 enum LibvlcInputNPObjectMethodIds
593 RuntimeNPObject::InvokeResult
594 LibvlcInputNPObject::invoke(int index, const NPVariant *args,
595 uint32_t argCount, NPVariant &result)
597 /* is plugin still running */
598 if( isPluginRunning() )
603 return INVOKERESULT_NO_SUCH_METHOD;
608 return INVOKERESULT_GENERIC_ERROR;
612 ** implementation of libvlc playlist items object
615 const NPUTF8 * const LibvlcPlaylistItemsNPObject::propertyNames[] =
619 COUNTNAMES(LibvlcPlaylistItemsNPObject,propertyCount,propertyNames);
621 enum LibvlcPlaylistItemsNPObjectPropertyIds
623 ID_playlistitems_count,
626 RuntimeNPObject::InvokeResult
627 LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
629 /* is plugin still running */
630 if( isPluginRunning() )
632 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
636 case ID_playlistitems_count:
638 int val = p_plugin->playlist_count();
639 INT32_TO_NPVARIANT(val, result);
640 return INVOKERESULT_NO_ERROR;
646 return INVOKERESULT_GENERIC_ERROR;
649 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
654 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
656 enum LibvlcPlaylistItemsNPObjectMethodIds
658 ID_playlistitems_clear,
659 ID_playlistitems_remove,
662 RuntimeNPObject::InvokeResult
663 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
664 uint32_t argCount, NPVariant &result)
666 /* is plugin still running */
667 if( isPluginRunning() )
669 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
673 case ID_playlistitems_clear:
676 p_plugin->playlist_clear();
677 VOID_TO_NPVARIANT(result);
678 return INVOKERESULT_NO_ERROR;
680 return INVOKERESULT_NO_SUCH_METHOD;
681 case ID_playlistitems_remove:
682 if( (argCount == 1) && isNumberValue(args[0]) )
684 if( !p_plugin->playlist_delete_item(numberValue(args[0])) )
685 return INVOKERESULT_GENERIC_ERROR;
686 VOID_TO_NPVARIANT(result);
687 return INVOKERESULT_NO_ERROR;
689 return INVOKERESULT_NO_SUCH_METHOD;
694 return INVOKERESULT_GENERIC_ERROR;
698 ** implementation of libvlc playlist object
701 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
703 // Why the isValid()?
704 if( isValid() && playlistItemsObj )
705 NPN_ReleaseObject(playlistItemsObj);
708 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
710 "itemCount", /* deprecated */
714 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
716 enum LibvlcPlaylistNPObjectPropertyIds
718 ID_playlist_itemcount,
719 ID_playlist_isplaying,
723 RuntimeNPObject::InvokeResult
724 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
726 /* is plugin still running */
727 if( isPluginRunning() )
729 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
733 case ID_playlist_itemcount: /* deprecated */
735 int val = p_plugin->playlist_count();
736 INT32_TO_NPVARIANT(val, result);
737 return INVOKERESULT_NO_ERROR;
739 case ID_playlist_isplaying:
741 int val = p_plugin->playlist_isplaying();
742 BOOLEAN_TO_NPVARIANT(val, result);
743 return INVOKERESULT_NO_ERROR;
745 case ID_playlist_items:
747 InstantObj<LibvlcPlaylistItemsNPObject>( playlistItemsObj );
748 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
749 return INVOKERESULT_NO_ERROR;
755 return INVOKERESULT_GENERIC_ERROR;
758 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
767 "clear", /* deprecated */
768 "removeItem", /* deprecated */
770 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
772 enum LibvlcPlaylistNPObjectMethodIds
776 ID_playlist_playItem,
777 ID_playlist_togglepause,
782 ID_playlist_removeitem
785 RuntimeNPObject::InvokeResult
786 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
787 uint32_t argCount, NPVariant &result)
789 /* is plugin still running */
790 if( isPluginRunning() )
792 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
796 // XXX FIXME this needs squashing into something much smaller
797 case ID_playlist_add:
799 if( (argCount < 1) || (argCount > 3) )
800 return INVOKERESULT_NO_SUCH_METHOD;
801 if( !NPVARIANT_IS_STRING(args[0]) )
802 return INVOKERESULT_NO_SUCH_METHOD;
805 if( NPVARIANT_IS_NULL(args[0]) )
806 return INVOKERESULT_NO_SUCH_METHOD;
808 char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
810 return INVOKERESULT_OUT_OF_MEMORY;
812 char *url = p_plugin->getAbsoluteURL(s);
816 // problem with combining url, use argument
821 // grab name if available
824 if( NPVARIANT_IS_NULL(args[1]) )
828 else if( NPVARIANT_IS_STRING(args[1]) )
830 name = stringValue(NPVARIANT_TO_STRING(args[1]));
835 return INVOKERESULT_INVALID_VALUE;
840 char** ppsz_options = NULL;
842 // grab options if available
845 if( NPVARIANT_IS_NULL(args[2]) )
849 else if( NPVARIANT_IS_STRING(args[2]) )
851 parseOptions(NPVARIANT_TO_STRING(args[2]),
852 &i_options, &ppsz_options);
855 else if( NPVARIANT_IS_OBJECT(args[2]) )
857 parseOptions(NPVARIANT_TO_OBJECT(args[2]),
858 &i_options, &ppsz_options);
864 return INVOKERESULT_INVALID_VALUE;
868 int item = p_plugin->playlist_add_extended_untrusted(url, name,
869 i_options, const_cast<const char **>(ppsz_options));
875 for( int i=0; i< i_options; ++i )
877 free(ppsz_options[i]);
881 INT32_TO_NPVARIANT(item, result);
882 return INVOKERESULT_NO_ERROR;
884 case ID_playlist_play:
887 p_plugin->playlist_play();
888 VOID_TO_NPVARIANT(result);
889 return INVOKERESULT_NO_ERROR;
891 return INVOKERESULT_NO_SUCH_METHOD;
892 case ID_playlist_playItem:
893 if( (argCount == 1) && isNumberValue(args[0]) )
895 p_plugin->playlist_play_item(numberValue(args[0]));
896 VOID_TO_NPVARIANT(result);
897 return INVOKERESULT_NO_ERROR;
899 return INVOKERESULT_NO_SUCH_METHOD;
900 case ID_playlist_togglepause:
903 p_plugin->playlist_pause();
904 VOID_TO_NPVARIANT(result);
905 return INVOKERESULT_NO_ERROR;
907 return INVOKERESULT_NO_SUCH_METHOD;
908 case ID_playlist_stop:
911 p_plugin->playlist_stop();
912 VOID_TO_NPVARIANT(result);
913 return INVOKERESULT_NO_ERROR;
915 return INVOKERESULT_NO_SUCH_METHOD;
916 case ID_playlist_next:
919 p_plugin->playlist_next();
920 VOID_TO_NPVARIANT(result);
921 return INVOKERESULT_NO_ERROR;
923 return INVOKERESULT_NO_SUCH_METHOD;
924 case ID_playlist_prev:
927 p_plugin->playlist_prev();
928 VOID_TO_NPVARIANT(result);
929 return INVOKERESULT_NO_ERROR;
931 return INVOKERESULT_NO_SUCH_METHOD;
932 case ID_playlist_clear: /* deprecated */
935 p_plugin->playlist_clear();
936 VOID_TO_NPVARIANT(result);
937 return INVOKERESULT_NO_ERROR;
939 return INVOKERESULT_NO_SUCH_METHOD;
940 case ID_playlist_removeitem: /* deprecated */
941 if( (argCount == 1) && isNumberValue(args[0]) )
943 if( !p_plugin->playlist_delete_item(numberValue(args[0])) )
944 return INVOKERESULT_GENERIC_ERROR;
945 VOID_TO_NPVARIANT(result);
946 return INVOKERESULT_NO_ERROR;
948 return INVOKERESULT_NO_SUCH_METHOD;
953 return INVOKERESULT_GENERIC_ERROR;
956 // XXX FIXME The new playlist_add creates a media instance and feeds it
957 // XXX FIXME these options one at a time, so this hunk of code does lots
958 // XXX FIXME of unnecessairy work. Break out something that can do one
959 // XXX FIXME option at a time and doesn't need to realloc().
960 // XXX FIXME Same for the other version of parseOptions.
962 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
963 int *i_options, char*** ppsz_options)
967 char *s = stringValue(nps);
972 char **options = (char **)malloc(capacity*sizeof(char *));
977 char *end = val + nps.UTF8Length;
980 // skip leading blanks
982 && ((*val == ' ' ) || (*val == '\t')) )
986 // skip till we get a blank character
992 if( ('\'' == c) || ('"' == c) )
994 // skip till end of string
995 while( (val < end) && (*(val++) != c ) );
1001 if( nOptions == capacity )
1004 char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1007 /* failed to allocate more memory */
1009 /* return what we got so far */
1010 *i_options = nOptions;
1011 *ppsz_options = options;
1014 options = moreOptions;
1017 options[nOptions++] = strdup(start);
1020 // must be end of string
1023 *i_options = nOptions;
1024 *ppsz_options = options;
1031 // XXX FIXME See comment at the other parseOptions variant.
1032 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
1033 char*** ppsz_options)
1035 /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1039 /* we are expecting to have a Javascript Array object */
1040 NPIdentifier propId = NPN_GetStringIdentifier("length");
1041 if( NPN_GetProperty(_instance, obj, propId, &value) )
1043 int count = numberValue(value);
1044 NPN_ReleaseVariantValue(&value);
1049 char **options = (char **)malloc(capacity*sizeof(char *));
1054 while( nOptions < count )
1056 propId = NPN_GetIntIdentifier(nOptions);
1057 if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1058 /* return what we got so far */
1061 if( ! NPVARIANT_IS_STRING(value) )
1063 /* return what we got so far */
1064 NPN_ReleaseVariantValue(&value);
1068 if( nOptions == capacity )
1071 char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1074 /* failed to allocate more memory */
1075 NPN_ReleaseVariantValue(&value);
1076 /* return what we got so far */
1077 *i_options = nOptions;
1078 *ppsz_options = options;
1081 options = moreOptions;
1084 options[nOptions++] = stringValue(value);
1085 NPN_ReleaseVariantValue(&value);
1087 *i_options = nOptions;
1088 *ppsz_options = options;
1095 ** implementation of libvlc subtitle object
1098 const NPUTF8 * const LibvlcSubtitleNPObject::propertyNames[] =
1104 enum LibvlcSubtitleNPObjectPropertyIds
1109 COUNTNAMES(LibvlcSubtitleNPObject,propertyCount,propertyNames);
1111 RuntimeNPObject::InvokeResult
1112 LibvlcSubtitleNPObject::getProperty(int index, NPVariant &result)
1114 /* is plugin still running */
1115 if( isPluginRunning() )
1117 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1118 libvlc_media_player_t *p_md = p_plugin->getMD();
1124 case ID_subtitle_track:
1126 /* get the current subtitle ID */
1127 int i_spu = libvlc_video_get_spu(p_md);
1129 INT32_TO_NPVARIANT(i_spu, result);
1130 return INVOKERESULT_NO_ERROR;
1132 case ID_subtitle_count:
1134 /* get the number of subtitles available */
1135 int i_spu = libvlc_video_get_spu_count(p_md);
1137 INT32_TO_NPVARIANT(i_spu, result);
1138 return INVOKERESULT_NO_ERROR;
1142 return INVOKERESULT_GENERIC_ERROR;
1145 RuntimeNPObject::InvokeResult
1146 LibvlcSubtitleNPObject::setProperty(int index, const NPVariant &value)
1148 /* is plugin still running */
1149 if( isPluginRunning() )
1151 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1152 libvlc_media_player_t *p_md = p_plugin->getMD();
1158 case ID_subtitle_track:
1160 if( isNumberValue(value) )
1162 /* set the new subtitle track to show */
1163 libvlc_video_set_spu(p_md, numberValue(value));
1165 return INVOKERESULT_NO_ERROR;
1167 return INVOKERESULT_INVALID_VALUE;
1171 return INVOKERESULT_GENERIC_ERROR;
1174 const NPUTF8 * const LibvlcSubtitleNPObject::methodNames[] =
1178 COUNTNAMES(LibvlcSubtitleNPObject,methodCount,methodNames);
1180 enum LibvlcSubtitleNPObjectMethodIds
1182 ID_subtitle_description
1185 RuntimeNPObject::InvokeResult
1186 LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
1187 uint32_t argCount, NPVariant &result)
1189 /* is plugin still running */
1190 if( isPluginRunning() )
1192 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1193 libvlc_media_player_t *p_md = p_plugin->getMD();
1199 case ID_subtitle_description:
1204 int i_spuID, i_limit, i;
1205 libvlc_track_description_t *p_spuDesc;
1207 /* get subtitles description */
1208 p_spuDesc = libvlc_video_get_spu_description(p_md);
1210 return INVOKERESULT_GENERIC_ERROR;
1212 /* get the number of subtitle available */
1213 i_limit = libvlc_video_get_spu_count(p_md);
1215 /* check if a number is given by the user
1216 * and get the subtitle number */
1217 if( isNumberValue(args[0]) )
1218 i_spuID = numberValue(args[0]);
1220 return INVOKERESULT_INVALID_VALUE;
1222 /* if bad number is given return invalid value */
1223 if ( ( i_spuID > ( i_limit -1 ) ) || ( i_spuID < 0 ) )
1224 return INVOKERESULT_INVALID_VALUE;
1226 /* get the good spuDesc */
1227 for( i = 0 ; i < i_spuID ; i++ )
1229 p_spuDesc = p_spuDesc->p_next;
1231 psz_name = p_spuDesc->psz_name;
1233 /* return the name of the track chosen */
1234 return invokeResultString(psz_name, result);
1236 return INVOKERESULT_NO_SUCH_METHOD;
1239 return INVOKERESULT_NO_SUCH_METHOD;
1242 return INVOKERESULT_GENERIC_ERROR;
1246 ** implementation of libvlc video object
1249 LibvlcVideoNPObject::~LibvlcVideoNPObject()
1253 if( marqueeObj ) NPN_ReleaseObject(marqueeObj);
1254 if( logoObj ) NPN_ReleaseObject(logoObj);
1255 if( deintObj ) NPN_ReleaseObject(deintObj);
1259 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1273 enum LibvlcVideoNPObjectPropertyIds
1275 ID_video_fullscreen,
1278 ID_video_aspectratio,
1284 ID_video_deinterlace,
1286 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1288 RuntimeNPObject::InvokeResult
1289 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1291 /* is plugin still running */
1292 if( isPluginRunning() )
1294 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1295 libvlc_media_player_t *p_md = p_plugin->getMD();
1301 case ID_video_fullscreen:
1303 int val = p_plugin->get_fullscreen();
1304 BOOLEAN_TO_NPVARIANT(val, result);
1305 return INVOKERESULT_NO_ERROR;
1307 case ID_video_height:
1309 int val = libvlc_video_get_height(p_md);
1310 INT32_TO_NPVARIANT(val, result);
1311 return INVOKERESULT_NO_ERROR;
1313 case ID_video_width:
1315 int val = libvlc_video_get_width(p_md);
1316 INT32_TO_NPVARIANT(val, result);
1317 return INVOKERESULT_NO_ERROR;
1319 case ID_video_aspectratio:
1321 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md);
1323 return INVOKERESULT_GENERIC_ERROR;
1325 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1326 return INVOKERESULT_NO_ERROR;
1328 case ID_video_subtitle:
1330 int i_spu = libvlc_video_get_spu(p_md);
1331 INT32_TO_NPVARIANT(i_spu, result);
1332 return INVOKERESULT_NO_ERROR;
1336 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md);
1338 return INVOKERESULT_GENERIC_ERROR;
1340 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1341 return INVOKERESULT_NO_ERROR;
1343 case ID_video_teletext:
1345 int i_page = libvlc_video_get_teletext(p_md);
1347 return INVOKERESULT_GENERIC_ERROR;
1348 INT32_TO_NPVARIANT(i_page, result);
1349 return INVOKERESULT_NO_ERROR;
1351 case ID_video_marquee:
1353 InstantObj<LibvlcMarqueeNPObject>( marqueeObj );
1354 OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1355 return INVOKERESULT_NO_ERROR;
1359 InstantObj<LibvlcLogoNPObject>( logoObj );
1360 OBJECT_TO_NPVARIANT(NPN_RetainObject(logoObj), result);
1361 return INVOKERESULT_NO_ERROR;
1363 case ID_video_deinterlace:
1365 InstantObj<LibvlcDeinterlaceNPObject>( deintObj );
1366 OBJECT_TO_NPVARIANT(NPN_RetainObject(deintObj), result);
1367 return INVOKERESULT_NO_ERROR;
1371 return INVOKERESULT_GENERIC_ERROR;
1374 RuntimeNPObject::InvokeResult
1375 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1377 /* is plugin still running */
1378 if( isPluginRunning() )
1380 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1381 libvlc_media_player_t *p_md = p_plugin->getMD();
1387 case ID_video_fullscreen:
1389 if( ! NPVARIANT_IS_BOOLEAN(value) )
1391 return INVOKERESULT_INVALID_VALUE;
1394 int val = NPVARIANT_TO_BOOLEAN(value);
1395 p_plugin->set_fullscreen(val);
1396 return INVOKERESULT_NO_ERROR;
1398 case ID_video_aspectratio:
1400 char *psz_aspect = NULL;
1402 if( ! NPVARIANT_IS_STRING(value) )
1404 return INVOKERESULT_INVALID_VALUE;
1407 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1410 return INVOKERESULT_GENERIC_ERROR;
1413 libvlc_video_set_aspect_ratio(p_md, psz_aspect);
1416 return INVOKERESULT_NO_ERROR;
1418 case ID_video_subtitle:
1420 if( isNumberValue(value) )
1422 libvlc_video_set_spu(p_md, numberValue(value));
1424 return INVOKERESULT_NO_ERROR;
1426 return INVOKERESULT_INVALID_VALUE;
1430 char *psz_geometry = NULL;
1432 if( ! NPVARIANT_IS_STRING(value) )
1434 return INVOKERESULT_INVALID_VALUE;
1437 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1440 return INVOKERESULT_GENERIC_ERROR;
1443 libvlc_video_set_crop_geometry(p_md, psz_geometry);
1446 return INVOKERESULT_NO_ERROR;
1448 case ID_video_teletext:
1450 if( isNumberValue(value) )
1452 libvlc_video_set_teletext(p_md, numberValue(value));
1453 return INVOKERESULT_NO_ERROR;
1455 return INVOKERESULT_INVALID_VALUE;
1459 return INVOKERESULT_GENERIC_ERROR;
1462 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1467 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1469 enum LibvlcVideoNPObjectMethodIds
1471 ID_video_togglefullscreen,
1472 ID_video_toggleteletext,
1475 RuntimeNPObject::InvokeResult
1476 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1477 uint32_t argCount, NPVariant &result)
1479 /* is plugin still running */
1480 if( isPluginRunning() )
1482 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1483 libvlc_media_player_t *p_md = p_plugin->getMD();
1489 case ID_video_togglefullscreen:
1493 p_plugin->toggle_fullscreen();
1494 VOID_TO_NPVARIANT(result);
1495 return INVOKERESULT_NO_ERROR;
1497 return INVOKERESULT_NO_SUCH_METHOD;
1499 case ID_video_toggleteletext:
1503 libvlc_toggle_teletext(p_md);
1504 VOID_TO_NPVARIANT(result);
1505 return INVOKERESULT_NO_ERROR;
1507 return INVOKERESULT_NO_SUCH_METHOD;
1510 return INVOKERESULT_NO_SUCH_METHOD;
1513 return INVOKERESULT_GENERIC_ERROR;
1517 ** implementation of libvlc marquee object
1520 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1533 enum LibvlcMarqueeNPObjectPropertyIds
1537 ID_marquee_position,
1546 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
1548 static const unsigned char marquee_idx[] = {
1549 libvlc_marquee_Color,
1550 libvlc_marquee_Opacity,
1551 libvlc_marquee_Position,
1552 libvlc_marquee_Refresh,
1553 libvlc_marquee_Size,
1555 libvlc_marquee_Timeout,
1560 RuntimeNPObject::InvokeResult
1561 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1565 if( !isPluginRunning() )
1566 return INVOKERESULT_GENERIC_ERROR;
1568 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1569 libvlc_media_player_t *p_md = p_plugin->getMD();
1575 case ID_marquee_color:
1576 case ID_marquee_opacity:
1577 case ID_marquee_refresh:
1578 case ID_marquee_timeout:
1579 case ID_marquee_size:
1583 libvlc_video_get_marquee_int(p_md, marquee_idx[index]),
1585 return INVOKERESULT_NO_ERROR;
1587 case ID_marquee_position:
1588 STRINGZ_TO_NPVARIANT( position_bynumber(
1589 libvlc_video_get_marquee_int(p_md, libvlc_marquee_Position) ),
1594 case ID_marquee_text:
1595 psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text);
1598 STRINGZ_TO_NPVARIANT(psz, result);
1599 return INVOKERESULT_NO_ERROR;
1603 return INVOKERESULT_GENERIC_ERROR;
1606 RuntimeNPObject::InvokeResult
1607 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1611 if( !isPluginRunning() )
1612 return INVOKERESULT_GENERIC_ERROR;
1614 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1615 libvlc_media_player_t *p_md = p_plugin->getMD();
1621 case ID_marquee_color:
1622 case ID_marquee_opacity:
1623 case ID_marquee_refresh:
1624 case ID_marquee_timeout:
1627 if( NPVARIANT_IS_INT32( value ) )
1629 libvlc_video_set_marquee_int(p_md, marquee_idx[index],
1630 NPVARIANT_TO_INT32( value ));
1631 return INVOKERESULT_NO_ERROR;
1635 case ID_marquee_position:
1636 if( !NPVARIANT_IS_STRING(value) ||
1637 !position_byname( NPVARIANT_TO_STRING(value).UTF8Characters, i ) )
1638 return INVOKERESULT_INVALID_VALUE;
1640 libvlc_video_set_marquee_int(p_md, libvlc_marquee_Position, i);
1641 return INVOKERESULT_NO_ERROR;
1643 case ID_marquee_text:
1644 if( NPVARIANT_IS_STRING( value ) )
1646 char *psz_text = stringValue( NPVARIANT_TO_STRING( value ) );
1647 libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
1650 return INVOKERESULT_NO_ERROR;
1654 return INVOKERESULT_NO_SUCH_METHOD;
1657 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1662 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1664 enum LibvlcMarqueeNPObjectMethodIds
1670 RuntimeNPObject::InvokeResult
1671 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1672 uint32_t argCount, NPVariant &result)
1674 if( !isPluginRunning() )
1675 return INVOKERESULT_GENERIC_ERROR;
1677 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1678 libvlc_media_player_t *p_md = p_plugin->getMD();
1684 case ID_marquee_enable:
1685 case ID_marquee_disable:
1686 libvlc_video_set_marquee_int(p_md, libvlc_marquee_Enable,
1687 index!=ID_marquee_disable);
1688 VOID_TO_NPVARIANT(result);
1689 return INVOKERESULT_NO_ERROR;
1691 return INVOKERESULT_NO_SUCH_METHOD;
1694 const NPUTF8 * const LibvlcLogoNPObject::propertyNames[] = {
1702 enum LibvlcLogoNPObjectPropertyIds {
1710 COUNTNAMES(LibvlcLogoNPObject,propertyCount,propertyNames);
1711 static const unsigned char logo_idx[] = {
1714 libvlc_logo_opacity,
1720 RuntimeNPObject::InvokeResult
1721 LibvlcLogoNPObject::getProperty(int index, NPVariant &result)
1723 if( !isPluginRunning() )
1724 return INVOKERESULT_GENERIC_ERROR;
1726 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1727 libvlc_media_player_t *p_md = p_plugin->getMD();
1734 case ID_logo_repeat:
1735 case ID_logo_opacity:
1740 libvlc_video_get_logo_int(p_md, logo_idx[index]), result);
1743 case ID_logo_position:
1744 STRINGZ_TO_NPVARIANT( position_bynumber(
1745 libvlc_video_get_logo_int(p_md, libvlc_logo_position) ),
1749 return INVOKERESULT_GENERIC_ERROR;
1751 return INVOKERESULT_NO_ERROR;
1754 RuntimeNPObject::InvokeResult
1755 LibvlcLogoNPObject::setProperty(int index, const NPVariant &value)
1759 if( !isPluginRunning() )
1760 return INVOKERESULT_GENERIC_ERROR;
1762 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1763 libvlc_media_player_t *p_md = p_plugin->getMD();
1770 case ID_logo_repeat:
1771 case ID_logo_opacity:
1774 if( !NPVARIANT_IS_INT32(value) )
1775 return INVOKERESULT_INVALID_VALUE;
1777 libvlc_video_set_logo_int(p_md, logo_idx[index],
1778 NPVARIANT_TO_INT32( value ));
1781 case ID_logo_position:
1782 if( !NPVARIANT_IS_STRING(value) ||
1783 !position_byname( NPVARIANT_TO_STRING(value).UTF8Characters, i ) )
1784 return INVOKERESULT_INVALID_VALUE;
1786 libvlc_video_set_logo_int(p_md, libvlc_logo_position, i);
1789 return INVOKERESULT_GENERIC_ERROR;
1791 return INVOKERESULT_NO_ERROR;
1795 const NPUTF8 * const LibvlcLogoNPObject::methodNames[] = {
1800 enum LibvlcLogoNPObjectMethodIds {
1805 COUNTNAMES(LibvlcLogoNPObject,methodCount,methodNames);
1807 RuntimeNPObject::InvokeResult
1808 LibvlcLogoNPObject::invoke(int index, const NPVariant *args,
1809 uint32_t argCount, NPVariant &result)
1814 if( !isPluginRunning() )
1815 return INVOKERESULT_GENERIC_ERROR;
1817 libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD();
1823 case ID_logo_enable:
1824 case ID_logo_disable:
1826 return INVOKERESULT_GENERIC_ERROR;
1828 libvlc_video_set_logo_int(p_md, libvlc_logo_enable,
1829 index != ID_logo_disable);
1830 VOID_TO_NPVARIANT(result);
1835 return INVOKERESULT_GENERIC_ERROR;
1837 for( len=0,i=0;i<argCount;++i )
1839 if( !NPVARIANT_IS_STRING(args[i]) )
1840 return INVOKERESULT_INVALID_VALUE;
1841 len+=NPVARIANT_TO_STRING(args[i]).UTF8Length+1;
1844 buf = (char *)malloc( len+1 );
1846 return INVOKERESULT_OUT_OF_MEMORY;
1848 for( h=buf,i=0;i<argCount;++i )
1851 len=NPVARIANT_TO_STRING(args[i]).UTF8Length;
1852 memcpy(h,NPVARIANT_TO_STRING(args[i]).UTF8Characters,len);
1857 libvlc_video_set_logo_string(p_md, libvlc_logo_file, buf);
1859 VOID_TO_NPVARIANT(result);
1862 return INVOKERESULT_NO_SUCH_METHOD;
1864 return INVOKERESULT_NO_ERROR;
1868 const NPUTF8 * const LibvlcDeinterlaceNPObject::propertyNames[] = {
1870 enum LibvlcDeinterlaceNPObjectPropertyIds {
1872 COUNTNAMES(LibvlcDeinterlaceNPObject,propertyCount,propertyNames);
1874 RuntimeNPObject::InvokeResult
1875 LibvlcDeinterlaceNPObject::getProperty(int index, NPVariant &result)
1877 return INVOKERESULT_GENERIC_ERROR;
1880 RuntimeNPObject::InvokeResult
1881 LibvlcDeinterlaceNPObject::setProperty(int index, const NPVariant &value)
1883 return INVOKERESULT_GENERIC_ERROR;
1887 const NPUTF8 * const LibvlcDeinterlaceNPObject::methodNames[] = {
1891 enum LibvlcDeinterlaceNPObjectMethodIds {
1895 COUNTNAMES(LibvlcDeinterlaceNPObject,methodCount,methodNames);
1897 RuntimeNPObject::InvokeResult
1898 LibvlcDeinterlaceNPObject::invoke(int index, const NPVariant *args,
1899 uint32_t argCount, NPVariant &result)
1903 if( !isPluginRunning() )
1904 return INVOKERESULT_GENERIC_ERROR;
1906 libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD();
1912 case ID_deint_disable:
1913 libvlc_video_set_deinterlace(p_md, NULL);
1916 case ID_deint_enable:
1917 if( argCount != 1 || !NPVARIANT_IS_STRING( args[0] ) )
1918 return INVOKERESULT_INVALID_VALUE;
1920 psz = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1921 libvlc_video_set_deinterlace(p_md, psz);
1926 return INVOKERESULT_NO_SUCH_METHOD;
1928 return INVOKERESULT_NO_ERROR;