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();
538 case ID_input_position:
540 if( ! NPVARIANT_IS_DOUBLE(value) )
542 return INVOKERESULT_INVALID_VALUE;
545 float val = (float)NPVARIANT_TO_DOUBLE(value);
546 libvlc_media_player_set_position(p_md, val);
547 return INVOKERESULT_NO_ERROR;
552 if( NPVARIANT_IS_INT32(value) )
553 val = (int64_t)NPVARIANT_TO_INT32(value);
554 else if( NPVARIANT_IS_DOUBLE(value) )
555 val = (int64_t)NPVARIANT_TO_DOUBLE(value);
558 return INVOKERESULT_INVALID_VALUE;
561 libvlc_media_player_set_time(p_md, val);
562 return INVOKERESULT_NO_ERROR;
567 if( NPVARIANT_IS_INT32(value) )
568 val = (float)NPVARIANT_TO_INT32(value);
569 else if( NPVARIANT_IS_DOUBLE(value) )
570 val = (float)NPVARIANT_TO_DOUBLE(value);
573 return INVOKERESULT_INVALID_VALUE;
576 libvlc_media_player_set_rate(p_md, val);
577 return INVOKERESULT_NO_ERROR;
583 return INVOKERESULT_GENERIC_ERROR;
586 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =
591 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
593 enum LibvlcInputNPObjectMethodIds
598 RuntimeNPObject::InvokeResult
599 LibvlcInputNPObject::invoke(int index, const NPVariant *args,
600 uint32_t argCount, NPVariant &result)
602 /* is plugin still running */
603 if( isPluginRunning() )
608 return INVOKERESULT_NO_SUCH_METHOD;
613 return INVOKERESULT_GENERIC_ERROR;
617 ** implementation of libvlc playlist items object
620 const NPUTF8 * const LibvlcPlaylistItemsNPObject::propertyNames[] =
624 COUNTNAMES(LibvlcPlaylistItemsNPObject,propertyCount,propertyNames);
626 enum LibvlcPlaylistItemsNPObjectPropertyIds
628 ID_playlistitems_count,
631 RuntimeNPObject::InvokeResult
632 LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
634 /* is plugin still running */
635 if( isPluginRunning() )
637 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
641 case ID_playlistitems_count:
643 int val = p_plugin->playlist_count();
644 INT32_TO_NPVARIANT(val, result);
645 return INVOKERESULT_NO_ERROR;
651 return INVOKERESULT_GENERIC_ERROR;
654 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
659 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
661 enum LibvlcPlaylistItemsNPObjectMethodIds
663 ID_playlistitems_clear,
664 ID_playlistitems_remove,
667 RuntimeNPObject::InvokeResult
668 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
669 uint32_t argCount, NPVariant &result)
671 /* is plugin still running */
672 if( isPluginRunning() )
674 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
678 case ID_playlistitems_clear:
681 p_plugin->playlist_clear();
682 VOID_TO_NPVARIANT(result);
683 return INVOKERESULT_NO_ERROR;
685 return INVOKERESULT_NO_SUCH_METHOD;
686 case ID_playlistitems_remove:
687 if( (argCount == 1) && isNumberValue(args[0]) )
689 if( !p_plugin->playlist_delete_item(numberValue(args[0])) )
690 return INVOKERESULT_GENERIC_ERROR;
691 VOID_TO_NPVARIANT(result);
692 return INVOKERESULT_NO_ERROR;
694 return INVOKERESULT_NO_SUCH_METHOD;
699 return INVOKERESULT_GENERIC_ERROR;
703 ** implementation of libvlc playlist object
706 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
708 // Why the isValid()?
709 if( isValid() && playlistItemsObj )
710 NPN_ReleaseObject(playlistItemsObj);
713 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] =
715 "itemCount", /* deprecated */
719 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
721 enum LibvlcPlaylistNPObjectPropertyIds
723 ID_playlist_itemcount,
724 ID_playlist_isplaying,
728 RuntimeNPObject::InvokeResult
729 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
731 /* is plugin still running */
732 if( isPluginRunning() )
734 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
738 case ID_playlist_itemcount: /* deprecated */
740 int val = p_plugin->playlist_count();
741 INT32_TO_NPVARIANT(val, result);
742 return INVOKERESULT_NO_ERROR;
744 case ID_playlist_isplaying:
746 int val = p_plugin->playlist_isplaying();
747 BOOLEAN_TO_NPVARIANT(val, result);
748 return INVOKERESULT_NO_ERROR;
750 case ID_playlist_items:
752 InstantObj<LibvlcPlaylistItemsNPObject>( playlistItemsObj );
753 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
754 return INVOKERESULT_NO_ERROR;
760 return INVOKERESULT_GENERIC_ERROR;
763 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
772 "clear", /* deprecated */
773 "removeItem", /* deprecated */
775 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
777 enum LibvlcPlaylistNPObjectMethodIds
781 ID_playlist_playItem,
782 ID_playlist_togglepause,
787 ID_playlist_removeitem
790 RuntimeNPObject::InvokeResult
791 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
792 uint32_t argCount, NPVariant &result)
794 /* is plugin still running */
795 if( isPluginRunning() )
797 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
801 // XXX FIXME this needs squashing into something much smaller
802 case ID_playlist_add:
804 if( (argCount < 1) || (argCount > 3) )
805 return INVOKERESULT_NO_SUCH_METHOD;
806 if( !NPVARIANT_IS_STRING(args[0]) )
807 return INVOKERESULT_NO_SUCH_METHOD;
810 if( NPVARIANT_IS_NULL(args[0]) )
811 return INVOKERESULT_NO_SUCH_METHOD;
813 char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
815 return INVOKERESULT_OUT_OF_MEMORY;
817 char *url = p_plugin->getAbsoluteURL(s);
821 // problem with combining url, use argument
826 // grab name if available
829 if( NPVARIANT_IS_NULL(args[1]) )
833 else if( NPVARIANT_IS_STRING(args[1]) )
835 name = stringValue(NPVARIANT_TO_STRING(args[1]));
840 return INVOKERESULT_INVALID_VALUE;
845 char** ppsz_options = NULL;
847 // grab options if available
850 if( NPVARIANT_IS_NULL(args[2]) )
854 else if( NPVARIANT_IS_STRING(args[2]) )
856 parseOptions(NPVARIANT_TO_STRING(args[2]),
857 &i_options, &ppsz_options);
860 else if( NPVARIANT_IS_OBJECT(args[2]) )
862 parseOptions(NPVARIANT_TO_OBJECT(args[2]),
863 &i_options, &ppsz_options);
869 return INVOKERESULT_INVALID_VALUE;
873 int item = p_plugin->playlist_add_extended_untrusted(url, name,
874 i_options, const_cast<const char **>(ppsz_options));
880 for( int i=0; i< i_options; ++i )
882 free(ppsz_options[i]);
886 INT32_TO_NPVARIANT(item, result);
887 return INVOKERESULT_NO_ERROR;
889 case ID_playlist_play:
892 p_plugin->playlist_play();
893 VOID_TO_NPVARIANT(result);
894 return INVOKERESULT_NO_ERROR;
896 return INVOKERESULT_NO_SUCH_METHOD;
897 case ID_playlist_playItem:
898 if( (argCount == 1) && isNumberValue(args[0]) )
900 p_plugin->playlist_play_item(numberValue(args[0]));
901 VOID_TO_NPVARIANT(result);
902 return INVOKERESULT_NO_ERROR;
904 return INVOKERESULT_NO_SUCH_METHOD;
905 case ID_playlist_togglepause:
908 p_plugin->playlist_pause();
909 VOID_TO_NPVARIANT(result);
910 return INVOKERESULT_NO_ERROR;
912 return INVOKERESULT_NO_SUCH_METHOD;
913 case ID_playlist_stop:
916 p_plugin->playlist_stop();
917 VOID_TO_NPVARIANT(result);
918 return INVOKERESULT_NO_ERROR;
920 return INVOKERESULT_NO_SUCH_METHOD;
921 case ID_playlist_next:
924 p_plugin->playlist_next();
925 VOID_TO_NPVARIANT(result);
926 return INVOKERESULT_NO_ERROR;
928 return INVOKERESULT_NO_SUCH_METHOD;
929 case ID_playlist_prev:
932 p_plugin->playlist_prev();
933 VOID_TO_NPVARIANT(result);
934 return INVOKERESULT_NO_ERROR;
936 return INVOKERESULT_NO_SUCH_METHOD;
937 case ID_playlist_clear: /* deprecated */
940 p_plugin->playlist_clear();
941 VOID_TO_NPVARIANT(result);
942 return INVOKERESULT_NO_ERROR;
944 return INVOKERESULT_NO_SUCH_METHOD;
945 case ID_playlist_removeitem: /* deprecated */
946 if( (argCount == 1) && isNumberValue(args[0]) )
948 if( !p_plugin->playlist_delete_item(numberValue(args[0])) )
949 return INVOKERESULT_GENERIC_ERROR;
950 VOID_TO_NPVARIANT(result);
951 return INVOKERESULT_NO_ERROR;
953 return INVOKERESULT_NO_SUCH_METHOD;
958 return INVOKERESULT_GENERIC_ERROR;
961 // XXX FIXME The new playlist_add creates a media instance and feeds it
962 // XXX FIXME these options one at a time, so this hunk of code does lots
963 // XXX FIXME of unnecessairy work. Break out something that can do one
964 // XXX FIXME option at a time and doesn't need to realloc().
965 // XXX FIXME Same for the other version of parseOptions.
967 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
968 int *i_options, char*** ppsz_options)
972 char *s = stringValue(nps);
977 char **options = (char **)malloc(capacity*sizeof(char *));
982 char *end = val + nps.UTF8Length;
985 // skip leading blanks
987 && ((*val == ' ' ) || (*val == '\t')) )
991 // skip till we get a blank character
997 if( ('\'' == c) || ('"' == c) )
999 // skip till end of string
1000 while( (val < end) && (*(val++) != c ) );
1006 if( nOptions == capacity )
1009 char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1012 /* failed to allocate more memory */
1014 /* return what we got so far */
1015 *i_options = nOptions;
1016 *ppsz_options = options;
1019 options = moreOptions;
1022 options[nOptions++] = strdup(start);
1025 // must be end of string
1028 *i_options = nOptions;
1029 *ppsz_options = options;
1036 // XXX FIXME See comment at the other parseOptions variant.
1037 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
1038 char*** ppsz_options)
1040 /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1044 /* we are expecting to have a Javascript Array object */
1045 NPIdentifier propId = NPN_GetStringIdentifier("length");
1046 if( NPN_GetProperty(_instance, obj, propId, &value) )
1048 int count = numberValue(value);
1049 NPN_ReleaseVariantValue(&value);
1054 char **options = (char **)malloc(capacity*sizeof(char *));
1059 while( nOptions < count )
1061 propId = NPN_GetIntIdentifier(nOptions);
1062 if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1063 /* return what we got so far */
1066 if( ! NPVARIANT_IS_STRING(value) )
1068 /* return what we got so far */
1069 NPN_ReleaseVariantValue(&value);
1073 if( nOptions == capacity )
1076 char **moreOptions = (char **)realloc(options, capacity*sizeof(char*));
1079 /* failed to allocate more memory */
1080 NPN_ReleaseVariantValue(&value);
1081 /* return what we got so far */
1082 *i_options = nOptions;
1083 *ppsz_options = options;
1086 options = moreOptions;
1089 options[nOptions++] = stringValue(value);
1090 NPN_ReleaseVariantValue(&value);
1092 *i_options = nOptions;
1093 *ppsz_options = options;
1100 ** implementation of libvlc subtitle object
1103 const NPUTF8 * const LibvlcSubtitleNPObject::propertyNames[] =
1109 enum LibvlcSubtitleNPObjectPropertyIds
1114 COUNTNAMES(LibvlcSubtitleNPObject,propertyCount,propertyNames);
1116 RuntimeNPObject::InvokeResult
1117 LibvlcSubtitleNPObject::getProperty(int index, NPVariant &result)
1119 /* is plugin still running */
1120 if( isPluginRunning() )
1122 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1123 libvlc_media_player_t *p_md = p_plugin->getMD();
1129 case ID_subtitle_track:
1131 /* get the current subtitle ID */
1132 int i_spu = libvlc_video_get_spu(p_md);
1134 INT32_TO_NPVARIANT(i_spu, result);
1135 return INVOKERESULT_NO_ERROR;
1137 case ID_subtitle_count:
1139 /* get the number of subtitles available */
1140 int i_spu = libvlc_video_get_spu_count(p_md);
1142 INT32_TO_NPVARIANT(i_spu, result);
1143 return INVOKERESULT_NO_ERROR;
1147 return INVOKERESULT_GENERIC_ERROR;
1150 RuntimeNPObject::InvokeResult
1151 LibvlcSubtitleNPObject::setProperty(int index, const NPVariant &value)
1153 /* is plugin still running */
1154 if( isPluginRunning() )
1156 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1157 libvlc_media_player_t *p_md = p_plugin->getMD();
1163 case ID_subtitle_track:
1165 if( isNumberValue(value) )
1167 /* set the new subtitle track to show */
1168 libvlc_video_set_spu(p_md, numberValue(value));
1170 return INVOKERESULT_NO_ERROR;
1172 return INVOKERESULT_INVALID_VALUE;
1176 return INVOKERESULT_GENERIC_ERROR;
1179 const NPUTF8 * const LibvlcSubtitleNPObject::methodNames[] =
1183 COUNTNAMES(LibvlcSubtitleNPObject,methodCount,methodNames);
1185 enum LibvlcSubtitleNPObjectMethodIds
1187 ID_subtitle_description
1190 RuntimeNPObject::InvokeResult
1191 LibvlcSubtitleNPObject::invoke(int index, const NPVariant *args,
1192 uint32_t argCount, NPVariant &result)
1194 /* is plugin still running */
1195 if( isPluginRunning() )
1197 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1198 libvlc_media_player_t *p_md = p_plugin->getMD();
1204 case ID_subtitle_description:
1209 int i_spuID, i_limit, i;
1210 libvlc_track_description_t *p_spuDesc;
1212 /* get subtitles description */
1213 p_spuDesc = libvlc_video_get_spu_description(p_md);
1215 return INVOKERESULT_GENERIC_ERROR;
1217 /* get the number of subtitle available */
1218 i_limit = libvlc_video_get_spu_count(p_md);
1220 /* check if a number is given by the user
1221 * and get the subtitle number */
1222 if( isNumberValue(args[0]) )
1223 i_spuID = numberValue(args[0]);
1225 return INVOKERESULT_INVALID_VALUE;
1227 /* if bad number is given return invalid value */
1228 if ( ( i_spuID > ( i_limit -1 ) ) || ( i_spuID < 0 ) )
1229 return INVOKERESULT_INVALID_VALUE;
1231 /* get the good spuDesc */
1232 for( i = 0 ; i < i_spuID ; i++ )
1234 p_spuDesc = p_spuDesc->p_next;
1236 psz_name = p_spuDesc->psz_name;
1238 /* return the name of the track chosen */
1239 return invokeResultString(psz_name, result);
1241 return INVOKERESULT_NO_SUCH_METHOD;
1244 return INVOKERESULT_NO_SUCH_METHOD;
1247 return INVOKERESULT_GENERIC_ERROR;
1251 ** implementation of libvlc video object
1254 LibvlcVideoNPObject::~LibvlcVideoNPObject()
1258 if( marqueeObj ) NPN_ReleaseObject(marqueeObj);
1259 if( logoObj ) NPN_ReleaseObject(logoObj);
1260 if( deintObj ) NPN_ReleaseObject(deintObj);
1264 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
1278 enum LibvlcVideoNPObjectPropertyIds
1280 ID_video_fullscreen,
1283 ID_video_aspectratio,
1289 ID_video_deinterlace,
1291 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1293 RuntimeNPObject::InvokeResult
1294 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1296 /* is plugin still running */
1297 if( isPluginRunning() )
1299 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1300 libvlc_media_player_t *p_md = p_plugin->getMD();
1306 case ID_video_fullscreen:
1308 int val = p_plugin->get_fullscreen();
1309 BOOLEAN_TO_NPVARIANT(val, result);
1310 return INVOKERESULT_NO_ERROR;
1312 case ID_video_height:
1314 int val = libvlc_video_get_height(p_md);
1315 INT32_TO_NPVARIANT(val, result);
1316 return INVOKERESULT_NO_ERROR;
1318 case ID_video_width:
1320 int val = libvlc_video_get_width(p_md);
1321 INT32_TO_NPVARIANT(val, result);
1322 return INVOKERESULT_NO_ERROR;
1324 case ID_video_aspectratio:
1326 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md);
1328 return INVOKERESULT_GENERIC_ERROR;
1330 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1331 return INVOKERESULT_NO_ERROR;
1333 case ID_video_subtitle:
1335 int i_spu = libvlc_video_get_spu(p_md);
1336 INT32_TO_NPVARIANT(i_spu, result);
1337 return INVOKERESULT_NO_ERROR;
1341 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md);
1343 return INVOKERESULT_GENERIC_ERROR;
1345 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1346 return INVOKERESULT_NO_ERROR;
1348 case ID_video_teletext:
1350 int i_page = libvlc_video_get_teletext(p_md);
1352 return INVOKERESULT_GENERIC_ERROR;
1353 INT32_TO_NPVARIANT(i_page, result);
1354 return INVOKERESULT_NO_ERROR;
1356 case ID_video_marquee:
1358 InstantObj<LibvlcMarqueeNPObject>( marqueeObj );
1359 OBJECT_TO_NPVARIANT(NPN_RetainObject(marqueeObj), result);
1360 return INVOKERESULT_NO_ERROR;
1364 InstantObj<LibvlcLogoNPObject>( logoObj );
1365 OBJECT_TO_NPVARIANT(NPN_RetainObject(logoObj), result);
1366 return INVOKERESULT_NO_ERROR;
1368 case ID_video_deinterlace:
1370 InstantObj<LibvlcDeinterlaceNPObject>( deintObj );
1371 OBJECT_TO_NPVARIANT(NPN_RetainObject(deintObj), result);
1372 return INVOKERESULT_NO_ERROR;
1376 return INVOKERESULT_GENERIC_ERROR;
1379 RuntimeNPObject::InvokeResult
1380 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1382 /* is plugin still running */
1383 if( isPluginRunning() )
1385 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1386 libvlc_media_player_t *p_md = p_plugin->getMD();
1392 case ID_video_fullscreen:
1394 if( ! NPVARIANT_IS_BOOLEAN(value) )
1396 return INVOKERESULT_INVALID_VALUE;
1399 int val = NPVARIANT_TO_BOOLEAN(value);
1400 p_plugin->set_fullscreen(val);
1401 return INVOKERESULT_NO_ERROR;
1403 case ID_video_aspectratio:
1405 char *psz_aspect = NULL;
1407 if( ! NPVARIANT_IS_STRING(value) )
1409 return INVOKERESULT_INVALID_VALUE;
1412 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1415 return INVOKERESULT_GENERIC_ERROR;
1418 libvlc_video_set_aspect_ratio(p_md, psz_aspect);
1421 return INVOKERESULT_NO_ERROR;
1423 case ID_video_subtitle:
1425 if( isNumberValue(value) )
1427 libvlc_video_set_spu(p_md, numberValue(value));
1429 return INVOKERESULT_NO_ERROR;
1431 return INVOKERESULT_INVALID_VALUE;
1435 char *psz_geometry = NULL;
1437 if( ! NPVARIANT_IS_STRING(value) )
1439 return INVOKERESULT_INVALID_VALUE;
1442 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1445 return INVOKERESULT_GENERIC_ERROR;
1448 libvlc_video_set_crop_geometry(p_md, psz_geometry);
1451 return INVOKERESULT_NO_ERROR;
1453 case ID_video_teletext:
1455 if( isNumberValue(value) )
1457 libvlc_video_set_teletext(p_md, numberValue(value));
1458 return INVOKERESULT_NO_ERROR;
1460 return INVOKERESULT_INVALID_VALUE;
1464 return INVOKERESULT_GENERIC_ERROR;
1467 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1472 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1474 enum LibvlcVideoNPObjectMethodIds
1476 ID_video_togglefullscreen,
1477 ID_video_toggleteletext,
1480 RuntimeNPObject::InvokeResult
1481 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1482 uint32_t argCount, NPVariant &result)
1484 /* is plugin still running */
1485 if( isPluginRunning() )
1487 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1488 libvlc_media_player_t *p_md = p_plugin->getMD();
1494 case ID_video_togglefullscreen:
1498 p_plugin->toggle_fullscreen();
1499 VOID_TO_NPVARIANT(result);
1500 return INVOKERESULT_NO_ERROR;
1502 return INVOKERESULT_NO_SUCH_METHOD;
1504 case ID_video_toggleteletext:
1508 libvlc_toggle_teletext(p_md);
1509 VOID_TO_NPVARIANT(result);
1510 return INVOKERESULT_NO_ERROR;
1512 return INVOKERESULT_NO_SUCH_METHOD;
1515 return INVOKERESULT_NO_SUCH_METHOD;
1518 return INVOKERESULT_GENERIC_ERROR;
1522 ** implementation of libvlc marquee object
1525 const NPUTF8 * const LibvlcMarqueeNPObject::propertyNames[] =
1538 enum LibvlcMarqueeNPObjectPropertyIds
1542 ID_marquee_position,
1551 COUNTNAMES(LibvlcMarqueeNPObject,propertyCount,propertyNames);
1553 static const unsigned char marquee_idx[] = {
1554 libvlc_marquee_Color,
1555 libvlc_marquee_Opacity,
1556 libvlc_marquee_Position,
1557 libvlc_marquee_Refresh,
1558 libvlc_marquee_Size,
1560 libvlc_marquee_Timeout,
1565 RuntimeNPObject::InvokeResult
1566 LibvlcMarqueeNPObject::getProperty(int index, NPVariant &result)
1570 if( !isPluginRunning() )
1571 return INVOKERESULT_GENERIC_ERROR;
1573 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1574 libvlc_media_player_t *p_md = p_plugin->getMD();
1580 case ID_marquee_color:
1581 case ID_marquee_opacity:
1582 case ID_marquee_refresh:
1583 case ID_marquee_timeout:
1584 case ID_marquee_size:
1588 libvlc_video_get_marquee_int(p_md, marquee_idx[index]),
1590 return INVOKERESULT_NO_ERROR;
1592 case ID_marquee_position:
1593 STRINGZ_TO_NPVARIANT( position_bynumber(
1594 libvlc_video_get_marquee_int(p_md, libvlc_marquee_Position) ),
1599 case ID_marquee_text:
1600 psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text);
1603 STRINGZ_TO_NPVARIANT(psz, result);
1604 return INVOKERESULT_NO_ERROR;
1608 return INVOKERESULT_GENERIC_ERROR;
1611 RuntimeNPObject::InvokeResult
1612 LibvlcMarqueeNPObject::setProperty(int index, const NPVariant &value)
1616 if( !isPluginRunning() )
1617 return INVOKERESULT_GENERIC_ERROR;
1619 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1620 libvlc_media_player_t *p_md = p_plugin->getMD();
1626 case ID_marquee_color:
1627 case ID_marquee_opacity:
1628 case ID_marquee_refresh:
1629 case ID_marquee_timeout:
1632 if( NPVARIANT_IS_INT32( value ) )
1634 libvlc_video_set_marquee_int(p_md, marquee_idx[index],
1635 NPVARIANT_TO_INT32( value ));
1636 return INVOKERESULT_NO_ERROR;
1640 case ID_marquee_position:
1641 if( !NPVARIANT_IS_STRING(value) ||
1642 !position_byname( NPVARIANT_TO_STRING(value).UTF8Characters, i ) )
1643 return INVOKERESULT_INVALID_VALUE;
1645 libvlc_video_set_marquee_int(p_md, libvlc_marquee_Position, i);
1646 return INVOKERESULT_NO_ERROR;
1648 case ID_marquee_text:
1649 if( NPVARIANT_IS_STRING( value ) )
1651 char *psz_text = stringValue( NPVARIANT_TO_STRING( value ) );
1652 libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
1655 return INVOKERESULT_NO_ERROR;
1659 return INVOKERESULT_NO_SUCH_METHOD;
1662 const NPUTF8 * const LibvlcMarqueeNPObject::methodNames[] =
1667 COUNTNAMES(LibvlcMarqueeNPObject,methodCount,methodNames);
1669 enum LibvlcMarqueeNPObjectMethodIds
1675 RuntimeNPObject::InvokeResult
1676 LibvlcMarqueeNPObject::invoke(int index, const NPVariant *args,
1677 uint32_t argCount, NPVariant &result)
1679 if( !isPluginRunning() )
1680 return INVOKERESULT_GENERIC_ERROR;
1682 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1683 libvlc_media_player_t *p_md = p_plugin->getMD();
1689 case ID_marquee_enable:
1690 case ID_marquee_disable:
1691 libvlc_video_set_marquee_int(p_md, libvlc_marquee_Enable,
1692 index!=ID_marquee_disable);
1693 VOID_TO_NPVARIANT(result);
1694 return INVOKERESULT_NO_ERROR;
1696 return INVOKERESULT_NO_SUCH_METHOD;
1699 const NPUTF8 * const LibvlcLogoNPObject::propertyNames[] = {
1707 enum LibvlcLogoNPObjectPropertyIds {
1715 COUNTNAMES(LibvlcLogoNPObject,propertyCount,propertyNames);
1716 static const unsigned char logo_idx[] = {
1719 libvlc_logo_opacity,
1725 RuntimeNPObject::InvokeResult
1726 LibvlcLogoNPObject::getProperty(int index, NPVariant &result)
1728 if( !isPluginRunning() )
1729 return INVOKERESULT_GENERIC_ERROR;
1731 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1732 libvlc_media_player_t *p_md = p_plugin->getMD();
1739 case ID_logo_repeat:
1740 case ID_logo_opacity:
1745 libvlc_video_get_logo_int(p_md, logo_idx[index]), result);
1748 case ID_logo_position:
1749 STRINGZ_TO_NPVARIANT( position_bynumber(
1750 libvlc_video_get_logo_int(p_md, libvlc_logo_position) ),
1754 return INVOKERESULT_GENERIC_ERROR;
1756 return INVOKERESULT_NO_ERROR;
1759 RuntimeNPObject::InvokeResult
1760 LibvlcLogoNPObject::setProperty(int index, const NPVariant &value)
1764 if( !isPluginRunning() )
1765 return INVOKERESULT_GENERIC_ERROR;
1767 VlcPlugin* p_plugin = getPrivate<VlcPlugin>();
1768 libvlc_media_player_t *p_md = p_plugin->getMD();
1775 case ID_logo_repeat:
1776 case ID_logo_opacity:
1779 if( !NPVARIANT_IS_INT32(value) )
1780 return INVOKERESULT_INVALID_VALUE;
1782 libvlc_video_set_logo_int(p_md, logo_idx[index],
1783 NPVARIANT_TO_INT32( value ));
1786 case ID_logo_position:
1787 if( !NPVARIANT_IS_STRING(value) ||
1788 !position_byname( NPVARIANT_TO_STRING(value).UTF8Characters, i ) )
1789 return INVOKERESULT_INVALID_VALUE;
1791 libvlc_video_set_logo_int(p_md, libvlc_logo_position, i);
1794 return INVOKERESULT_GENERIC_ERROR;
1796 return INVOKERESULT_NO_ERROR;
1800 const NPUTF8 * const LibvlcLogoNPObject::methodNames[] = {
1805 enum LibvlcLogoNPObjectMethodIds {
1810 COUNTNAMES(LibvlcLogoNPObject,methodCount,methodNames);
1812 RuntimeNPObject::InvokeResult
1813 LibvlcLogoNPObject::invoke(int index, const NPVariant *args,
1814 uint32_t argCount, NPVariant &result)
1819 if( !isPluginRunning() )
1820 return INVOKERESULT_GENERIC_ERROR;
1822 libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD();
1828 case ID_logo_enable:
1829 case ID_logo_disable:
1831 return INVOKERESULT_GENERIC_ERROR;
1833 libvlc_video_set_logo_int(p_md, libvlc_logo_enable,
1834 index != ID_logo_disable);
1835 VOID_TO_NPVARIANT(result);
1840 return INVOKERESULT_GENERIC_ERROR;
1842 for( len=0,i=0;i<argCount;++i )
1844 if( !NPVARIANT_IS_STRING(args[i]) )
1845 return INVOKERESULT_INVALID_VALUE;
1846 len+=NPVARIANT_TO_STRING(args[i]).UTF8Length+1;
1849 buf = (char *)malloc( len+1 );
1851 return INVOKERESULT_OUT_OF_MEMORY;
1853 for( h=buf,i=0;i<argCount;++i )
1856 len=NPVARIANT_TO_STRING(args[i]).UTF8Length;
1857 memcpy(h,NPVARIANT_TO_STRING(args[i]).UTF8Characters,len);
1862 libvlc_video_set_logo_string(p_md, libvlc_logo_file, buf);
1864 VOID_TO_NPVARIANT(result);
1867 return INVOKERESULT_NO_SUCH_METHOD;
1869 return INVOKERESULT_NO_ERROR;
1873 const NPUTF8 * const LibvlcDeinterlaceNPObject::propertyNames[] = {
1875 enum LibvlcDeinterlaceNPObjectPropertyIds {
1877 COUNTNAMES(LibvlcDeinterlaceNPObject,propertyCount,propertyNames);
1879 RuntimeNPObject::InvokeResult
1880 LibvlcDeinterlaceNPObject::getProperty(int index, NPVariant &result)
1882 return INVOKERESULT_GENERIC_ERROR;
1885 RuntimeNPObject::InvokeResult
1886 LibvlcDeinterlaceNPObject::setProperty(int index, const NPVariant &value)
1888 return INVOKERESULT_GENERIC_ERROR;
1892 const NPUTF8 * const LibvlcDeinterlaceNPObject::methodNames[] = {
1896 enum LibvlcDeinterlaceNPObjectMethodIds {
1900 COUNTNAMES(LibvlcDeinterlaceNPObject,methodCount,methodNames);
1902 RuntimeNPObject::InvokeResult
1903 LibvlcDeinterlaceNPObject::invoke(int index, const NPVariant *args,
1904 uint32_t argCount, NPVariant &result)
1908 if( !isPluginRunning() )
1909 return INVOKERESULT_GENERIC_ERROR;
1911 libvlc_media_player_t *p_md = getPrivate<VlcPlugin>()->getMD();
1917 case ID_deint_disable:
1918 libvlc_video_set_deinterlace(p_md, NULL);
1921 case ID_deint_enable:
1922 if( argCount != 1 || !NPVARIANT_IS_STRING( args[0] ) )
1923 return INVOKERESULT_INVALID_VALUE;
1925 psz = stringValue( NPVARIANT_TO_STRING( args[0] ) );
1926 libvlc_video_set_deinterlace(p_md, psz);
1931 return INVOKERESULT_NO_SUCH_METHOD;
1933 return INVOKERESULT_NO_ERROR;