]> git.sesse.net Git - vlc/blob - mozilla/control/npolibvlc.cpp
871c6d5f2c219f7edcca4b71a95f93fe26910c0f
[vlc] / mozilla / control / npolibvlc.cpp
1 /*****************************************************************************\r
2  * npolibvlc.cpp: official Javascript APIs\r
3  *****************************************************************************\r
4  * Copyright (C) 2002-2006 the VideoLAN team\r
5  *\r
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.\r
21  *****************************************************************************/\r
22 \r
23 #include "config.h"\r
24 \r
25 #include <stdio.h>\r
26 #include <string.h>\r
27 #include <stdlib.h>\r
28 \r
29 /* Mozilla stuff */\r
30 #ifdef HAVE_MOZILLA_CONFIG_H\r
31 #   include <mozilla-config.h>\r
32 #endif\r
33 \r
34 #include "npolibvlc.h"\r
35 #include "vlcplugin.h"\r
36 \r
37 /*\r
38 ** implementation of libvlc root object\r
39 */\r
40 \r
41 LibvlcRootNPObject::LibvlcRootNPObject(NPP instance, const NPClass *aClass) :\r
42         RuntimeNPObject(instance, aClass)\r
43 {\r
44     audioObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcAudioNPObject>::getClass());\r
45     inputObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcInputNPObject>::getClass());\r
46     playlistObj = NPN_CreateObject(instance, RuntimeNPClass<LibvlcPlaylistNPObject>::getClass());\r
47     videoObj = NPN_CreateObject(instance,RuntimeNPClass<LibvlcVideoNPObject>::getClass());\r
48 }\r
49 \r
50 LibvlcRootNPObject::~LibvlcRootNPObject()\r
51 {\r
52     NPN_ReleaseObject(audioObj);\r
53     NPN_ReleaseObject(inputObj);\r
54     NPN_ReleaseObject(playlistObj);\r
55     NPN_ReleaseObject(videoObj);\r
56 }\r
57 \r
58 const NPUTF8 * const LibvlcRootNPObject::propertyNames[] = \r
59 {\r
60     "audio",\r
61     "input",\r
62     "playlist",\r
63     "video",\r
64 };\r
65 \r
66 const int LibvlcRootNPObject::propertyCount = sizeof(LibvlcRootNPObject::propertyNames)/sizeof(NPUTF8 *);\r
67 \r
68 enum LibvlcRootNPObjectPropertyIds\r
69 {\r
70     ID_audio = 0,\r
71     ID_input,\r
72     ID_playlist,\r
73     ID_video,\r
74 };\r
75 \r
76 RuntimeNPObject::InvokeResult LibvlcRootNPObject::getProperty(int index, NPVariant &result)\r
77 {\r
78     switch( index )\r
79     {\r
80         case ID_audio:\r
81             OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result);\r
82             return INVOKERESULT_NO_ERROR;\r
83         case ID_input:\r
84             OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), result);\r
85             return INVOKERESULT_NO_ERROR;\r
86         case ID_playlist:\r
87             OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), result);\r
88             return INVOKERESULT_NO_ERROR;\r
89         case ID_video:\r
90             OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result);\r
91             return INVOKERESULT_NO_ERROR;\r
92     }\r
93     return INVOKERESULT_GENERIC_ERROR;\r
94 }\r
95 \r
96 const NPUTF8 * const LibvlcRootNPObject::methodNames[] =\r
97 {\r
98     /* no methods */\r
99 };\r
100 \r
101 const int LibvlcRootNPObject::methodCount = sizeof(LibvlcRootNPObject::methodNames)/sizeof(NPUTF8 *);\r
102 \r
103 /*\r
104 ** implementation of libvlc audio object\r
105 */\r
106 \r
107 const NPUTF8 * const LibvlcAudioNPObject::propertyNames[] = \r
108 {\r
109     "mute",\r
110     "volume",\r
111 };\r
112 \r
113 const int LibvlcAudioNPObject::propertyCount = sizeof(LibvlcAudioNPObject::propertyNames)/sizeof(NPUTF8 *);\r
114 \r
115 enum LibvlcAudioNPObjectPropertyIds\r
116 {\r
117     ID_mute,\r
118     ID_volume,\r
119 };\r
120 \r
121 RuntimeNPObject::InvokeResult LibvlcAudioNPObject::getProperty(int index, NPVariant &result)\r
122 {\r
123     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
124     if( p_plugin )\r
125     {\r
126         libvlc_exception_t ex;\r
127         libvlc_exception_init(&ex);\r
128 \r
129         switch( index )\r
130         {\r
131             case ID_mute:\r
132             {\r
133                 vlc_bool_t muted = libvlc_audio_get_mute(p_plugin->getVLC(), &ex);\r
134                 if( libvlc_exception_raised(&ex) )\r
135                 {\r
136                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
137                     libvlc_exception_clear(&ex);\r
138                     return INVOKERESULT_GENERIC_ERROR;\r
139                 }\r
140                 BOOLEAN_TO_NPVARIANT(muted, result);\r
141                 return INVOKERESULT_NO_ERROR;\r
142             }\r
143             case ID_volume:\r
144             {\r
145                 int volume = libvlc_audio_get_volume(p_plugin->getVLC(), &ex);\r
146                 if( libvlc_exception_raised(&ex) )\r
147                 {\r
148                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
149                     libvlc_exception_clear(&ex);\r
150                     return INVOKERESULT_GENERIC_ERROR;\r
151                 }\r
152                 INT32_TO_NPVARIANT(volume, result);\r
153                 return INVOKERESULT_NO_ERROR;\r
154             }\r
155         }\r
156     }\r
157     return INVOKERESULT_GENERIC_ERROR;\r
158 }\r
159 \r
160 RuntimeNPObject::InvokeResult LibvlcAudioNPObject::setProperty(int index, const NPVariant &value)\r
161 {\r
162     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
163     if( p_plugin )\r
164     {\r
165         libvlc_exception_t ex;\r
166         libvlc_exception_init(&ex);\r
167 \r
168         switch( index )\r
169         {\r
170             case ID_mute:\r
171                 if( NPVARIANT_IS_BOOLEAN(value) )\r
172                 {\r
173                     libvlc_audio_set_mute(p_plugin->getVLC(),\r
174                                           NPVARIANT_TO_BOOLEAN(value), &ex);\r
175                     if( libvlc_exception_raised(&ex) )\r
176                     {\r
177                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
178                         libvlc_exception_clear(&ex);\r
179                         return INVOKERESULT_GENERIC_ERROR;\r
180                     }\r
181                     return INVOKERESULT_NO_ERROR;\r
182                 }\r
183                 return INVOKERESULT_INVALID_VALUE;\r
184             case ID_volume:\r
185                 if( isNumberValue(value) )\r
186                 {\r
187                     libvlc_audio_set_volume(p_plugin->getVLC(),\r
188                                             numberValue(value), &ex);\r
189                     if( libvlc_exception_raised(&ex) )\r
190                     {\r
191                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
192                         libvlc_exception_clear(&ex);\r
193                         return INVOKERESULT_GENERIC_ERROR;\r
194                     }\r
195                     return INVOKERESULT_NO_ERROR;\r
196                 }\r
197                 return INVOKERESULT_INVALID_VALUE;\r
198         }\r
199     }\r
200     return INVOKERESULT_GENERIC_ERROR;\r
201 }\r
202 \r
203 const NPUTF8 * const LibvlcAudioNPObject::methodNames[] =\r
204 {\r
205     "togglemute",\r
206 };\r
207 \r
208 const int LibvlcAudioNPObject::methodCount = sizeof(LibvlcAudioNPObject::methodNames)/sizeof(NPUTF8 *);\r
209 \r
210 enum LibvlcAudioNPObjectMethodIds\r
211 {\r
212     ID_togglemute,\r
213 };\r
214 \r
215 RuntimeNPObject::InvokeResult LibvlcAudioNPObject::invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result)\r
216 {\r
217     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
218     if( p_plugin )\r
219     {\r
220         libvlc_exception_t ex;\r
221         libvlc_exception_init(&ex);\r
222 \r
223         switch( index )\r
224         {\r
225             case ID_togglemute:\r
226                 if( argCount == 0 )\r
227                 {\r
228                     libvlc_audio_toggle_mute(p_plugin->getVLC(), &ex);\r
229                     if( libvlc_exception_raised(&ex) )\r
230                     {\r
231                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
232                         libvlc_exception_clear(&ex);\r
233                         return INVOKERESULT_GENERIC_ERROR;\r
234                     }\r
235                     else\r
236                     {\r
237                         VOID_TO_NPVARIANT(result);\r
238                         return INVOKERESULT_NO_ERROR;\r
239                     }\r
240                 }\r
241                 return INVOKERESULT_NO_SUCH_METHOD;\r
242             default:\r
243                 return INVOKERESULT_NO_SUCH_METHOD;\r
244         }\r
245     }\r
246     return INVOKERESULT_GENERIC_ERROR;\r
247 }\r
248 \r
249 /*\r
250 ** implementation of libvlc input object\r
251 */\r
252 \r
253 const NPUTF8 * const LibvlcInputNPObject::propertyNames[] = \r
254 {\r
255     "length",\r
256     "position",\r
257     "time",\r
258     "fps",\r
259     "hasvout",\r
260 };\r
261 \r
262 const int LibvlcInputNPObject::propertyCount = sizeof(LibvlcInputNPObject::propertyNames)/sizeof(NPUTF8 *);\r
263 \r
264 enum LibvlcInputNPObjectPropertyIds\r
265 {\r
266     ID_length,\r
267     ID_position,\r
268     ID_time,\r
269     ID_fps,\r
270     ID_hasvout,\r
271 };\r
272 \r
273 RuntimeNPObject::InvokeResult LibvlcInputNPObject::getProperty(int index, NPVariant &result)\r
274 {\r
275     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
276     if( p_plugin )\r
277     {\r
278         libvlc_exception_t ex;\r
279         libvlc_exception_init(&ex);\r
280 \r
281         libvlc_input_t *p_input = libvlc_playlist_get_input(p_plugin->getVLC(), &ex);\r
282         if( libvlc_exception_raised(&ex) )\r
283         {\r
284             NPN_SetException(this, libvlc_exception_get_message(&ex));\r
285             libvlc_exception_clear(&ex);\r
286             return INVOKERESULT_GENERIC_ERROR;\r
287         }\r
288 \r
289         switch( index )\r
290         {\r
291             case ID_length:\r
292             {\r
293                 double val = (double)libvlc_input_get_length(p_input, &ex);\r
294                 libvlc_input_free(p_input);\r
295                 if( libvlc_exception_raised(&ex) )\r
296                 {\r
297                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
298                     libvlc_exception_clear(&ex);\r
299                     return INVOKERESULT_GENERIC_ERROR;\r
300                 }\r
301                 DOUBLE_TO_NPVARIANT(val, result);\r
302                 return INVOKERESULT_NO_ERROR;\r
303             }\r
304             case ID_position:\r
305             {\r
306                 double val = libvlc_input_get_position(p_input, &ex);\r
307                 libvlc_input_free(p_input);\r
308                 if( libvlc_exception_raised(&ex) )\r
309                 {\r
310                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
311                     libvlc_exception_clear(&ex);\r
312                     return INVOKERESULT_GENERIC_ERROR;\r
313                 }\r
314                 DOUBLE_TO_NPVARIANT(val, result);\r
315                 return INVOKERESULT_NO_ERROR;\r
316             }\r
317             case ID_time:\r
318             {\r
319                 double val = (double)libvlc_input_get_time(p_input, &ex);\r
320                 libvlc_input_free(p_input);\r
321                 if( libvlc_exception_raised(&ex) )\r
322                 {\r
323                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
324                     libvlc_exception_clear(&ex);\r
325                     return INVOKERESULT_GENERIC_ERROR;\r
326                 }\r
327                 DOUBLE_TO_NPVARIANT(val, result);\r
328                 return INVOKERESULT_NO_ERROR;\r
329             }\r
330             case ID_fps:\r
331             {\r
332                 double val = libvlc_input_get_fps(p_input, &ex);\r
333                 libvlc_input_free(p_input);\r
334                 if( libvlc_exception_raised(&ex) )\r
335                 {\r
336                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
337                     libvlc_exception_clear(&ex);\r
338                     return INVOKERESULT_GENERIC_ERROR;\r
339                 }\r
340                 DOUBLE_TO_NPVARIANT(val, result);\r
341                 return INVOKERESULT_NO_ERROR;\r
342             }\r
343             case ID_hasvout:\r
344             {\r
345                 vlc_bool_t val = libvlc_input_has_vout(p_input, &ex);\r
346                 libvlc_input_free(p_input);\r
347                 if( libvlc_exception_raised(&ex) )\r
348                 {\r
349                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
350                     libvlc_exception_clear(&ex);\r
351                     return INVOKERESULT_GENERIC_ERROR;\r
352                 }\r
353                 BOOLEAN_TO_NPVARIANT(val, result);\r
354                 return INVOKERESULT_NO_ERROR;\r
355             }\r
356         }\r
357         libvlc_input_free(p_input);\r
358     }\r
359     return INVOKERESULT_GENERIC_ERROR;\r
360 }\r
361 \r
362 RuntimeNPObject::InvokeResult LibvlcInputNPObject::setProperty(int index, const NPVariant &value)\r
363 {\r
364     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
365     if( p_plugin )\r
366     {\r
367         libvlc_exception_t ex;\r
368         libvlc_exception_init(&ex);\r
369 \r
370         libvlc_input_t *p_input = libvlc_playlist_get_input(p_plugin->getVLC(), &ex);\r
371         if( libvlc_exception_raised(&ex) )\r
372         {\r
373             NPN_SetException(this, libvlc_exception_get_message(&ex));\r
374             libvlc_exception_clear(&ex);\r
375             return INVOKERESULT_GENERIC_ERROR;\r
376         }\r
377 \r
378         switch( index )\r
379         {\r
380             case ID_position:\r
381             {\r
382                 if( ! NPVARIANT_IS_DOUBLE(value) )\r
383                 {\r
384                     libvlc_input_free(p_input);\r
385                     return INVOKERESULT_INVALID_VALUE;\r
386                 }\r
387 \r
388                 float val = (float)NPVARIANT_TO_DOUBLE(value);\r
389                 libvlc_input_set_position(p_input, val, &ex);\r
390                 libvlc_input_free(p_input);\r
391                 if( libvlc_exception_raised(&ex) )\r
392                 {\r
393                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
394                     libvlc_exception_clear(&ex);\r
395                     return INVOKERESULT_GENERIC_ERROR;\r
396                 }\r
397                 return INVOKERESULT_NO_ERROR;\r
398             }\r
399             case ID_time:\r
400             {\r
401                 vlc_int64_t val;\r
402                 if( NPVARIANT_IS_INT32(value) )\r
403                     val = (vlc_int64_t)NPVARIANT_TO_INT32(value);\r
404                 else if( NPVARIANT_IS_DOUBLE(value) )\r
405                     val = (vlc_int64_t)NPVARIANT_TO_DOUBLE(value);\r
406                 else\r
407                 {\r
408                     libvlc_input_free(p_input);\r
409                     return INVOKERESULT_INVALID_VALUE;\r
410                 }\r
411 \r
412                 libvlc_input_set_time(p_input, val, &ex);\r
413                 libvlc_input_free(p_input);\r
414                 if( libvlc_exception_raised(&ex) )\r
415                 {\r
416                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
417                     libvlc_exception_clear(&ex);\r
418                     return INVOKERESULT_GENERIC_ERROR;\r
419                 }\r
420                 return INVOKERESULT_NO_ERROR;\r
421             }\r
422         }\r
423         libvlc_input_free(p_input);\r
424     }\r
425     return INVOKERESULT_GENERIC_ERROR;\r
426 }\r
427 \r
428 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =\r
429 {\r
430     /* no methods */\r
431 };\r
432 \r
433 const int LibvlcInputNPObject::methodCount = sizeof(LibvlcInputNPObject::methodNames)/sizeof(NPUTF8 *);\r
434 \r
435 /*\r
436 ** implementation of libvlc playlist object\r
437 */\r
438 \r
439 \r
440 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] = \r
441 {\r
442     "itemscount",\r
443     "isplaying",\r
444 };\r
445 \r
446 const int LibvlcPlaylistNPObject::propertyCount = sizeof(LibvlcPlaylistNPObject::propertyNames)/sizeof(NPUTF8 *);\r
447 \r
448 enum LibvlcPlaylistNPObjectPropertyIds\r
449 {\r
450     ID_itemscount,\r
451     ID_isplaying,\r
452 };\r
453 \r
454 RuntimeNPObject::InvokeResult LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)\r
455 {\r
456     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
457     if( p_plugin )\r
458     {\r
459         libvlc_exception_t ex;\r
460         libvlc_exception_init(&ex);\r
461 \r
462         switch( index )\r
463         {\r
464             case ID_itemscount:\r
465             {\r
466                 int val = libvlc_playlist_items_count(p_plugin->getVLC(), &ex);\r
467                 if( libvlc_exception_raised(&ex) )\r
468                 {\r
469                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
470                     libvlc_exception_clear(&ex);\r
471                     return INVOKERESULT_GENERIC_ERROR;\r
472                 }\r
473                 INT32_TO_NPVARIANT(val, result);\r
474                 return INVOKERESULT_NO_ERROR;\r
475             }\r
476             case ID_isplaying:\r
477             {\r
478                 int val = libvlc_playlist_isplaying(p_plugin->getVLC(), &ex);\r
479                 if( libvlc_exception_raised(&ex) )\r
480                 {\r
481                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
482                     libvlc_exception_clear(&ex);\r
483                     return INVOKERESULT_GENERIC_ERROR;\r
484                 }\r
485                 BOOLEAN_TO_NPVARIANT(val, result);\r
486                 return INVOKERESULT_NO_ERROR;\r
487             }\r
488         }\r
489     }\r
490     return INVOKERESULT_GENERIC_ERROR;\r
491 }\r
492 \r
493 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =\r
494 {\r
495     "add",\r
496     "play",\r
497     "togglepause",\r
498     "stop",\r
499     "next",\r
500     "prev",\r
501     "clear",\r
502     "deleteitem"\r
503 };\r
504 \r
505 const int LibvlcPlaylistNPObject::methodCount = sizeof(LibvlcPlaylistNPObject::methodNames)/sizeof(NPUTF8 *);\r
506 \r
507 enum LibvlcPlaylistNPObjectMethodIds\r
508 {\r
509     ID_add,\r
510     ID_play,\r
511     ID_togglepause,\r
512     ID_stop,\r
513     ID_next,\r
514     ID_prev,\r
515     ID_clear,\r
516     ID_deleteitem,\r
517 };\r
518 \r
519 RuntimeNPObject::InvokeResult LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result)\r
520 {\r
521     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
522     if( p_plugin )\r
523     {\r
524         libvlc_exception_t ex;\r
525         libvlc_exception_init(&ex);\r
526 \r
527         switch( index )\r
528         {\r
529             case ID_add:\r
530             {\r
531                 if( (argCount < 1) || (argCount > 3) )\r
532                     return INVOKERESULT_NO_SUCH_METHOD;\r
533 \r
534                 char *url = NULL;\r
535 \r
536                 // grab URL\r
537                 if( NPVARIANT_IS_STRING(args[0]) )\r
538                 {\r
539                     char *s = stringValue(NPVARIANT_TO_STRING(args[0]));\r
540                     if( s )\r
541                     {\r
542                         url = p_plugin->getAbsoluteURL(s);\r
543                         delete s;\r
544                         if( ! url )\r
545                             // what happened ?\r
546                             return INVOKERESULT_GENERIC_ERROR;\r
547                     }\r
548                     else\r
549                         return INVOKERESULT_OUT_OF_MEMORY;\r
550                 }\r
551                 else\r
552                     return INVOKERESULT_NO_SUCH_METHOD;\r
553 \r
554                 char *name = NULL;\r
555 \r
556                 // grab name if available\r
557                 if( argCount > 1 )\r
558                 {\r
559                     if( NPVARIANT_IS_NULL(args[1]) )\r
560                     {\r
561                         // do nothing\r
562                     }\r
563                     else if( NPVARIANT_IS_STRING(args[1]) )\r
564                     {\r
565                         name = stringValue(NPVARIANT_TO_STRING(args[0]));\r
566                     }\r
567                     else\r
568                         return INVOKERESULT_NO_SUCH_METHOD;\r
569                 }\r
570 \r
571                 int i_options = 0;\r
572                 char** ppsz_options = NULL;\r
573 \r
574                 // grab options if available\r
575                 if( argCount > 2 )\r
576                 {\r
577                     if( NPVARIANT_IS_NULL(args[2]) )\r
578                     {\r
579                         // do nothing\r
580                     }\r
581                     else if( NPVARIANT_IS_STRING(args[2]) )\r
582                     {\r
583                         parseOptions(NPVARIANT_TO_STRING(args[2]), &i_options, &ppsz_options);\r
584 \r
585                     }\r
586                     else if( NPVARIANT_IS_OBJECT(args[2]) )\r
587                     {\r
588                         parseOptions(NPVARIANT_TO_OBJECT(args[2]), &i_options, &ppsz_options);\r
589                     }\r
590                 }\r
591 \r
592                 int item = libvlc_playlist_add_extended(p_plugin->getVLC(),\r
593                                                         url,\r
594                                                         name,\r
595                                                         i_options,\r
596                                                         const_cast<const char **>(ppsz_options),\r
597                                                         &ex);\r
598                 delete url;\r
599                 delete name;\r
600                 for( int i=0; i< i_options; ++i )\r
601                 {\r
602                     if( ppsz_options[i] )\r
603                         free(ppsz_options[i]);\r
604                 }\r
605                 if( ppsz_options )\r
606                     free(ppsz_options);\r
607                 if( libvlc_exception_raised(&ex) )\r
608                 {\r
609                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
610                     libvlc_exception_clear(&ex);\r
611                     return INVOKERESULT_GENERIC_ERROR;\r
612                 }\r
613                 else\r
614                 {\r
615                     INT32_TO_NPVARIANT(item, result);\r
616                     return INVOKERESULT_NO_ERROR;\r
617                 }\r
618             }\r
619             case ID_play:\r
620                 if( argCount == 0 )\r
621                 {\r
622                     libvlc_playlist_play(p_plugin->getVLC(), -1, 0, NULL, &ex);\r
623                     if( libvlc_exception_raised(&ex) )\r
624                     {\r
625                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
626                         libvlc_exception_clear(&ex);\r
627                         return INVOKERESULT_GENERIC_ERROR;\r
628                     }\r
629                     else\r
630                     {\r
631                         VOID_TO_NPVARIANT(result);\r
632                         return INVOKERESULT_NO_ERROR;\r
633                     }\r
634                 }\r
635                 return INVOKERESULT_NO_SUCH_METHOD;\r
636             case ID_togglepause:\r
637                 if( argCount == 0 )\r
638                 {\r
639                     libvlc_playlist_pause(p_plugin->getVLC(), &ex);\r
640                     if( libvlc_exception_raised(&ex) )\r
641                     {\r
642                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
643                         libvlc_exception_clear(&ex);\r
644                         return INVOKERESULT_GENERIC_ERROR;\r
645                     }\r
646                     else\r
647                     {\r
648                         VOID_TO_NPVARIANT(result);\r
649                         return INVOKERESULT_NO_ERROR;\r
650                     }\r
651                 }\r
652                 return INVOKERESULT_NO_SUCH_METHOD;\r
653             case ID_stop:\r
654                 if( argCount == 0 )\r
655                 {\r
656                     libvlc_playlist_stop(p_plugin->getVLC(), &ex);\r
657                     if( libvlc_exception_raised(&ex) )\r
658                     {\r
659                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
660                         libvlc_exception_clear(&ex);\r
661                         return INVOKERESULT_GENERIC_ERROR;\r
662                     }\r
663                     else\r
664                     {\r
665                         VOID_TO_NPVARIANT(result);\r
666                         return INVOKERESULT_NO_ERROR;\r
667                     }\r
668                 }\r
669                 return INVOKERESULT_NO_SUCH_METHOD;\r
670             case ID_next:\r
671                 if( argCount == 0 )\r
672                 {\r
673                     libvlc_playlist_next(p_plugin->getVLC(), &ex);\r
674                     if( libvlc_exception_raised(&ex) )\r
675                     {\r
676                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
677                         libvlc_exception_clear(&ex);\r
678                         return INVOKERESULT_GENERIC_ERROR;\r
679                     }\r
680                     else\r
681                     {\r
682                         VOID_TO_NPVARIANT(result);\r
683                         return INVOKERESULT_NO_ERROR;\r
684                     }\r
685                 }\r
686                 return INVOKERESULT_NO_SUCH_METHOD;\r
687             case ID_prev:\r
688                 if( argCount == 0 )\r
689                 {\r
690                     libvlc_playlist_prev(p_plugin->getVLC(), &ex);\r
691                     if( libvlc_exception_raised(&ex) )\r
692                     {\r
693                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
694                         libvlc_exception_clear(&ex);\r
695                         return INVOKERESULT_GENERIC_ERROR;\r
696                     }\r
697                     else\r
698                     {\r
699                         VOID_TO_NPVARIANT(result);\r
700                         return INVOKERESULT_NO_ERROR;\r
701                     }\r
702                 }\r
703                 return INVOKERESULT_NO_SUCH_METHOD;\r
704             case ID_clear:\r
705                 if( argCount == 0 )\r
706                 {\r
707                     libvlc_playlist_clear(p_plugin->getVLC(), &ex);\r
708                     if( libvlc_exception_raised(&ex) )\r
709                     {\r
710                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
711                         libvlc_exception_clear(&ex);\r
712                         return INVOKERESULT_GENERIC_ERROR;\r
713                     }\r
714                     else\r
715                     {\r
716                         VOID_TO_NPVARIANT(result);\r
717                         return INVOKERESULT_NO_ERROR;\r
718                     }\r
719                 }\r
720                 return INVOKERESULT_NO_SUCH_METHOD;\r
721             case ID_deleteitem:\r
722                 if( (argCount == 1) && isNumberValue(args[0]) )\r
723                 {\r
724                     libvlc_playlist_delete_item(p_plugin->getVLC(), numberValue(args[0]), &ex);\r
725                     if( libvlc_exception_raised(&ex) )\r
726                     {\r
727                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
728                         libvlc_exception_clear(&ex);\r
729                         return INVOKERESULT_GENERIC_ERROR;\r
730                     }\r
731                     else\r
732                     {\r
733                         VOID_TO_NPVARIANT(result);\r
734                         return INVOKERESULT_NO_ERROR;\r
735                     }\r
736                 }\r
737                 return INVOKERESULT_NO_SUCH_METHOD;\r
738             default:\r
739                 return INVOKERESULT_NO_SUCH_METHOD;\r
740         }\r
741     }\r
742     return INVOKERESULT_GENERIC_ERROR;\r
743 }\r
744  \r
745 void LibvlcPlaylistNPObject::parseOptions(const NPString &s, int *i_options, char*** ppsz_options)\r
746 {\r
747     if( s.utf8length )\r
748     {\r
749         char *val = stringValue(s);\r
750         if( val )\r
751         {\r
752             long capacity = 16;\r
753             char **options = (char **)malloc(capacity*sizeof(char *));\r
754             if( options )\r
755             {\r
756                 int nOptions = 0;\r
757 \r
758                 char *end = val + s.utf8length;\r
759                 while( val < end )\r
760                 {\r
761                     // skip leading blanks\r
762                     while( (val < end)\r
763                         && ((*val == ' ' ) || (*val == '\t')) )\r
764                         ++val;\r
765 \r
766                     char *start = val;\r
767                     // skip till we get a blank character\r
768                     while( (val < end)\r
769                         && (*val != ' ' )\r
770                         && (*val != '\t') )\r
771                     {\r
772                         char c = *(val++);\r
773                         if( ('\'' == c) || ('"' == c) )\r
774                         {\r
775                             // skip till end of string\r
776                             while( (val < end) && (*(val++) != c ) );\r
777                         }\r
778                     }\r
779 \r
780                     if( val > start )\r
781                     {\r
782                         if( nOptions == capacity )\r
783                         {\r
784                             capacity += 16;\r
785                             char **moreOptions = (char **)realloc(options, capacity*sizeof(char*)); \r
786                             if( ! moreOptions )\r
787                             {\r
788                                 /* failed to allocate more memory */\r
789                                 delete val;\r
790                                 /* return what we got so far */\r
791                                 *i_options = nOptions;\r
792                                 *ppsz_options = options;\r
793                                 break;\r
794                             }\r
795                             options = moreOptions;\r
796                         }\r
797                         *(val++) = '\0';\r
798                         options[nOptions++] = strdup(start);\r
799                     }\r
800                     else\r
801                         // must be end of string\r
802                         break;\r
803                 }\r
804                 *i_options = nOptions;\r
805                 *ppsz_options = options;\r
806             }\r
807             delete val;\r
808         }\r
809     }\r
810 }\r
811 \r
812 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options, char*** ppsz_options)\r
813 {\r
814     /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */\r
815 \r
816     NPVariant value;\r
817 \r
818     /* we are expecting to have a Javascript Array object */\r
819     NPIdentifier propId = NPN_GetStringIdentifier("length");\r
820     if( NPN_GetProperty(_instance, obj, propId, &value) )\r
821     {\r
822         int count = numberValue(value);\r
823         NPN_ReleaseVariantValue(&value);\r
824 \r
825         if( count )\r
826         {\r
827             long capacity = 16;\r
828             char **options = (char **)malloc(capacity*sizeof(char *));\r
829             if( options )\r
830             {\r
831                 int nOptions = 0;\r
832 \r
833                 while( nOptions < count )\r
834                 {\r
835                     propId = NPN_GetIntIdentifier(nOptions);\r
836                     if( ! NPN_GetProperty(_instance, obj, propId, &value) )\r
837                         /* return what we got so far */\r
838                         break;\r
839 \r
840                     if( ! NPVARIANT_IS_STRING(value) )\r
841                     {\r
842                         /* return what we got so far */\r
843                         NPN_ReleaseVariantValue(&value);\r
844                         break;\r
845                     }\r
846 \r
847                     if( nOptions == capacity )\r
848                     {\r
849                         capacity += 16;\r
850                         char **moreOptions = (char **)realloc(options, capacity*sizeof(char*)); \r
851                         if( ! moreOptions )\r
852                         {\r
853                             /* failed to allocate more memory */\r
854                             NPN_ReleaseVariantValue(&value);\r
855                             /* return what we got so far */\r
856                             *i_options = nOptions;\r
857                             *ppsz_options = options;\r
858                             break;\r
859                         }\r
860                         options = moreOptions;\r
861                     }\r
862 \r
863                     options[nOptions++] = stringValue(value);\r
864                 }\r
865                 *i_options = nOptions;\r
866                 *ppsz_options = options;\r
867             }\r
868         }\r
869     }\r
870 }\r
871 \r
872 /*\r
873 ** implementation of libvlc video object\r
874 */\r
875 \r
876 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] = \r
877 {\r
878     "fullscreen",\r
879     "height",\r
880     "width",\r
881 };\r
882 \r
883 enum LibvlcVideoNPObjectPropertyIds\r
884 {\r
885     ID_fullscreen,\r
886     ID_height,\r
887     ID_width,\r
888 };\r
889 \r
890 const int LibvlcVideoNPObject::propertyCount = sizeof(LibvlcVideoNPObject::propertyNames)/sizeof(NPUTF8 *);\r
891 \r
892 RuntimeNPObject::InvokeResult LibvlcVideoNPObject::getProperty(int index, NPVariant &result)\r
893 {\r
894     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
895     if( p_plugin )\r
896     {\r
897         libvlc_exception_t ex;\r
898         libvlc_exception_init(&ex);\r
899 \r
900         libvlc_input_t *p_input = libvlc_playlist_get_input(p_plugin->getVLC(), &ex);\r
901         if( libvlc_exception_raised(&ex) )\r
902         {\r
903             NPN_SetException(this, libvlc_exception_get_message(&ex));\r
904             libvlc_exception_clear(&ex);\r
905             return INVOKERESULT_GENERIC_ERROR;\r
906         }\r
907 \r
908         switch( index )\r
909         {\r
910             case ID_fullscreen:\r
911             {\r
912                 int val = libvlc_get_fullscreen(p_input, &ex);\r
913                 libvlc_input_free(p_input);\r
914                 if( libvlc_exception_raised(&ex) )\r
915                 {\r
916                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
917                     libvlc_exception_clear(&ex);\r
918                     return INVOKERESULT_GENERIC_ERROR;\r
919                 }\r
920                 BOOLEAN_TO_NPVARIANT(val, result);\r
921                 return INVOKERESULT_NO_ERROR;\r
922             }\r
923             case ID_height:\r
924             {\r
925                 int val = libvlc_video_get_height(p_input, &ex);\r
926                 libvlc_input_free(p_input);\r
927                 if( libvlc_exception_raised(&ex) )\r
928                 {\r
929                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
930                     libvlc_exception_clear(&ex);\r
931                     return INVOKERESULT_GENERIC_ERROR;\r
932                 }\r
933                 INT32_TO_NPVARIANT(val, result);\r
934                 return INVOKERESULT_NO_ERROR;\r
935             }\r
936             case ID_width:\r
937             {\r
938                 int val = libvlc_video_get_width(p_input, &ex);\r
939                 libvlc_input_free(p_input);\r
940                 if( libvlc_exception_raised(&ex) )\r
941                 {\r
942                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
943                     libvlc_exception_clear(&ex);\r
944                     return INVOKERESULT_GENERIC_ERROR;\r
945                 }\r
946                 INT32_TO_NPVARIANT(val, result);\r
947                 return INVOKERESULT_NO_ERROR;\r
948             }\r
949         }\r
950         libvlc_input_free(p_input);\r
951     }\r
952     return INVOKERESULT_GENERIC_ERROR;\r
953 }\r
954 \r
955 RuntimeNPObject::InvokeResult LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)\r
956 {\r
957     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
958     if( p_plugin )\r
959     {\r
960         libvlc_exception_t ex;\r
961         libvlc_exception_init(&ex);\r
962 \r
963         libvlc_input_t *p_input = libvlc_playlist_get_input(p_plugin->getVLC(), &ex);\r
964         if( libvlc_exception_raised(&ex) )\r
965         {\r
966             NPN_SetException(this, libvlc_exception_get_message(&ex));\r
967             libvlc_exception_clear(&ex);\r
968             return INVOKERESULT_GENERIC_ERROR;\r
969         }\r
970 \r
971         switch( index )\r
972         {\r
973             case ID_fullscreen:\r
974             {\r
975                 if( ! NPVARIANT_IS_BOOLEAN(value) )\r
976                 {\r
977                     libvlc_input_free(p_input);\r
978                     return INVOKERESULT_INVALID_VALUE;\r
979                 }\r
980 \r
981                 int val = NPVARIANT_TO_BOOLEAN(value);\r
982                 libvlc_set_fullscreen(p_input, val, &ex);\r
983                 libvlc_input_free(p_input);\r
984                 if( libvlc_exception_raised(&ex) )\r
985                 {\r
986                     NPN_SetException(this, libvlc_exception_get_message(&ex));\r
987                     libvlc_exception_clear(&ex);\r
988                     return INVOKERESULT_GENERIC_ERROR;\r
989                 }\r
990                 return INVOKERESULT_NO_ERROR;\r
991             }\r
992         }\r
993         libvlc_input_free(p_input);\r
994     }\r
995     return INVOKERESULT_GENERIC_ERROR;\r
996 }\r
997 \r
998 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =\r
999 {\r
1000     "togglefullscreen",\r
1001 };\r
1002 \r
1003 enum LibvlcVideoNPObjectMethodIds\r
1004 {\r
1005     ID_togglefullscreen,\r
1006 };\r
1007 \r
1008 const int LibvlcVideoNPObject::methodCount = sizeof(LibvlcVideoNPObject::methodNames)/sizeof(NPUTF8 *);\r
1009 \r
1010 RuntimeNPObject::InvokeResult LibvlcVideoNPObject::invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result)\r
1011 {\r
1012     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);\r
1013     if( p_plugin )\r
1014     {\r
1015         libvlc_exception_t ex;\r
1016         libvlc_exception_init(&ex);\r
1017 \r
1018         libvlc_input_t *p_input = libvlc_playlist_get_input(p_plugin->getVLC(), &ex);\r
1019         if( libvlc_exception_raised(&ex) )\r
1020         {\r
1021             NPN_SetException(this, libvlc_exception_get_message(&ex));\r
1022             libvlc_exception_clear(&ex);\r
1023             return INVOKERESULT_GENERIC_ERROR;\r
1024         }\r
1025 \r
1026         switch( index )\r
1027         {\r
1028             case ID_togglefullscreen:\r
1029                 if( argCount == 0 )\r
1030                 {\r
1031                     libvlc_toggle_fullscreen(p_input, &ex);\r
1032                     libvlc_input_free(p_input);\r
1033                     if( libvlc_exception_raised(&ex) )\r
1034                     {\r
1035                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
1036                         libvlc_exception_clear(&ex);\r
1037                         return INVOKERESULT_GENERIC_ERROR;\r
1038                     }\r
1039                     else\r
1040                     {\r
1041                         VOID_TO_NPVARIANT(result);\r
1042                         return INVOKERESULT_NO_ERROR;\r
1043                     }\r
1044                 }\r
1045                 else\r
1046                 {\r
1047                     /* cannot get input, probably not playing */\r
1048                     if( libvlc_exception_raised(&ex) )\r
1049                     {\r
1050                         NPN_SetException(this, libvlc_exception_get_message(&ex));\r
1051                         libvlc_exception_clear(&ex);\r
1052                     }\r
1053                     return INVOKERESULT_GENERIC_ERROR;\r
1054                 }\r
1055                 return INVOKERESULT_NO_SUCH_METHOD;\r
1056             default:\r
1057                 return INVOKERESULT_NO_SUCH_METHOD;\r
1058         }\r
1059     }\r
1060     return INVOKERESULT_GENERIC_ERROR;\r
1061 }\r
1062 \r