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 *****************************************************************************/
32 #ifdef HAVE_MOZILLA_CONFIG_H
33 # include <mozilla-config.h>
36 #include "vlcplugin.h"
37 #include "npolibvlc.h"
42 ** Local helper macros and function
44 #define COUNTNAMES(a,b,c) const int a::b = sizeof(a::c)/sizeof(NPUTF8 *)
45 #define RETURN_ON_ERROR \
47 NPN_SetException(this, libvlc_errmsg()); \
48 return INVOKERESULT_GENERIC_ERROR; \
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)"
54 // Make a copy of an NPVariant.
55 NPVariant copyNPVariant(const NPVariant& original)
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))
67 NPObject *obj = NPVARIANT_TO_OBJECT(original);
68 NPN_RetainObject(obj);
69 OBJECT_TO_NPVARIANT(obj, res);
71 else if (NPVARIANT_IS_BOOLEAN(original))
72 BOOLEAN_TO_NPVARIANT(NPVARIANT_TO_BOOLEAN(original), res);
78 ** implementation of libvlc root object
81 LibvlcRootNPObject::~LibvlcRootNPObject()
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.
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);
101 const NPUTF8 * const LibvlcRootNPObject::propertyNames[] =
110 COUNTNAMES(LibvlcRootNPObject,propertyCount,propertyNames);
112 enum LibvlcRootNPObjectPropertyIds
122 RuntimeNPObject::InvokeResult
123 LibvlcRootNPObject::getProperty(int index, NPVariant &result)
125 /* is plugin still running */
126 if( isPluginRunning() )
131 InstantObj<LibvlcAudioNPObject>( audioObj );
132 OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result);
133 return INVOKERESULT_NO_ERROR;
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;
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);
156 return INVOKERESULT_GENERIC_ERROR;
159 const NPUTF8 * const LibvlcRootNPObject::methodNames[] =
163 "removeEventListener",
165 COUNTNAMES(LibvlcRootNPObject,methodCount,methodNames);
167 enum LibvlcRootNPObjectMethodIds
170 ID_root_addeventlistener,
171 ID_root_removeeventlistener,
174 RuntimeNPObject::InvokeResult LibvlcRootNPObject::invoke(int index,
175 const NPVariant *args, uint32_t argCount, NPVariant &result)
177 /* is plugin still running */
178 if( !isPluginRunning() )
179 return INVOKERESULT_GENERIC_ERROR;
183 case ID_root_versionInfo:
185 return INVOKERESULT_NO_SUCH_METHOD;
186 return invokeResultString(libvlc_get_version(),result);
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]) )
196 if( !VlcPlugin::canUseEventListener() )
198 NPN_SetException(this, ERROR_API_VERSION);
199 return INVOKERESULT_GENERIC_ERROR;
202 NPObject *listener = NPVARIANT_TO_OBJECT(args[1]);
203 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
206 if(ID_root_removeeventlistener!=index)
207 b = p_plugin->events.insert(NPVARIANT_TO_STRING(args[0]),
208 listener, NPVARIANT_TO_BOOLEAN(args[2]));
210 b = p_plugin->events.remove(NPVARIANT_TO_STRING(args[0]),
211 listener, NPVARIANT_TO_BOOLEAN(args[2]));
213 VOID_TO_NPVARIANT(result);
215 return b ? INVOKERESULT_NO_ERROR : INVOKERESULT_GENERIC_ERROR;
217 return INVOKERESULT_NO_SUCH_METHOD;
221 ** implementation of libvlc audio object
224 const NPUTF8 * const LibvlcAudioNPObject::propertyNames[] =
232 COUNTNAMES(LibvlcAudioNPObject,propertyCount,propertyNames);
234 enum LibvlcAudioNPObjectPropertyIds
243 RuntimeNPObject::InvokeResult
244 LibvlcAudioNPObject::getProperty(int index, NPVariant &result)
246 /* is plugin still running */
247 if( isPluginRunning() )
249 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
251 libvlc_media_player_t *p_md = p_plugin->getMD();
259 bool muted = libvlc_audio_get_mute(p_md);
260 BOOLEAN_TO_NPVARIANT(muted, result);
261 return INVOKERESULT_NO_ERROR;
263 case ID_audio_volume:
265 int volume = libvlc_audio_get_volume(p_md);
266 INT32_TO_NPVARIANT(volume, result);
267 return INVOKERESULT_NO_ERROR;
271 int track = libvlc_audio_get_track(p_md);
272 INT32_TO_NPVARIANT(track, result);
273 return INVOKERESULT_NO_ERROR;
277 // get the number of audio track available
278 int i_track = libvlc_audio_get_track_count(p_md);
280 INT32_TO_NPVARIANT(i_track, result);
281 return INVOKERESULT_NO_ERROR;
283 case ID_audio_channel:
285 int channel = libvlc_audio_get_channel(p_md);
286 INT32_TO_NPVARIANT(channel, result);
287 return INVOKERESULT_NO_ERROR;
293 return INVOKERESULT_GENERIC_ERROR;
296 RuntimeNPObject::InvokeResult
297 LibvlcAudioNPObject::setProperty(int index, const NPVariant &value)
299 /* is plugin still running */
300 if( isPluginRunning() )
302 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
304 libvlc_media_player_t *p_md = p_plugin->getMD();
311 if( NPVARIANT_IS_BOOLEAN(value) )
313 libvlc_audio_set_mute(p_md,
314 NPVARIANT_TO_BOOLEAN(value));
315 return INVOKERESULT_NO_ERROR;
317 return INVOKERESULT_INVALID_VALUE;
318 case ID_audio_volume:
319 if( isNumberValue(value) )
321 libvlc_audio_set_volume(p_md, numberValue(value));
322 return INVOKERESULT_NO_ERROR;
324 return INVOKERESULT_INVALID_VALUE;
326 if( isNumberValue(value) )
328 libvlc_audio_set_track(p_md, numberValue(value));
329 return INVOKERESULT_NO_ERROR;
331 return INVOKERESULT_INVALID_VALUE;
332 case ID_audio_channel:
333 if( isNumberValue(value) )
335 libvlc_audio_set_channel(p_md, numberValue(value));
336 return INVOKERESULT_NO_ERROR;
338 return INVOKERESULT_INVALID_VALUE;
343 return INVOKERESULT_GENERIC_ERROR;
346 const NPUTF8 * const LibvlcAudioNPObject::methodNames[] =
351 COUNTNAMES(LibvlcAudioNPObject,methodCount,methodNames);
353 enum LibvlcAudioNPObjectMethodIds
356 ID_audio_description,
359 RuntimeNPObject::InvokeResult
360 LibvlcAudioNPObject::invoke(int index, const NPVariant *args,
361 uint32_t argCount, NPVariant &result)
363 /* is plugin still running */
364 if( isPluginRunning() )
366 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
367 libvlc_media_player_t *p_md = p_plugin->getMD();
373 case ID_audio_togglemute:
376 libvlc_audio_toggle_mute(p_md);
377 VOID_TO_NPVARIANT(result);
378 return INVOKERESULT_NO_ERROR;
380 return INVOKERESULT_NO_SUCH_METHOD;
381 case ID_audio_description:
386 int i_trackID, i_limit, i;
387 libvlc_track_description_t *p_trackDesc;
389 /* get tracks description */
390 p_trackDesc = libvlc_audio_get_track_description(p_md);
392 return INVOKERESULT_GENERIC_ERROR;
394 /* get the number of track available */
395 i_limit = libvlc_audio_get_track_count(p_md);
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]);
402 return INVOKERESULT_INVALID_VALUE;
404 /* if bad number is given return invalid value */
405 if ( ( i_trackID > ( i_limit - 1 ) ) || ( i_trackID < 0 ) )
406 return INVOKERESULT_INVALID_VALUE;
408 /* get the good trackDesc */
409 for( i = 0 ; i < i_trackID ; i++ )
411 p_trackDesc = p_trackDesc->p_next;
413 psz_name = p_trackDesc->psz_name;
415 /* display the name of the track chosen */
416 return invokeResultString( psz_name, result );
418 return INVOKERESULT_NO_SUCH_METHOD;
424 return INVOKERESULT_GENERIC_ERROR;
428 ** implementation of libvlc input object
431 const NPUTF8 * const LibvlcInputNPObject::propertyNames[] =
441 COUNTNAMES(LibvlcInputNPObject,propertyCount,propertyNames);
443 enum LibvlcInputNPObjectPropertyIds
454 RuntimeNPObject::InvokeResult
455 LibvlcInputNPObject::getProperty(int index, NPVariant &result)
457 /* is plugin still running */
458 if( isPluginRunning() )
460 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
461 libvlc_media_player_t *p_md = p_plugin->getMD();
464 if( index != ID_input_state )
468 /* for input state, return CLOSED rather than an exception */
469 INT32_TO_NPVARIANT(0, result);
470 return INVOKERESULT_NO_ERROR;
476 case ID_input_length:
478 double val = (double)libvlc_media_player_get_length(p_md);
479 DOUBLE_TO_NPVARIANT(val, result);
480 return INVOKERESULT_NO_ERROR;
482 case ID_input_position:
484 double val = libvlc_media_player_get_position(p_md);
485 DOUBLE_TO_NPVARIANT(val, result);
486 return INVOKERESULT_NO_ERROR;
490 double val = (double)libvlc_media_player_get_time(p_md);
491 DOUBLE_TO_NPVARIANT(val, result);
492 return INVOKERESULT_NO_ERROR;
496 int val = libvlc_media_player_get_state(p_md);
497 INT32_TO_NPVARIANT(val, result);
498 return INVOKERESULT_NO_ERROR;
502 float val = libvlc_media_player_get_rate(p_md);
503 DOUBLE_TO_NPVARIANT(val, result);
504 return INVOKERESULT_NO_ERROR;
508 double val = libvlc_media_player_get_fps(p_md);
509 DOUBLE_TO_NPVARIANT(val, result);
510 return INVOKERESULT_NO_ERROR;
512 case ID_input_hasvout:
514 bool val = p_plugin->player_has_vout();
515 BOOLEAN_TO_NPVARIANT(val, result);
516 return INVOKERESULT_NO_ERROR;
522 return INVOKERESULT_GENERIC_ERROR;
525 RuntimeNPObject::InvokeResult
526 LibvlcInputNPObject::setProperty(int index, const NPVariant &value)
528 /* is plugin still running */
529 if( isPluginRunning() )
531 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
532 libvlc_media_player_t *p_md = p_plugin->getMD();
535 NPN_SetException(this, libvlc_errmsg() );
536 return INVOKERESULT_GENERIC_ERROR;
541 case ID_input_position:
543 if( ! NPVARIANT_IS_DOUBLE(value) )
545 return INVOKERESULT_INVALID_VALUE;
548 float val = (float)NPVARIANT_TO_DOUBLE(value);
549 libvlc_media_player_set_position(p_md, val);
550 return INVOKERESULT_NO_ERROR;
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);
561 return INVOKERESULT_INVALID_VALUE;
564 libvlc_media_player_set_time(p_md, val);
565 return INVOKERESULT_NO_ERROR;
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);
576 return INVOKERESULT_INVALID_VALUE;
579 libvlc_media_player_set_rate(p_md, val);
580 return INVOKERESULT_NO_ERROR;
586 return INVOKERESULT_GENERIC_ERROR;
589 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =
594 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
596 enum LibvlcInputNPObjectMethodIds
601 RuntimeNPObject::InvokeResult
602 LibvlcInputNPObject::invoke(int index, const NPVariant *args,
603 uint32_t argCount, NPVariant &result)
605 /* is plugin still running */
606 if( isPluginRunning() )
611 return INVOKERESULT_NO_SUCH_METHOD;
616 return INVOKERESULT_GENERIC_ERROR;
620 ** implementation of libvlc playlist items object
623 const NPUTF8 * const LibvlcPlaylistItemsNPObject::propertyNames[] =
627 COUNTNAMES(LibvlcPlaylistItemsNPObject,propertyCount,propertyNames);
629 enum LibvlcPlaylistItemsNPObjectPropertyIds
631 ID_playlistitems_count,
634 RuntimeNPObject::InvokeResult
635 LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
637 /* is plugin still running */
638 if( isPluginRunning() )
640 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
644 case ID_playlistitems_count:
646 int val = p_plugin->playlist_count();
647 INT32_TO_NPVARIANT(val, result);
648 return INVOKERESULT_NO_ERROR;
654 return INVOKERESULT_GENERIC_ERROR;
657 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
662 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
664 enum LibvlcPlaylistItemsNPObjectMethodIds
666 ID_playlistitems_clear,
667 ID_playlistitems_remove,
670 RuntimeNPObject::InvokeResult
671 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
672 uint32_t argCount, NPVariant &result)
674 /* is plugin still running */
675 if( isPluginRunning() )
677 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
681 case ID_playlistitems_clear:
684 p_plugin->playlist_clear();
685 VOID_TO_NPVARIANT(result);
686 return INVOKERESULT_NO_ERROR;
688 return INVOKERESULT_NO_SUCH_METHOD;
689 case ID_playlistitems_remove:
690 if( (argCount == 1) && isNumberValue(args[0]) )
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;
697 return INVOKERESULT_NO_SUCH_METHOD;
702 return INVOKERESULT_GENERIC_ERROR;
706 ** implementation of libvlc playlist object
709 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
711 // Why the isValid()?
712 if( isValid() && playlistItemsObj )
713 NPN_ReleaseObject(playlistItemsObj);
716 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
718 "itemCount", /* deprecated */
722 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
724 enum LibvlcPlaylistNPObjectPropertyIds
726 ID_playlist_itemcount,
727 ID_playlist_isplaying,
731 RuntimeNPObject::InvokeResult
732 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
734 /* is plugin still running */
735 if( isPluginRunning() )
737 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
741 case ID_playlist_itemcount: /* deprecated */
743 int val = p_plugin->playlist_count();
744 INT32_TO_NPVARIANT(val, result);
745 return INVOKERESULT_NO_ERROR;
747 case ID_playlist_isplaying:
749 int val = p_plugin->playlist_isplaying();
750 BOOLEAN_TO_NPVARIANT(val, result);
751 return INVOKERESULT_NO_ERROR;
753 case ID_playlist_items:
755 InstantObj<LibvlcPlaylistItemsNPObject>( playlistItemsObj );
756 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
757 return INVOKERESULT_NO_ERROR;
763 return INVOKERESULT_GENERIC_ERROR;
766 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
775 "clear", /* deprecated */
776 "removeItem", /* deprecated */
778 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
780 enum LibvlcPlaylistNPObjectMethodIds
784 ID_playlist_playItem,
785 ID_playlist_togglepause,
790 ID_playlist_removeitem
793 RuntimeNPObject::InvokeResult
794 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
795 uint32_t argCount, NPVariant &result)
797 /* is plugin still running */
798 if( isPluginRunning() )
800 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
804 // XXX FIXME this needs squashing into something much smaller
805 case ID_playlist_add:
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;
813 if( NPVARIANT_IS_NULL(args[0]) )
814 return INVOKERESULT_NO_SUCH_METHOD;
816 char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
818 return INVOKERESULT_OUT_OF_MEMORY;
820 char *url = p_plugin->getAbsoluteURL(s);
824 // problem with combining url, use argument
829 // grab name if available
832 if( NPVARIANT_IS_NULL(args[1]) )
836 else if( NPVARIANT_IS_STRING(args[1]) )
838 name = stringValue(NPVARIANT_TO_STRING(args[1]));
843 return INVOKERESULT_INVALID_VALUE;
848 char** ppsz_options = NULL;
850 // grab options if available
853 if( NPVARIANT_IS_NULL(args[2]) )
857 else if( NPVARIANT_IS_STRING(args[2]) )
859 parseOptions(NPVARIANT_TO_STRING(args[2]),
860 &i_options, &ppsz_options);
863 else if( NPVARIANT_IS_OBJECT(args[2]) )
865 parseOptions(NPVARIANT_TO_OBJECT(args[2]),
866 &i_options, &ppsz_options);
872 return INVOKERESULT_INVALID_VALUE;
876 int item = p_plugin->playlist_add_extended_untrusted(url, name,
877 i_options, const_cast<const char **>(ppsz_options));
883 for( int i=0; i< i_options; ++i )
885 free(ppsz_options[i]);
889 INT32_TO_NPVARIANT(item, result);
890 return INVOKERESULT_NO_ERROR;
892 case ID_playlist_play:
895 p_plugin->playlist_play();
896 VOID_TO_NPVARIANT(result);
897 return INVOKERESULT_NO_ERROR;
899 return INVOKERESULT_NO_SUCH_METHOD;
900 case ID_playlist_playItem:
901 if( (argCount == 1) && isNumberValue(args[0]) )
903 p_plugin->playlist_play_item(numberValue(args[0]));
904 VOID_TO_NPVARIANT(result);
905 return INVOKERESULT_NO_ERROR;
907 return INVOKERESULT_NO_SUCH_METHOD;
908 case ID_playlist_togglepause:
911 p_plugin->playlist_pause();
912 VOID_TO_NPVARIANT(result);
913 return INVOKERESULT_NO_ERROR;
915 return INVOKERESULT_NO_SUCH_METHOD;
916 case ID_playlist_stop:
919 p_plugin->playlist_stop();
920 VOID_TO_NPVARIANT(result);
921 return INVOKERESULT_NO_ERROR;
923 return INVOKERESULT_NO_SUCH_METHOD;
924 case ID_playlist_next:
927 p_plugin->playlist_next();
928 VOID_TO_NPVARIANT(result);
929 return INVOKERESULT_NO_ERROR;
931 return INVOKERESULT_NO_SUCH_METHOD;
932 case ID_playlist_prev:
935 p_plugin->playlist_prev();
936 VOID_TO_NPVARIANT(result);
937 return INVOKERESULT_NO_ERROR;
939 return INVOKERESULT_NO_SUCH_METHOD;
940 case ID_playlist_clear: /* deprecated */
943 p_plugin->playlist_clear();
944 VOID_TO_NPVARIANT(result);
945 return INVOKERESULT_NO_ERROR;
947 return INVOKERESULT_NO_SUCH_METHOD;
948 case ID_playlist_removeitem: /* deprecated */
949 if( (argCount == 1) && isNumberValue(args[0]) )
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;
956 return INVOKERESULT_NO_SUCH_METHOD;
961 return INVOKERESULT_GENERIC_ERROR;
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.
970 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
971 int *i_options, char*** ppsz_options)
975 char *s = stringValue(nps);
980 char **options = (char **)malloc(capacity*sizeof(char *));
985 char *end = val + nps.utf8length;
988 // skip leading blanks
990 && ((*val == ' ' ) || (*val == '\t')) )
994 // skip till we get a blank character
1000 if( ('\'' == c) || ('"' == c) )
1002 // skip till end of string
1003 while( (val < end) && (*(val++) != c ) );
1009 if( nOptions == capacity )
1012 char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1015 /* failed to allocate more memory */
1017 /* return what we got so far */
1018 *i_options = nOptions;
1019 *ppsz_options = options;
1022 options = moreOptions;
1025 options[nOptions++] = strdup(start);
1028 // must be end of string
1031 *i_options = nOptions;
1032 *ppsz_options = options;
1039 // XXX FIXME See comment at the other parseOptions variant.
1040 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
1041 char*** ppsz_options)
1043 /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1047 /* we are expecting to have a Javascript Array object */
1048 NPIdentifier propId = NPN_GetStringIdentifier("length");
1049 if( NPN_GetProperty(_instance, obj, propId, &value) )
1051 int count = numberValue(value);
1052 NPN_ReleaseVariantValue(&value);
1057 char **options = (char **)malloc(capacity*sizeof(char *));
1062 while( nOptions < count )
1064 propId = NPN_GetIntIdentifier(nOptions);
1065 if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1066 /* return what we got so far */
1069 if( ! NPVARIANT_IS_STRING(value) )
1071 /* return what we got so far */
1072 NPN_ReleaseVariantValue(&value);
1076 if( nOptions == capacity )
1079 char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
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;
1089 options = moreOptions;
1092 options[nOptions++] = stringValue(value);
1093 NPN_ReleaseVariantValue(&value);
1095 *i_options = nOptions;
1096 *ppsz_options = options;
1103 ** implementation of libvlc subtitle object
1106 const NPUTF8 * const LibvlcSubtitleNPObject::propertyNames[] =
1112 enum LibvlcSubtitleNPObjectPropertyIds
1117 COUNTNAMES(LibvlcSubtitleNPObject,propertyCount,propertyNames);
1119 RuntimeNPObject::InvokeResult
1120 LibvlcSubtitleNPObject::getProperty(int index, NPVariant &result)
1122 /* is plugin still running */
1123 if( isPluginRunning() )
1125 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1126 libvlc_media_player_t *p_md = p_plugin->getMD();
1132 case ID_subtitle_track:
1134 /* get the current subtitle ID */
1135 int i_spu = libvlc_video_get_spu(p_md);
1137 INT32_TO_NPVARIANT(i_spu, result);
1138 return INVOKERESULT_NO_ERROR;
1140 case ID_subtitle_count:
1142 /* get the number of subtitles available */
1143 int i_spu = libvlc_video_get_spu_count(p_md);
1145 INT32_TO_NPVARIANT(i_spu, result);
1146 return INVOKERESULT_NO_ERROR;
1150 return INVOKERESULT_GENERIC_ERROR;
1153 RuntimeNPObject::InvokeResult
1154 LibvlcSubtitleNPObject::setProperty(int index, const NPVariant &value)
1156 /* is plugin still running */
1157 if( isPluginRunning() )
1159 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1160 libvlc_media_player_t *p_md = p_plugin->getMD();
1166 case ID_subtitle_track:
1168 if( isNumberValue(value) )
1170 /* set the new subtitle track to show */
1171 libvlc_video_set_spu(p_md, numberValue(value));
1173 return INVOKERESULT_NO_ERROR;
1175 return INVOKERESULT_INVALID_VALUE;
1179 return INVOKERESULT_GENERIC_ERROR;
1182 const NPUTF8 * const LibvlcSubtitleNPObject::methodNames[] =
1186 COUNTNAMES(LibvlcSubtitleNPObject,methodCount,methodNames);
1188 enum LibvlcSubtitleNPObjectMethodIds
1190 ID_subtitle_description
1193 RuntimeNPObject::InvokeResult
1194 LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
1195 uint32_t argCount, NPVariant &result)
1197 /* is plugin still running */
1198 if( isPluginRunning() )
1200 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1201 libvlc_media_player_t *p_md = p_plugin->getMD();
1207 case ID_subtitle_description:
1212 int i_spuID, i_limit, i;
1213 libvlc_track_description_t *p_spuDesc;
1215 /* get subtitles description */
1216 p_spuDesc = libvlc_video_get_spu_description(p_md);
1218 return INVOKERESULT_GENERIC_ERROR;
1220 /* get the number of subtitle available */
1221 i_limit = libvlc_video_get_spu_count(p_md);
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]);
1228 return INVOKERESULT_INVALID_VALUE;
1230 /* if bad number is given return invalid value */
1231 if ( ( i_spuID > ( i_limit -1 ) ) || ( i_spuID < 0 ) )
1232 return INVOKERESULT_INVALID_VALUE;
1234 /* get the good spuDesc */
1235 for( i = 0 ; i < i_spuID ; i++ )
1237 p_spuDesc = p_spuDesc->p_next;
1239 psz_name = p_spuDesc->psz_name;
1241 /* return the name of the track chosen */
1242 return invokeResultString(psz_name, result);
1244 return INVOKERESULT_NO_SUCH_METHOD;
1247 return INVOKERESULT_NO_SUCH_METHOD;
1250 return INVOKERESULT_GENERIC_ERROR;
1254 ** implementation of libvlc video object
1257 LibvlcVideoNPObject::~LibvlcVideoNPObject()
1261 if( marqueeObj ) NPN_ReleaseObject(marqueeObj);
1262 if( logoObj ) NPN_ReleaseObject(logoObj);
1263 if( deintObj ) NPN_ReleaseObject(deintObj);
1267 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1281 enum LibvlcVideoNPObjectPropertyIds
1283 ID_video_fullscreen,
1286 ID_video_aspectratio,
1292 ID_video_deinterlace,
1294 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1296 RuntimeNPObject::InvokeResult
1297 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1299 /* is plugin still running */
1300 if( isPluginRunning() )
1302 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1303 libvlc_media_player_t *p_md = p_plugin->getMD();
1309 case ID_video_fullscreen:
1311 int val = p_plugin->get_fullscreen();
1312 BOOLEAN_TO_NPVARIANT(val, result);
1313 return INVOKERESULT_NO_ERROR;
1315 case ID_video_height:
1317 int val = libvlc_video_get_height(p_md);
1318 INT32_TO_NPVARIANT(val, result);
1319 return INVOKERESULT_NO_ERROR;
1321 case ID_video_width:
1323 int val = libvlc_video_get_width(p_md);
1324 INT32_TO_NPVARIANT(val, result);
1325 return INVOKERESULT_NO_ERROR;
1327 case ID_video_aspectratio:
1329 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md);
1331 return INVOKERESULT_GENERIC_ERROR;
1333 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1334 return INVOKERESULT_NO_ERROR;
1336 case ID_video_subtitle:
1338 int i_spu = libvlc_video_get_spu(p_md);
1339 INT32_TO_NPVARIANT(i_spu, result);
1340 return INVOKERESULT_NO_ERROR;
1344 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md);
1346 return INVOKERESULT_GENERIC_ERROR;
1348 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1349 return INVOKERESULT_NO_ERROR;
1351 case ID_video_teletext:
1353 int i_page = libvlc_video_get_teletext(p_md);
1355 return INVOKERESULT_GENERIC_ERROR;
1356 INT32_TO_NPVARIANT(i_page, result);
1357 return INVOKERESULT_NO_ERROR;
1359 case ID_video_marquee:
1361 InstantObj<LibvlcMarqueeNPObject>( marqueeObj );
1362 OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1363 return INVOKERESULT_NO_ERROR;
1367 InstantObj<LibvlcLogoNPObject>( logoObj );
1368 OBJECT_TO_NPVARIANT(NPN_RetainObject(logoObj), result);
1369 return INVOKERESULT_NO_ERROR;
1371 case ID_video_deinterlace:
1373 InstantObj<LibvlcDeinterlaceNPObject>( deintObj );
1374 OBJECT_TO_NPVARIANT(NPN_RetainObject(deintObj), result);
1375 return INVOKERESULT_NO_ERROR;
1379 return INVOKERESULT_GENERIC_ERROR;
1382 RuntimeNPObject::InvokeResult
1383 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1385 /* is plugin still running */
1386 if( isPluginRunning() )
1388 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1389 libvlc_media_player_t *p_md = p_plugin->getMD();
1395 case ID_video_fullscreen:
1397 if( ! NPVARIANT_IS_BOOLEAN(value) )
1399 return INVOKERESULT_INVALID_VALUE;
1402 int val = NPVARIANT_TO_BOOLEAN(value);
1403 p_plugin->set_fullscreen(val);
1404 return INVOKERESULT_NO_ERROR;
1406 case ID_video_aspectratio:
1408 char *psz_aspect = NULL;
1410 if( ! NPVARIANT_IS_STRING(value) )
1412 return INVOKERESULT_INVALID_VALUE;
1415 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1418 return INVOKERESULT_GENERIC_ERROR;
1421 libvlc_video_set_aspect_ratio(p_md, psz_aspect);
1424 return INVOKERESULT_NO_ERROR;
1426 case ID_video_subtitle:
1428 if( isNumberValue(value) )
1430 libvlc_video_set_spu(p_md, numberValue(value));
1432 return INVOKERESULT_NO_ERROR;
1434 return INVOKERESULT_INVALID_VALUE;
1438 char *psz_geometry = NULL;
1440 if( ! NPVARIANT_IS_STRING(value) )
1442 return INVOKERESULT_INVALID_VALUE;
1445 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1448 return INVOKERESULT_GENERIC_ERROR;
1451 libvlc_video_set_crop_geometry(p_md, psz_geometry);
1454 return INVOKERESULT_NO_ERROR;
1456 case ID_video_teletext:
1458 if( isNumberValue(value) )
1460 libvlc_video_set_teletext(p_md, numberValue(value));
1461 return INVOKERESULT_NO_ERROR;
1463 return INVOKERESULT_INVALID_VALUE;
1467 return INVOKERESULT_GENERIC_ERROR;
1470 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1475 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1477 enum LibvlcVideoNPObjectMethodIds
1479 ID_video_togglefullscreen,
1480 ID_video_toggleteletext,
1483 RuntimeNPObject::InvokeResult
1484 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1485 uint32_t argCount, NPVariant &result)
1487 /* is plugin still running */
1488 if( isPluginRunning() )
1490 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1491 libvlc_media_player_t *p_md = p_plugin->getMD();
1497 case ID_video_togglefullscreen:
1501 p_plugin->toggle_fullscreen();
1502 VOID_TO_NPVARIANT(result);
1503 return INVOKERESULT_NO_ERROR;
1505 return INVOKERESULT_NO_SUCH_METHOD;
1507 case ID_video_toggleteletext:
1511 libvlc_toggle_teletext(p_md);
1512 VOID_TO_NPVARIANT(result);
1513 return INVOKERESULT_NO_ERROR;
1515 return INVOKERESULT_NO_SUCH_METHOD;
1518 return INVOKERESULT_NO_SUCH_METHOD;
1521 return INVOKERESULT_GENERIC_ERROR;
1525 ** implementation of libvlc marquee object
1528 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1541 enum LibvlcMarqueeNPObjectPropertyIds
1545 ID_marquee_position,
1554 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
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,
1563 libvlc_marquee_Timeout,
1568 RuntimeNPObject::InvokeResult
1569 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1573 if( !isPluginRunning() )
1574 return INVOKERESULT_GENERIC_ERROR;
1576 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1577 libvlc_media_player_t *p_md = p_plugin->getMD();
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:
1591 libvlc_video_get_marquee_int(p_md, marquee_idx[index]),
1593 return INVOKERESULT_NO_ERROR;
1595 case ID_marquee_position:
1596 STRINGZ_TO_NPVARIANT( position_bynumber(
1597 libvlc_video_get_marquee_int(p_md, libvlc_marquee_Position) ),
1602 case ID_marquee_text:
1603 psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text);
1606 STRINGZ_TO_NPVARIANT(psz, result);
1607 return INVOKERESULT_NO_ERROR;
1611 return INVOKERESULT_GENERIC_ERROR;
1614 RuntimeNPObject::InvokeResult
1615 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1619 if( !isPluginRunning() )
1620 return INVOKERESULT_GENERIC_ERROR;
1622 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1623 libvlc_media_player_t *p_md = p_plugin->getMD();
1629 case ID_marquee_color:
1630 case ID_marquee_opacity:
1631 case ID_marquee_refresh:
1632 case ID_marquee_timeout:
1635 if( NPVARIANT_IS_INT32( value ) )
1637 libvlc_video_set_marquee_int(p_md, marquee_idx[index],
1638 NPVARIANT_TO_INT32( value ));
1639 return INVOKERESULT_NO_ERROR;
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;
1648 libvlc_video_set_marquee_int(p_md, libvlc_marquee_Position, i);
1649 return INVOKERESULT_NO_ERROR;
1651 case ID_marquee_text:
1652 if( NPVARIANT_IS_STRING( value ) )
1654 char *psz_text = stringValue( NPVARIANT_TO_STRING( value ) );
1655 libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
1658 return INVOKERESULT_NO_ERROR;
1662 return INVOKERESULT_NO_SUCH_METHOD;
1665 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1670 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1672 enum LibvlcMarqueeNPObjectMethodIds
1678 RuntimeNPObject::InvokeResult
1679 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1680 uint32_t argCount, NPVariant &result)
1682 if( !isPluginRunning() )
1683 return INVOKERESULT_GENERIC_ERROR;
1685 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1686 libvlc_media_player_t *p_md = p_plugin->getMD();
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;
1699 return INVOKERESULT_NO_SUCH_METHOD;
1702 const NPUTF8 * const LibvlcLogoNPObject::propertyNames[] = {
1710 enum LibvlcLogoNPObjectPropertyIds {
1718 COUNTNAMES(LibvlcLogoNPObject,propertyCount,propertyNames);
1719 static const unsigned char logo_idx[] = {
1722 libvlc_logo_opacity,
1728 RuntimeNPObject::InvokeResult
1729 LibvlcLogoNPObject::getProperty(int index, NPVariant &result)
1731 if( !isPluginRunning() )
1732 return INVOKERESULT_GENERIC_ERROR;
1734 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1735 libvlc_media_player_t *p_md = p_plugin->getMD();
1742 case ID_logo_repeat:
1743 case ID_logo_opacity:
1748 libvlc_video_get_logo_int(p_md, logo_idx[index]), result);
1751 case ID_logo_position:
1752 STRINGZ_TO_NPVARIANT( position_bynumber(
1753 libvlc_video_get_logo_int(p_md, libvlc_logo_position) ),
1757 return INVOKERESULT_GENERIC_ERROR;
1759 return INVOKERESULT_NO_ERROR;
1762 RuntimeNPObject::InvokeResult
1763 LibvlcLogoNPObject::setProperty(int index, const NPVariant &value)
1767 if( !isPluginRunning() )
1768 return INVOKERESULT_GENERIC_ERROR;
1770 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1771 libvlc_media_player_t *p_md = p_plugin->getMD();
1778 case ID_logo_repeat:
1779 case ID_logo_opacity:
1782 if( !NPVARIANT_IS_INT32(value) )
1783 return INVOKERESULT_INVALID_VALUE;
1785 libvlc_video_set_logo_int(p_md, logo_idx[index],
1786 NPVARIANT_TO_INT32( value ));
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;
1794 libvlc_video_set_logo_int(p_md, libvlc_logo_position, i);
1797 return INVOKERESULT_GENERIC_ERROR;
1799 return INVOKERESULT_NO_ERROR;
1803 const NPUTF8 * const LibvlcLogoNPObject::methodNames[] = {
1808 enum LibvlcLogoNPObjectMethodIds {
1813 COUNTNAMES(LibvlcLogoNPObject,methodCount,methodNames);
1815 RuntimeNPObject::InvokeResult
1816 LibvlcLogoNPObject::invoke(int index, const NPVariant *args,
1817 uint32_t argCount, NPVariant &result)
1822 if( !isPluginRunning() )
1823 return INVOKERESULT_GENERIC_ERROR;
1825 libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD();
1831 case ID_logo_enable:
1832 case ID_logo_disable:
1834 return INVOKERESULT_GENERIC_ERROR;
1836 libvlc_video_set_logo_int(p_md, libvlc_logo_enable,
1837 index != ID_logo_disable);
1838 VOID_TO_NPVARIANT(result);
1843 return INVOKERESULT_GENERIC_ERROR;
1845 for( len=0,i=0;i<argCount;++i )
1847 if( !NPVARIANT_IS_STRING(args[i]) )
1848 return INVOKERESULT_INVALID_VALUE;
1849 len+=NPVARIANT_TO_STRING(args[i]).utf8length+1;
1852 buf = (char *)malloc( len+1 );
1854 return INVOKERESULT_OUT_OF_MEMORY;
1856 for( h=buf,i=0;i<argCount;++i )
1859 len=NPVARIANT_TO_STRING(args[i]).utf8length;
1860 memcpy(h,NPVARIANT_TO_STRING(args[i]).utf8characters,len);
1865 libvlc_video_set_logo_string(p_md, libvlc_logo_file, buf);
1867 VOID_TO_NPVARIANT(result);
1870 return INVOKERESULT_NO_SUCH_METHOD;
1872 return INVOKERESULT_NO_ERROR;
1876 const NPUTF8 * const LibvlcDeinterlaceNPObject::propertyNames[] = {
1878 enum LibvlcDeinterlaceNPObjectPropertyIds {
1880 COUNTNAMES(LibvlcDeinterlaceNPObject,propertyCount,propertyNames);
1882 RuntimeNPObject::InvokeResult
1883 LibvlcDeinterlaceNPObject::getProperty(int index, NPVariant &result)
1885 return INVOKERESULT_GENERIC_ERROR;
1888 RuntimeNPObject::InvokeResult
1889 LibvlcDeinterlaceNPObject::setProperty(int index, const NPVariant &value)
1891 return INVOKERESULT_GENERIC_ERROR;
1895 const NPUTF8 * const LibvlcDeinterlaceNPObject::methodNames[] = {
1899 enum LibvlcDeinterlaceNPObjectMethodIds {
1903 COUNTNAMES(LibvlcDeinterlaceNPObject,methodCount,methodNames);
1905 RuntimeNPObject::InvokeResult
1906 LibvlcDeinterlaceNPObject::invoke(int index, const NPVariant *args,
1907 uint32_t argCount, NPVariant &result)
1911 if( !isPluginRunning() )
1912 return INVOKERESULT_GENERIC_ERROR;
1914 libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD();
1920 case ID_deint_disable:
1921 libvlc_video_set_deinterlace(p_md, NULL);
1924 case ID_deint_enable:
1925 if( argCount != 1 || !NPVARIANT_IS_STRING( args[0] ) )
1926 return INVOKERESULT_INVALID_VALUE;
1928 psz = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1929 libvlc_video_set_deinterlace(p_md, psz);
1934 return INVOKERESULT_NO_SUCH_METHOD;
1936 return INVOKERESULT_NO_ERROR;