]> git.sesse.net Git - vlc/blob - projects/mozilla/control/npolibvlc.cpp
Make both parameters of RETURN_ON_EXCEPTION explicit.
[vlc] / projects / mozilla / control / npolibvlc.cpp
1 /*****************************************************************************
2  * npolibvlc.cpp: official Javascript APIs
3  *****************************************************************************
4  * Copyright (C) 2002-2006 the VideoLAN team
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 /* Mozilla stuff */
30 #ifdef HAVE_MOZILLA_CONFIG_H
31 #   include <mozilla-config.h>
32 #endif
33
34 #include "vlcplugin.h"
35 #include "npolibvlc.h"
36
37 /*
38 ** Local helper macros and function
39 */
40 #define COUNTNAMES(a,b,c) const int a::b = sizeof(a::c)/sizeof(NPUTF8 *)
41 #define RETURN_ON_EXCEPTION(this,ex) \
42     do { if( libvlc_exception_raised(&ex) ) \
43     { \
44         NPN_SetException(this, libvlc_exception_get_message(&ex)); \
45         libvlc_exception_clear(&ex); \
46         return INVOKERESULT_GENERIC_ERROR; \
47     } } while(false)
48
49 /*
50 ** implementation of libvlc root object
51 */
52
53 LibvlcRootNPObject::~LibvlcRootNPObject()
54 {
55     /*
56     ** When the plugin is destroyed, firefox takes it upon itself to
57     ** destroy all 'live' script objects and ignores refcounting.
58     ** Therefore we cannot safely assume that refcounting will control
59     ** lifespan of objects. Hence they are only lazily created on
60     ** request, so that firefox can take ownership, and are not released
61     ** when the plugin is destroyed.
62     */
63     if( isValid() )
64     {
65         if( audioObj    ) NPN_ReleaseObject(audioObj);
66         if( inputObj    ) NPN_ReleaseObject(inputObj);
67         if( logObj      ) NPN_ReleaseObject(logObj);
68         if( playlistObj ) NPN_ReleaseObject(playlistObj);
69         if( videoObj    ) NPN_ReleaseObject(videoObj);
70     }
71 }
72
73 const NPUTF8 * const LibvlcRootNPObject::propertyNames[] = 
74 {
75     "audio",
76     "input",
77     "log",
78     "playlist",
79     "video",
80     "VersionInfo",
81 };
82 COUNTNAMES(LibvlcRootNPObject,propertyCount,propertyNames);
83
84 enum LibvlcRootNPObjectPropertyIds
85 {
86     ID_root_audio = 0,
87     ID_root_input,
88     ID_root_log,
89     ID_root_playlist,
90     ID_root_video,
91     ID_root_VersionInfo,
92 };
93
94 RuntimeNPObject::InvokeResult
95 LibvlcRootNPObject::getProperty(int index, NPVariant &result)
96 {
97     /* is plugin still running */
98     if( _instance->pdata )
99     {
100         switch( index )
101         {
102             case ID_root_audio:
103                 // create child object in lazyman fashion to avoid
104                 // ownership problem with firefox
105                 if( ! audioObj )
106                     audioObj = NPN_CreateObject(_instance,
107                              RuntimeNPClass<LibvlcAudioNPObject>::getClass());
108                 OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), result);
109                 return INVOKERESULT_NO_ERROR;
110             case ID_root_input:
111                 // create child object in lazyman fashion to avoid
112                 // ownership problem with firefox
113                 if( ! inputObj )
114                     inputObj = NPN_CreateObject(_instance,
115                              RuntimeNPClass<LibvlcInputNPObject>::getClass());
116                 OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), result);
117                 return INVOKERESULT_NO_ERROR;
118             case ID_root_log:
119                 // create child object in lazyman fashion to avoid
120                 // ownership problem with firefox
121                 if( ! logObj )
122                     logObj = NPN_CreateObject(_instance,
123                                RuntimeNPClass<LibvlcLogNPObject>::getClass());
124                 OBJECT_TO_NPVARIANT(NPN_RetainObject(logObj), result);
125                 return INVOKERESULT_NO_ERROR;
126             case ID_root_playlist:
127                 // create child object in lazyman fashion to avoid
128                 // ownership problem with firefox
129                 if( ! playlistObj )
130                     playlistObj = NPN_CreateObject(_instance,
131                           RuntimeNPClass<LibvlcPlaylistNPObject>::getClass());
132                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), result);
133                 return INVOKERESULT_NO_ERROR;
134             case ID_root_video:
135                 // create child object in lazyman fashion to avoid
136                 // ownership problem with firefox
137                 if( ! videoObj )
138                     videoObj = NPN_CreateObject(_instance,
139                              RuntimeNPClass<LibvlcVideoNPObject>::getClass());
140                 OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), result);
141                 return INVOKERESULT_NO_ERROR;
142             case ID_root_VersionInfo:
143             {
144                 int len = strlen(libvlc_get_version());
145                 NPUTF8 *retval =(NPUTF8*)NPN_MemAlloc(len);
146                 if( retval )
147                 {
148                     memcpy(retval, libvlc_get_version(), len);
149                     STRINGN_TO_NPVARIANT(retval, len, result);
150                 }
151                 else
152                 {
153                     NULL_TO_NPVARIANT(result);
154                 }
155                 return INVOKERESULT_NO_ERROR;
156             }
157             default:
158                 ;
159         }
160     }
161     return INVOKERESULT_GENERIC_ERROR;
162 }
163
164 const NPUTF8 * const LibvlcRootNPObject::methodNames[] =
165 {
166     "versionInfo",
167 };
168 COUNTNAMES(LibvlcRootNPObject,methodCount,methodNames);
169
170 enum LibvlcRootNPObjectMethodIds
171 {
172     ID_root_versionInfo,
173 };
174
175 RuntimeNPObject::InvokeResult LibvlcRootNPObject::invoke(int index,
176                   const NPVariant *args, uint32_t argCount, NPVariant &result)
177 {
178     /* is plugin still running */
179     if( _instance->pdata )
180     {
181         libvlc_exception_t ex;
182         libvlc_exception_init(&ex);
183
184         switch( index )
185         {
186             case ID_root_versionInfo:
187                 if( argCount == 0 )
188                 {
189                     int len = strlen(libvlc_get_version());
190                     NPUTF8 *retval =(NPUTF8*)NPN_MemAlloc(len);
191                     if( retval )
192                     {
193                         memcpy(retval, libvlc_get_version(), len);
194                         STRINGN_TO_NPVARIANT(retval, len, result);
195                     }
196                     else
197                     {
198                         NULL_TO_NPVARIANT(result);
199                     }
200                     return INVOKERESULT_NO_ERROR;
201                 }
202                 return INVOKERESULT_NO_SUCH_METHOD;
203             default:
204                 ;
205         }
206     }
207     return INVOKERESULT_GENERIC_ERROR;
208 }
209
210 /*
211 ** implementation of libvlc audio object
212 */
213
214 const NPUTF8 * const LibvlcAudioNPObject::propertyNames[] = 
215 {
216     "mute",
217     "volume",
218     "track",
219     "channel",
220 };
221 COUNTNAMES(LibvlcAudioNPObject,propertyCount,propertyNames);
222
223 enum LibvlcAudioNPObjectPropertyIds
224 {
225     ID_audio_mute,
226     ID_audio_volume,
227     ID_audio_track,
228     ID_audio_channel,
229 };
230
231 RuntimeNPObject::InvokeResult
232 LibvlcAudioNPObject::getProperty(int index, NPVariant &result)
233 {
234     /* is plugin still running */
235     if( _instance->pdata )
236     {
237         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
238         libvlc_exception_t ex;
239         libvlc_exception_init(&ex);
240
241         switch( index )
242         {
243             case ID_audio_mute:
244             {
245                 bool muted = libvlc_audio_get_mute(p_plugin->getVLC(), &ex);
246                 RETURN_ON_EXCEPTION(this,ex);
247                 BOOLEAN_TO_NPVARIANT(muted, result);
248                 return INVOKERESULT_NO_ERROR;
249             }
250             case ID_audio_volume:
251             {
252                 int volume = libvlc_audio_get_volume(p_plugin->getVLC(), &ex);
253                 RETURN_ON_EXCEPTION(this,ex);
254                 INT32_TO_NPVARIANT(volume, result);
255                 return INVOKERESULT_NO_ERROR;
256             }
257             case ID_audio_track:
258             {
259                 libvlc_media_player_t *p_md =
260                     libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
261                 RETURN_ON_EXCEPTION(this,ex);
262                 int track = libvlc_audio_get_track(p_md, &ex);
263                 libvlc_media_player_release(p_md);
264                 RETURN_ON_EXCEPTION(this,ex);
265                 INT32_TO_NPVARIANT(track, result);
266                 return INVOKERESULT_NO_ERROR;
267             }
268             case ID_audio_channel:
269             {
270                 int channel = libvlc_audio_get_channel(p_plugin->getVLC(), &ex);
271                 RETURN_ON_EXCEPTION(this,ex);
272                 INT32_TO_NPVARIANT(channel, result);
273                 return INVOKERESULT_NO_ERROR;
274             }
275             default:
276                 ;
277         }
278     }
279     return INVOKERESULT_GENERIC_ERROR;
280 }
281
282 RuntimeNPObject::InvokeResult
283 LibvlcAudioNPObject::setProperty(int index, const NPVariant &value)
284 {
285     /* is plugin still running */
286     if( _instance->pdata )
287     {
288         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
289         libvlc_exception_t ex;
290         libvlc_exception_init(&ex);
291
292         switch( index )
293         {
294             case ID_audio_mute:
295                 if( NPVARIANT_IS_BOOLEAN(value) )
296                 {
297                     libvlc_audio_set_mute(p_plugin->getVLC(),
298                                           NPVARIANT_TO_BOOLEAN(value), &ex);
299                     RETURN_ON_EXCEPTION(this,ex);
300                     return INVOKERESULT_NO_ERROR;
301                 }
302                 return INVOKERESULT_INVALID_VALUE;
303             case ID_audio_volume:
304                 if( isNumberValue(value) )
305                 {
306                     libvlc_audio_set_volume(p_plugin->getVLC(),
307                                             numberValue(value), &ex);
308                     RETURN_ON_EXCEPTION(this,ex);
309                     return INVOKERESULT_NO_ERROR;
310                 }
311                 return INVOKERESULT_INVALID_VALUE;
312             case ID_audio_track:
313                 if( isNumberValue(value) )
314                 {
315                     libvlc_media_player_t *p_md =
316                       libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
317                     RETURN_ON_EXCEPTION(this,ex);
318                     libvlc_audio_set_track(p_md,
319                                            numberValue(value), &ex);
320                     libvlc_media_player_release(p_md);
321                     RETURN_ON_EXCEPTION(this,ex);
322                     return INVOKERESULT_NO_ERROR;
323                 }
324                 return INVOKERESULT_INVALID_VALUE;
325             case ID_audio_channel:
326                 if( isNumberValue(value) )
327                 {
328                     libvlc_audio_set_channel(p_plugin->getVLC(),
329                                              numberValue(value), &ex);
330                     RETURN_ON_EXCEPTION(this,ex);
331                     return INVOKERESULT_NO_ERROR;
332                 }
333                 return INVOKERESULT_INVALID_VALUE;
334             default:
335                 ;
336         }
337     }
338     return INVOKERESULT_GENERIC_ERROR;
339 }
340
341 const NPUTF8 * const LibvlcAudioNPObject::methodNames[] =
342 {
343     "toggleMute",
344 };
345 COUNTNAMES(LibvlcAudioNPObject,methodCount,methodNames);
346
347 enum LibvlcAudioNPObjectMethodIds
348 {
349     ID_audio_togglemute,
350 };
351
352 RuntimeNPObject::InvokeResult
353 LibvlcAudioNPObject::invoke(int index, const NPVariant *args,
354                             uint32_t argCount, NPVariant &result)
355 {
356     /* is plugin still running */
357     if( _instance->pdata )
358     {
359         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
360         libvlc_exception_t ex;
361         libvlc_exception_init(&ex);
362
363         switch( index )
364         {
365             case ID_audio_togglemute:
366                 if( argCount == 0 )
367                 {
368                     libvlc_audio_toggle_mute(p_plugin->getVLC(), &ex);
369                     RETURN_ON_EXCEPTION(this,ex);
370                     VOID_TO_NPVARIANT(result);
371                     return INVOKERESULT_NO_ERROR;
372                 }
373                 return INVOKERESULT_NO_SUCH_METHOD;
374             default:
375                 ;
376         }
377     }
378     return INVOKERESULT_GENERIC_ERROR;
379 }
380
381 /*
382 ** implementation of libvlc input object
383 */
384
385 const NPUTF8 * const LibvlcInputNPObject::propertyNames[] = 
386 {
387     "length",
388     "position",
389     "time",
390     "state",
391     "rate",
392     "fps",
393     "hasVout",
394 };
395 COUNTNAMES(LibvlcInputNPObject,propertyCount,propertyNames);
396
397 enum LibvlcInputNPObjectPropertyIds
398 {
399     ID_input_length,
400     ID_input_position,
401     ID_input_time,
402     ID_input_state,
403     ID_input_rate,
404     ID_input_fps,
405     ID_input_hasvout,
406 };
407
408 RuntimeNPObject::InvokeResult
409 LibvlcInputNPObject::getProperty(int index, NPVariant &result)
410 {
411     /* is plugin still running */
412     if( _instance->pdata )
413     {
414         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
415         libvlc_exception_t ex;
416         libvlc_exception_init(&ex);
417
418         libvlc_media_player_t *p_md =
419                     libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
420         if( libvlc_exception_raised(&ex) )
421         {
422             if( index != ID_input_state )
423             {
424                 NPN_SetException(this, libvlc_exception_get_message(&ex));
425                 libvlc_exception_clear(&ex);
426                 return INVOKERESULT_GENERIC_ERROR;
427             }
428             else
429             {
430                 /* for input state, return CLOSED rather than an exception */
431                 INT32_TO_NPVARIANT(0, result);
432                 libvlc_exception_clear(&ex);
433                 return INVOKERESULT_NO_ERROR;
434             }
435         }
436
437         switch( index )
438         {
439             case ID_input_length:
440             {
441                 double val = (double)libvlc_media_player_get_length(p_md, &ex);
442                 libvlc_media_player_release(p_md);
443                 RETURN_ON_EXCEPTION(this,ex);
444                 DOUBLE_TO_NPVARIANT(val, result);
445                 return INVOKERESULT_NO_ERROR;
446             }
447             case ID_input_position:
448             {
449                 double val = libvlc_media_player_get_position(p_md, &ex);
450                 libvlc_media_player_release(p_md);
451                 RETURN_ON_EXCEPTION(this,ex);
452                 DOUBLE_TO_NPVARIANT(val, result);
453                 return INVOKERESULT_NO_ERROR;
454             }
455             case ID_input_time:
456             {
457                 double val = (double)libvlc_media_player_get_time(p_md, &ex);
458                 libvlc_media_player_release(p_md);
459                 RETURN_ON_EXCEPTION(this,ex);
460                 DOUBLE_TO_NPVARIANT(val, result);
461                 return INVOKERESULT_NO_ERROR;
462             }
463             case ID_input_state:
464             {
465                 int val = libvlc_media_player_get_state(p_md, &ex);
466                 libvlc_media_player_release(p_md);
467                 RETURN_ON_EXCEPTION(this,ex);
468                 INT32_TO_NPVARIANT(val, result);
469                 return INVOKERESULT_NO_ERROR;
470             }
471             case ID_input_rate:
472             {
473                 float val = libvlc_media_player_get_rate(p_md, &ex);
474                 libvlc_media_player_release(p_md);
475                 RETURN_ON_EXCEPTION(this,ex);
476                 DOUBLE_TO_NPVARIANT(val, result);
477                 return INVOKERESULT_NO_ERROR;
478             }
479             case ID_input_fps:
480             {
481                 double val = libvlc_media_player_get_fps(p_md, &ex);
482                 libvlc_media_player_release(p_md);
483                 RETURN_ON_EXCEPTION(this,ex);
484                 DOUBLE_TO_NPVARIANT(val, result);
485                 return INVOKERESULT_NO_ERROR;
486             }
487             case ID_input_hasvout:
488             {
489                 bool val = libvlc_media_player_has_vout(p_md, &ex);
490                 libvlc_media_player_release(p_md);
491                 RETURN_ON_EXCEPTION(this,ex);
492                 BOOLEAN_TO_NPVARIANT(val, result);
493                 return INVOKERESULT_NO_ERROR;
494             }
495             default:
496                 ;
497         }
498         libvlc_media_player_release(p_md);
499     }
500     return INVOKERESULT_GENERIC_ERROR;
501 }
502
503 RuntimeNPObject::InvokeResult
504 LibvlcInputNPObject::setProperty(int index, const NPVariant &value)
505 {
506     /* is plugin still running */
507     if( _instance->pdata )
508     {
509         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
510         libvlc_exception_t ex;
511         libvlc_exception_init(&ex);
512
513         libvlc_media_player_t *p_md =
514                     libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
515         RETURN_ON_EXCEPTION(this,ex);
516
517         switch( index )
518         {
519             case ID_input_position:
520             {
521                 if( ! NPVARIANT_IS_DOUBLE(value) )
522                 {
523                     libvlc_media_player_release(p_md);
524                     return INVOKERESULT_INVALID_VALUE;
525                 }
526
527                 float val = (float)NPVARIANT_TO_DOUBLE(value);
528                 libvlc_media_player_set_position(p_md, val, &ex);
529                 libvlc_media_player_release(p_md);
530                 RETURN_ON_EXCEPTION(this,ex);
531                 return INVOKERESULT_NO_ERROR;
532             }
533             case ID_input_time:
534             {
535                 int64_t val;
536                 if( NPVARIANT_IS_INT32(value) )
537                     val = (int64_t)NPVARIANT_TO_INT32(value);
538                 else if( NPVARIANT_IS_DOUBLE(value) )
539                     val = (int64_t)NPVARIANT_TO_DOUBLE(value);
540                 else
541                 {
542                     libvlc_media_player_release(p_md);
543                     return INVOKERESULT_INVALID_VALUE;
544                 }
545
546                 libvlc_media_player_set_time(p_md, val, &ex);
547                 libvlc_media_player_release(p_md);
548                 RETURN_ON_EXCEPTION(this,ex);
549                 return INVOKERESULT_NO_ERROR;
550             }
551             case ID_input_rate:
552             {
553                 float val;
554                 if( NPVARIANT_IS_INT32(value) )
555                     val = (float)NPVARIANT_TO_INT32(value);
556                 else if( NPVARIANT_IS_DOUBLE(value) )
557                     val = (float)NPVARIANT_TO_DOUBLE(value);
558                 else
559                 {
560                     libvlc_media_player_release(p_md);
561                     return INVOKERESULT_INVALID_VALUE;
562                 }
563
564                 libvlc_media_player_set_rate(p_md, val, &ex);
565                 libvlc_media_player_release(p_md);
566                 RETURN_ON_EXCEPTION(this,ex);
567                 return INVOKERESULT_NO_ERROR;
568             }
569             default:
570                 ;
571         }
572         libvlc_media_player_release(p_md);
573     }
574     return INVOKERESULT_GENERIC_ERROR;
575 }
576
577 const NPUTF8 * const LibvlcInputNPObject::methodNames[] =
578 {
579     /* no methods */
580 };
581
582 COUNTNAMES(LibvlcInputNPObject,methodCount,methodNames);
583
584 /*
585 ** implementation of libvlc message object
586 */
587
588 const NPUTF8 * const LibvlcMessageNPObject::propertyNames[] = 
589 {
590     "severity",
591     "type",
592     "name",
593     "header",
594     "message",
595 };
596 COUNTNAMES(LibvlcMessageNPObject,propertyCount,propertyNames);
597
598 enum LibvlcMessageNPObjectPropertyIds
599 {
600     ID_message_severity,
601     ID_message_type,
602     ID_message_name,
603     ID_message_header,
604     ID_message_message,
605 };
606
607 RuntimeNPObject::InvokeResult
608 LibvlcMessageNPObject::getProperty(int index, NPVariant &result)
609 {
610     /* is plugin still running */
611     if( _instance->pdata )
612     {
613         switch( index )
614         {
615             case ID_message_severity:
616             {
617                 INT32_TO_NPVARIANT(_msg.i_severity, result);
618                 return INVOKERESULT_NO_ERROR;
619             }
620             case ID_message_type:
621             {
622                 if( _msg.psz_type )
623                 {
624                     int len = strlen(_msg.psz_type);
625                     NPUTF8* retval = (NPUTF8*)NPN_MemAlloc(len);
626                     if( retval )
627                     {
628                         memcpy(retval, _msg.psz_type, len);
629                         STRINGN_TO_NPVARIANT(retval, len, result);
630                     }
631                 }
632                 else
633                 {
634                     NULL_TO_NPVARIANT(result);
635                 }
636                 return INVOKERESULT_NO_ERROR;
637             }
638             case ID_message_name:
639             {
640                 if( _msg.psz_name )
641                 {
642                     int len = strlen(_msg.psz_name);
643                     NPUTF8* retval = (NPUTF8*)NPN_MemAlloc(len);
644                     if( retval )
645                     {
646                         memcpy(retval, _msg.psz_name, len);
647                         STRINGN_TO_NPVARIANT(retval, len, result);
648                     }
649                 }
650                 else
651                 {
652                     NULL_TO_NPVARIANT(result);
653                 }
654                 return INVOKERESULT_NO_ERROR;
655             }
656             case ID_message_header:
657             {
658                 if( _msg.psz_header )
659                 {
660                     int len = strlen(_msg.psz_header);
661                     NPUTF8* retval = (NPUTF8*)NPN_MemAlloc(len);
662                     if( retval )
663                     {
664                         memcpy(retval, _msg.psz_header, len);
665                         STRINGN_TO_NPVARIANT(retval, len, result);
666                     }
667                 }
668                 else
669                 {
670                     NULL_TO_NPVARIANT(result);
671                 }
672                 return INVOKERESULT_NO_ERROR;
673             }
674             case ID_message_message:
675             {
676                 if( _msg.psz_message )
677                 {
678                     int len = strlen(_msg.psz_message);
679                     NPUTF8* retval = (NPUTF8*)NPN_MemAlloc(len);
680                     if( retval )
681                     {
682                         memcpy(retval, _msg.psz_message, len);
683                         STRINGN_TO_NPVARIANT(retval, len, result);
684                     }
685                 }
686                 else
687                 {
688                     NULL_TO_NPVARIANT(result);
689                 }
690                 return INVOKERESULT_NO_ERROR;
691             }
692             default:
693                 ;
694         }
695     }
696     return INVOKERESULT_GENERIC_ERROR;
697 }
698
699 const NPUTF8 * const LibvlcMessageNPObject::methodNames[] =
700 {
701     /* no methods */
702 };
703 COUNTNAMES(LibvlcMessageNPObject,methodCount,methodNames);
704
705 /*
706 ** implementation of libvlc message iterator object
707 */
708
709 LibvlcMessageIteratorNPObject::LibvlcMessageIteratorNPObject(NPP instance,
710                                                       const NPClass *aClass) :
711     RuntimeNPObject(instance, aClass),
712     _p_iter(NULL)
713 {
714     /* is plugin still running */
715     if( instance->pdata )
716     {
717         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
718         libvlc_log_t *p_log = p_plugin->getLog();
719         if( p_log )
720         {
721             _p_iter = libvlc_log_get_iterator(p_log, NULL);
722         }
723     }
724 };
725
726 LibvlcMessageIteratorNPObject::~LibvlcMessageIteratorNPObject()
727 {
728     if( _p_iter )
729         libvlc_log_iterator_free(_p_iter, NULL);
730 }
731
732 const NPUTF8 * const LibvlcMessageIteratorNPObject::propertyNames[] = 
733 {
734     "hasNext",
735 };
736 COUNTNAMES(LibvlcMessageIteratorNPObject,propertyCount,propertyNames);
737
738 enum LibvlcMessageIteratorNPObjectPropertyIds
739 {
740     ID_messageiterator_hasNext,
741 };
742
743 RuntimeNPObject::InvokeResult
744 LibvlcMessageIteratorNPObject::getProperty(int index, NPVariant &result)
745 {
746     /* is plugin still running */
747     if( _instance->pdata )
748     {
749         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
750         switch( index )
751         {
752             case ID_messageiterator_hasNext:
753             {
754                 if( _p_iter && p_plugin->getLog() )
755                 {
756                     libvlc_exception_t ex;
757                     libvlc_exception_init(&ex);
758
759                     BOOLEAN_TO_NPVARIANT(
760                          libvlc_log_iterator_has_next(_p_iter, &ex), result );
761                     RETURN_ON_EXCEPTION(this,ex);
762                 }
763                 else
764                 {
765                     BOOLEAN_TO_NPVARIANT(0, result);
766                 }
767                 return INVOKERESULT_NO_ERROR;
768             }
769             default:
770                 ;
771         }
772     }
773     return INVOKERESULT_GENERIC_ERROR;
774 }
775
776 const NPUTF8 * const LibvlcMessageIteratorNPObject::methodNames[] =
777 {
778     "next",
779 };
780 COUNTNAMES(LibvlcMessageIteratorNPObject,methodCount,methodNames);
781
782 enum LibvlcMessageIteratorNPObjectMethodIds
783 {
784     ID_messageiterator_next,
785 };
786
787 RuntimeNPObject::InvokeResult
788 LibvlcMessageIteratorNPObject::invoke(int index, const NPVariant *args,
789                                       uint32_t argCount, NPVariant &result)
790 {
791     /* is plugin still running */
792     if( _instance->pdata )
793     {
794         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
795         libvlc_exception_t ex;
796         libvlc_exception_init(&ex);
797
798         switch( index )
799         {
800             case ID_messageiterator_next:
801                 if( argCount == 0 )
802                 {
803                     if( _p_iter && p_plugin->getLog() )
804                     {
805                         struct libvlc_log_message_t buffer;
806
807                         buffer.sizeof_msg = sizeof(buffer);
808
809                         libvlc_log_iterator_next(_p_iter, &buffer, &ex);
810                         RETURN_ON_EXCEPTION(this,ex);
811
812                         LibvlcMessageNPObject* message =
813                             static_cast<LibvlcMessageNPObject*>(
814                             NPN_CreateObject(_instance, RuntimeNPClass<
815                             LibvlcMessageNPObject>::getClass()));
816                         if( message )
817                         {
818                             message->setMessage(buffer);
819                             OBJECT_TO_NPVARIANT(message, result);
820                             return INVOKERESULT_NO_ERROR;
821                         }
822                         return INVOKERESULT_OUT_OF_MEMORY;
823                     }
824                     return INVOKERESULT_GENERIC_ERROR;
825                 }
826                 return INVOKERESULT_NO_SUCH_METHOD;
827             default:
828                 ;
829         }
830     }
831     return INVOKERESULT_GENERIC_ERROR;
832 }
833  
834 /*
835 ** implementation of libvlc message object
836 */
837
838 const NPUTF8 * const LibvlcMessagesNPObject::propertyNames[] = 
839 {
840     "count",
841 };
842 COUNTNAMES(LibvlcMessagesNPObject,propertyCount,propertyNames);
843
844 enum LibvlcMessagesNPObjectPropertyIds
845 {
846     ID_messages_count,
847 };
848
849 RuntimeNPObject::InvokeResult
850 LibvlcMessagesNPObject::getProperty(int index, NPVariant &result)
851 {
852     /* is plugin still running */
853     if( _instance->pdata )
854     {
855         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
856         switch( index )
857         {
858             case ID_messages_count:
859             {
860                 libvlc_log_t *p_log = p_plugin->getLog();
861                 if( p_log )
862                 {
863                     libvlc_exception_t ex;
864                     libvlc_exception_init(&ex);
865
866                     INT32_TO_NPVARIANT(libvlc_log_count(p_log, &ex), result);
867                     RETURN_ON_EXCEPTION(this,ex);
868                 }
869                 else
870                 {
871                     INT32_TO_NPVARIANT(0, result);
872                 }
873                 return INVOKERESULT_NO_ERROR;
874             }
875             default:
876                 ;
877         }
878     }
879     return INVOKERESULT_GENERIC_ERROR;
880 }
881
882 const NPUTF8 * const LibvlcMessagesNPObject::methodNames[] =
883 {
884     "clear",
885     "iterator",
886 };
887 COUNTNAMES(LibvlcMessagesNPObject,methodCount,methodNames);
888
889 enum LibvlcMessagesNPObjectMethodIds
890 {
891     ID_messages_clear,
892     ID_messages_iterator,
893 };
894
895 RuntimeNPObject::InvokeResult
896 LibvlcMessagesNPObject::invoke(int index, const NPVariant *args,
897                                uint32_t argCount, NPVariant &result)
898 {
899     /* is plugin still running */
900     if( _instance->pdata )
901     {
902         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
903         libvlc_exception_t ex;
904         libvlc_exception_init(&ex);
905
906         switch( index )
907         {
908             case ID_messages_clear:
909                 if( argCount == 0 )
910                 {
911                     libvlc_log_t *p_log = p_plugin->getLog();
912                     if( p_log )
913                     {
914                         libvlc_log_clear(p_log, &ex);
915                         RETURN_ON_EXCEPTION(this,ex);
916                     }
917                     return INVOKERESULT_NO_ERROR;
918                 }
919                 return INVOKERESULT_NO_SUCH_METHOD;
920
921             case ID_messages_iterator:
922                 if( argCount == 0 )
923                 {
924                     LibvlcMessageIteratorNPObject* iter =
925                         static_cast<LibvlcMessageIteratorNPObject*>(
926                         NPN_CreateObject(_instance, RuntimeNPClass<
927                         LibvlcMessageIteratorNPObject>::getClass()));
928                     if( iter )
929                     {
930                         OBJECT_TO_NPVARIANT(iter, result);
931                         return INVOKERESULT_NO_ERROR;
932                     }
933                     return INVOKERESULT_OUT_OF_MEMORY;
934                 }
935                 return INVOKERESULT_NO_SUCH_METHOD;
936
937             default:
938                 ;
939         }
940     }
941     return INVOKERESULT_GENERIC_ERROR;
942 }
943
944  
945 /*
946 ** implementation of libvlc message object
947 */
948
949
950 LibvlcLogNPObject::~LibvlcLogNPObject()
951 {
952     if( isValid() )
953     {
954         if( messagesObj ) NPN_ReleaseObject(messagesObj);
955     }
956 };
957
958 const NPUTF8 * const LibvlcLogNPObject::propertyNames[] = 
959 {
960     "messages",
961     "verbosity",
962 };
963 COUNTNAMES(LibvlcLogNPObject,propertyCount,propertyNames);
964
965 enum LibvlcLogNPObjectPropertyIds
966 {
967     ID_log_messages,
968     ID_log_verbosity,
969 };
970
971 RuntimeNPObject::InvokeResult
972 LibvlcLogNPObject::getProperty(int index, NPVariant &result)
973 {
974     /* is plugin still running */
975     if( _instance->pdata )
976     {
977         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
978         libvlc_exception_t ex;
979         libvlc_exception_init(&ex);
980
981         switch( index )
982         {
983             case ID_log_messages:
984             {
985                 // create child object in lazyman fashion to avoid
986                 // ownership problem with firefox
987                 if( ! messagesObj )
988                     messagesObj = NPN_CreateObject(_instance,
989                           RuntimeNPClass<LibvlcMessagesNPObject>::getClass());
990                 OBJECT_TO_NPVARIANT(NPN_RetainObject(messagesObj), result);
991                 return INVOKERESULT_NO_ERROR;
992             }
993             case ID_log_verbosity:
994             {
995                 if( p_plugin->getLog() )
996                 {
997                     INT32_TO_NPVARIANT( libvlc_get_log_verbosity(
998                                         p_plugin->getVLC(), &ex), result);
999                     RETURN_ON_EXCEPTION(this,ex);
1000                 }
1001                 else
1002                 {
1003                     /* log is not enabled, return -1 */
1004                     DOUBLE_TO_NPVARIANT(-1.0, result);
1005                 }
1006                 return INVOKERESULT_NO_ERROR;
1007             }
1008             default:
1009                 ;
1010         }
1011     }
1012     return INVOKERESULT_GENERIC_ERROR;
1013 }
1014
1015 RuntimeNPObject::InvokeResult
1016 LibvlcLogNPObject::setProperty(int index, const NPVariant &value)
1017 {
1018     /* is plugin still running */
1019     if( _instance->pdata )
1020     {
1021         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1022         libvlc_exception_t ex;
1023         libvlc_exception_init(&ex);
1024
1025         switch( index )
1026         {
1027             case ID_log_verbosity:
1028                 if( isNumberValue(value) )
1029                 {
1030                     libvlc_instance_t* p_libvlc = p_plugin->getVLC();
1031                     libvlc_log_t *p_log = p_plugin->getLog();
1032                     int verbosity = numberValue(value);
1033                     if( verbosity >= 0 )
1034                     {
1035                         if( !p_log )
1036                         {
1037                             p_log = libvlc_log_open(p_libvlc, &ex);
1038                             RETURN_ON_EXCEPTION(this,ex);
1039                             p_plugin->setLog(p_log);
1040                         }
1041                         libvlc_set_log_verbosity(p_libvlc, (unsigned)verbosity, &ex);
1042                         RETURN_ON_EXCEPTION(this,ex);
1043                     }
1044                     else if( p_log )
1045                     {
1046                         /* close log  when verbosity is set to -1 */
1047                         p_plugin->setLog(NULL);
1048                         libvlc_log_close(p_log, &ex);
1049                         RETURN_ON_EXCEPTION(this,ex);
1050                     }
1051                     return INVOKERESULT_NO_ERROR;
1052                 }
1053                 return INVOKERESULT_INVALID_VALUE;
1054             default:
1055                 ;
1056         }
1057     }
1058     return INVOKERESULT_GENERIC_ERROR;
1059 }
1060
1061 const NPUTF8 * const LibvlcLogNPObject::methodNames[] =
1062 {
1063     /* no methods */
1064 };
1065 COUNTNAMES(LibvlcLogNPObject,methodCount,methodNames);
1066
1067 /*
1068 ** implementation of libvlc playlist items object
1069 */
1070
1071 const NPUTF8 * const LibvlcPlaylistItemsNPObject::propertyNames[] = 
1072 {
1073     "count",
1074 };
1075 COUNTNAMES(LibvlcPlaylistItemsNPObject,propertyCount,propertyNames);
1076
1077 enum LibvlcPlaylistItemsNPObjectPropertyIds
1078 {
1079     ID_playlistitems_count,
1080 };
1081
1082 RuntimeNPObject::InvokeResult
1083 LibvlcPlaylistItemsNPObject::getProperty(int index, NPVariant &result)
1084 {
1085     /* is plugin still running */
1086     if( _instance->pdata )
1087     {
1088         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1089         libvlc_exception_t ex;
1090         libvlc_exception_init(&ex);
1091
1092         switch( index )
1093         {
1094             case ID_playlistitems_count:
1095             {
1096                 libvlc_playlist_lock(p_plugin->getVLC());
1097                 int val = libvlc_playlist_items_count(p_plugin->getVLC(), &ex);
1098                 libvlc_playlist_unlock(p_plugin->getVLC());
1099                 RETURN_ON_EXCEPTION(this,ex);
1100                 INT32_TO_NPVARIANT(val, result);
1101                 return INVOKERESULT_NO_ERROR;
1102             }
1103             default:
1104                 ;
1105         }
1106     }
1107     return INVOKERESULT_GENERIC_ERROR;
1108 }
1109
1110 const NPUTF8 * const LibvlcPlaylistItemsNPObject::methodNames[] =
1111 {
1112     "clear",
1113     "remove",
1114 };
1115 COUNTNAMES(LibvlcPlaylistItemsNPObject,methodCount,methodNames);
1116
1117 enum LibvlcPlaylistItemsNPObjectMethodIds
1118 {
1119     ID_playlistitems_clear,
1120     ID_playlistitems_remove,
1121 };
1122
1123 RuntimeNPObject::InvokeResult
1124 LibvlcPlaylistItemsNPObject::invoke(int index, const NPVariant *args,
1125                                     uint32_t argCount, NPVariant &result)
1126 {
1127     /* is plugin still running */
1128     if( _instance->pdata )
1129     {
1130         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1131         libvlc_exception_t ex;
1132         libvlc_exception_init(&ex);
1133
1134         switch( index )
1135         {
1136             case ID_playlistitems_clear:
1137                 if( argCount == 0 )
1138                 {
1139                     libvlc_playlist_clear(p_plugin->getVLC(), &ex);
1140                     RETURN_ON_EXCEPTION(this,ex);
1141                     VOID_TO_NPVARIANT(result);
1142                     return INVOKERESULT_NO_ERROR;
1143                 }
1144                 return INVOKERESULT_NO_SUCH_METHOD;
1145             case ID_playlistitems_remove:
1146                 if( (argCount == 1) && isNumberValue(args[0]) )
1147                 {
1148                     libvlc_playlist_delete_item(p_plugin->getVLC(),
1149                                                 numberValue(args[0]), &ex);
1150                     RETURN_ON_EXCEPTION(this,ex);
1151                     VOID_TO_NPVARIANT(result);
1152                     return INVOKERESULT_NO_ERROR;
1153                 }
1154                 return INVOKERESULT_NO_SUCH_METHOD;
1155             default:
1156                 ;
1157         }
1158     }
1159     return INVOKERESULT_GENERIC_ERROR;
1160 }
1161
1162 /*
1163 ** implementation of libvlc playlist object
1164 */
1165
1166
1167 LibvlcPlaylistNPObject::~LibvlcPlaylistNPObject()
1168 {
1169     if( isValid() )
1170     {
1171         if( playlistItemsObj ) NPN_ReleaseObject(playlistItemsObj);
1172     }
1173 };
1174
1175 const NPUTF8 * const LibvlcPlaylistNPObject::propertyNames[] = 
1176 {
1177     "itemCount", /* deprecated */
1178     "isPlaying",
1179     "items",
1180 };
1181 COUNTNAMES(LibvlcPlaylistNPObject,propertyCount,propertyNames);
1182
1183 enum LibvlcPlaylistNPObjectPropertyIds
1184 {
1185     ID_playlist_itemcount,
1186     ID_playlist_isplaying,
1187     ID_playlist_items,
1188 };
1189
1190 RuntimeNPObject::InvokeResult
1191 LibvlcPlaylistNPObject::getProperty(int index, NPVariant &result)
1192 {
1193     /* is plugin still running */
1194     if( _instance->pdata )
1195     {
1196         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1197         libvlc_exception_t ex;
1198         libvlc_exception_init(&ex);
1199
1200         switch( index )
1201         {
1202             case ID_playlist_itemcount: /* deprecated */
1203             {
1204                 libvlc_playlist_lock(p_plugin->getVLC());
1205                 int val = libvlc_playlist_items_count(p_plugin->getVLC(), &ex);
1206                 libvlc_playlist_unlock(p_plugin->getVLC());
1207                 RETURN_ON_EXCEPTION(this,ex);
1208                 INT32_TO_NPVARIANT(val, result);
1209                 return INVOKERESULT_NO_ERROR;
1210             }
1211             case ID_playlist_isplaying:
1212             {
1213                 libvlc_playlist_lock(p_plugin->getVLC());
1214                 int val = libvlc_playlist_isplaying(p_plugin->getVLC(), &ex);
1215                 libvlc_playlist_unlock(p_plugin->getVLC());
1216                 RETURN_ON_EXCEPTION(this,ex);
1217                 BOOLEAN_TO_NPVARIANT(val, result);
1218                 return INVOKERESULT_NO_ERROR;
1219             }
1220             case ID_playlist_items:
1221             {
1222                 // create child object in lazyman fashion to avoid
1223                 // ownership problem with firefox
1224                 if( ! playlistItemsObj )
1225                     playlistItemsObj =
1226                         NPN_CreateObject(_instance, RuntimeNPClass<
1227                         LibvlcPlaylistItemsNPObject>::getClass());
1228                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
1229                 return INVOKERESULT_NO_ERROR;
1230             }
1231             default:
1232                 ;
1233         }
1234     }
1235     return INVOKERESULT_GENERIC_ERROR;
1236 }
1237
1238 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
1239 {
1240     "add",
1241     "play",
1242     "playItem",
1243     "togglePause",
1244     "stop",
1245     "next",
1246     "prev",
1247     "clear", /* deprecated */
1248     "removeItem", /* deprecated */
1249 };
1250 COUNTNAMES(LibvlcPlaylistNPObject,methodCount,methodNames);
1251
1252 enum LibvlcPlaylistNPObjectMethodIds
1253 {
1254     ID_playlist_add,
1255     ID_playlist_play,
1256     ID_playlist_playItem,
1257     ID_playlist_togglepause,
1258     ID_playlist_stop,
1259     ID_playlist_next,
1260     ID_playlist_prev,
1261     ID_playlist_clear,
1262     ID_playlist_removeitem
1263 };
1264
1265 RuntimeNPObject::InvokeResult
1266 LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args,
1267                                uint32_t argCount, NPVariant &result)
1268 {
1269     /* is plugin still running */
1270     if( _instance->pdata )
1271     {
1272         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1273         libvlc_exception_t ex;
1274         libvlc_exception_init(&ex);
1275
1276         switch( index )
1277         {
1278             case ID_playlist_add:
1279             {
1280                 if( (argCount < 1) || (argCount > 3) )
1281                     return INVOKERESULT_NO_SUCH_METHOD;
1282
1283                 char *url = NULL;
1284
1285                 // grab URL
1286                 if( NPVARIANT_IS_STRING(args[0]) )
1287                 {
1288                     char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
1289                     if( s )
1290                     {
1291                         url = p_plugin->getAbsoluteURL(s);
1292                         if( url )
1293                             free(s);
1294                         else
1295                             // problem with combining url, use argument
1296                             url = s;
1297                     }
1298                     else
1299                         return INVOKERESULT_OUT_OF_MEMORY;
1300                 }
1301                 else
1302                     return INVOKERESULT_NO_SUCH_METHOD;
1303
1304                 char *name = NULL;
1305
1306                 // grab name if available
1307                 if( argCount > 1 )
1308                 {
1309                     if( NPVARIANT_IS_NULL(args[1]) )
1310                     {
1311                         // do nothing
1312                     }
1313                     else if( NPVARIANT_IS_STRING(args[1]) )
1314                     {
1315                         name = stringValue(NPVARIANT_TO_STRING(args[1]));
1316                     }
1317                     else
1318                     {
1319                         free(url);
1320                         return INVOKERESULT_INVALID_VALUE;
1321                     }
1322                 }
1323
1324                 int i_options = 0;
1325                 char** ppsz_options = NULL;
1326
1327                 // grab options if available
1328                 if( argCount > 2 )
1329                 {
1330                     if( NPVARIANT_IS_NULL(args[2]) )
1331                     {
1332                         // do nothing
1333                     }
1334                     else if( NPVARIANT_IS_STRING(args[2]) )
1335                     {
1336                         parseOptions(NPVARIANT_TO_STRING(args[2]),
1337                                      &i_options, &ppsz_options);
1338
1339                     }
1340                     else if( NPVARIANT_IS_OBJECT(args[2]) )
1341                     {
1342                         parseOptions(NPVARIANT_TO_OBJECT(args[2]),
1343                                      &i_options, &ppsz_options);
1344                     }
1345                     else
1346                     {
1347                         free(url);
1348                         free(name);
1349                         return INVOKERESULT_INVALID_VALUE;
1350                     }
1351                 }
1352
1353                 int item = libvlc_playlist_add_extended_untrusted(
1354                                p_plugin->getVLC(), url, name, i_options,
1355                                const_cast<const char **>(ppsz_options), &ex);
1356                 free(url);
1357                 free(name);
1358                 for( int i=0; i< i_options; ++i )
1359                 {
1360                     free(ppsz_options[i]);
1361                 }
1362                 free(ppsz_options);
1363
1364                 RETURN_ON_EXCEPTION(this,ex);
1365                 INT32_TO_NPVARIANT(item, result);
1366                 return INVOKERESULT_NO_ERROR;
1367             }
1368             case ID_playlist_play:
1369                 if( argCount == 0 )
1370                 {
1371                     libvlc_playlist_play(p_plugin->getVLC(), -1, 0, NULL, &ex);
1372                     RETURN_ON_EXCEPTION(this,ex);
1373                     VOID_TO_NPVARIANT(result);
1374                     return INVOKERESULT_NO_ERROR;
1375                 }
1376                 return INVOKERESULT_NO_SUCH_METHOD;
1377             case ID_playlist_playItem:
1378                 if( (argCount == 1) && isNumberValue(args[0]) )
1379                 {
1380                     libvlc_playlist_play(p_plugin->getVLC(),
1381                                          numberValue(args[0]), 0, NULL, &ex);
1382                     RETURN_ON_EXCEPTION(this,ex);
1383                     VOID_TO_NPVARIANT(result);
1384                     return INVOKERESULT_NO_ERROR;
1385                 }
1386                 return INVOKERESULT_NO_SUCH_METHOD;
1387             case ID_playlist_togglepause:
1388                 if( argCount == 0 )
1389                 {
1390                     libvlc_playlist_pause(p_plugin->getVLC(), &ex);
1391                     RETURN_ON_EXCEPTION(this,ex);
1392                     VOID_TO_NPVARIANT(result);
1393                     return INVOKERESULT_NO_ERROR;
1394                 }
1395                 return INVOKERESULT_NO_SUCH_METHOD;
1396             case ID_playlist_stop:
1397                 if( argCount == 0 )
1398                 {
1399                     libvlc_playlist_stop(p_plugin->getVLC(), &ex);
1400                     RETURN_ON_EXCEPTION(this,ex);
1401                     VOID_TO_NPVARIANT(result);
1402                     return INVOKERESULT_NO_ERROR;
1403                 }
1404                 return INVOKERESULT_NO_SUCH_METHOD;
1405             case ID_playlist_next:
1406                 if( argCount == 0 )
1407                 {
1408                     libvlc_playlist_next(p_plugin->getVLC(), &ex);
1409                     RETURN_ON_EXCEPTION(this,ex);
1410                     VOID_TO_NPVARIANT(result);
1411                     return INVOKERESULT_NO_ERROR;
1412                 }
1413                 return INVOKERESULT_NO_SUCH_METHOD;
1414             case ID_playlist_prev:
1415                 if( argCount == 0 )
1416                 {
1417                     libvlc_playlist_prev(p_plugin->getVLC(), &ex);
1418                     RETURN_ON_EXCEPTION(this,ex);
1419                     VOID_TO_NPVARIANT(result);
1420                     return INVOKERESULT_NO_ERROR;
1421                 }
1422                 return INVOKERESULT_NO_SUCH_METHOD;
1423             case ID_playlist_clear: /* deprecated */
1424                 if( argCount == 0 )
1425                 {
1426                     libvlc_playlist_clear(p_plugin->getVLC(), &ex);
1427                     RETURN_ON_EXCEPTION(this,ex);
1428                     VOID_TO_NPVARIANT(result);
1429                     return INVOKERESULT_NO_ERROR;
1430                 }
1431                 return INVOKERESULT_NO_SUCH_METHOD;
1432             case ID_playlist_removeitem: /* deprecated */
1433                 if( (argCount == 1) && isNumberValue(args[0]) )
1434                 {
1435                     libvlc_playlist_delete_item(p_plugin->getVLC(),
1436                                                 numberValue(args[0]), &ex);
1437                     RETURN_ON_EXCEPTION(this,ex);
1438                     VOID_TO_NPVARIANT(result);
1439                     return INVOKERESULT_NO_ERROR;
1440                 }
1441                 return INVOKERESULT_NO_SUCH_METHOD;
1442             default:
1443                 ;
1444         }
1445     }
1446     return INVOKERESULT_GENERIC_ERROR;
1447 }
1448
1449 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps,
1450                                          int *i_options, char*** ppsz_options)
1451 {
1452     if( nps.utf8length )
1453     {
1454         char *s = stringValue(nps);
1455         char *val = s;
1456         if( val )
1457         {
1458             long capacity = 16;
1459             char **options = (char **)malloc(capacity*sizeof(char *));
1460             if( options )
1461             {
1462                 int nOptions = 0;
1463
1464                 char *end = val + nps.utf8length;
1465                 while( val < end )
1466                 {
1467                     // skip leading blanks
1468                     while( (val < end)
1469                         && ((*val == ' ' ) || (*val == '\t')) )
1470                         ++val;
1471
1472                     char *start = val;
1473                     // skip till we get a blank character
1474                     while( (val < end)
1475                         && (*val != ' ' )
1476                         && (*val != '\t') )
1477                     {
1478                         char c = *(val++);
1479                         if( ('\'' == c) || ('"' == c) )
1480                         {
1481                             // skip till end of string
1482                             while( (val < end) && (*(val++) != c ) );
1483                         }
1484                     }
1485
1486                     if( val > start )
1487                     {
1488                         if( nOptions == capacity )
1489                         {
1490                             capacity += 16;
1491                             char **moreOptions = (char **)realloc(options, capacity*sizeof(char*)); 
1492                             if( ! moreOptions )
1493                             {
1494                                 /* failed to allocate more memory */
1495                                 free(s);
1496                                 /* return what we got so far */
1497                                 *i_options = nOptions;
1498                                 *ppsz_options = options;
1499                                 return;
1500                             }
1501                             options = moreOptions;
1502                         }
1503                         *(val++) = '\0';
1504                         options[nOptions++] = strdup(start);
1505                     }
1506                     else
1507                         // must be end of string
1508                         break;
1509                 }
1510                 *i_options = nOptions;
1511                 *ppsz_options = options;
1512             }
1513             free(s);
1514         }
1515     }
1516 }
1517
1518 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options,
1519                                           char*** ppsz_options)
1520 {
1521     /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1522
1523     NPVariant value;
1524
1525     /* we are expecting to have a Javascript Array object */
1526     NPIdentifier propId = NPN_GetStringIdentifier("length");
1527     if( NPN_GetProperty(_instance, obj, propId, &value) )
1528     {
1529         int count = numberValue(value);
1530         NPN_ReleaseVariantValue(&value);
1531
1532         if( count )
1533         {
1534             long capacity = 16;
1535             char **options = (char **)malloc(capacity*sizeof(char *));
1536             if( options )
1537             {
1538                 int nOptions = 0;
1539
1540                 while( nOptions < count )
1541                 {
1542                     propId = NPN_GetIntIdentifier(nOptions);
1543                     if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1544                         /* return what we got so far */
1545                         break;
1546
1547                     if( ! NPVARIANT_IS_STRING(value) )
1548                     {
1549                         /* return what we got so far */
1550                         NPN_ReleaseVariantValue(&value);
1551                         break;
1552                     }
1553
1554                     if( nOptions == capacity )
1555                     {
1556                         capacity += 16;
1557                         char **moreOptions = (char **)realloc(options, capacity*sizeof(char*)); 
1558                         if( ! moreOptions )
1559                         {
1560                             /* failed to allocate more memory */
1561                             NPN_ReleaseVariantValue(&value);
1562                             /* return what we got so far */
1563                             *i_options = nOptions;
1564                             *ppsz_options = options;
1565                             break;
1566                         }
1567                         options = moreOptions;
1568                     }
1569
1570                     options[nOptions++] = stringValue(value);
1571                 }
1572                 *i_options = nOptions;
1573                 *ppsz_options = options;
1574             }
1575         }
1576     }
1577 }
1578
1579 /*
1580 ** implementation of libvlc video object
1581 */
1582
1583 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] = 
1584 {
1585     "fullscreen",
1586     "height",
1587     "width",
1588     "aspectRatio",
1589     "subtitle",
1590     "crop",
1591     "teletext"
1592 };
1593
1594 enum LibvlcVideoNPObjectPropertyIds
1595 {
1596     ID_video_fullscreen,
1597     ID_video_height,
1598     ID_video_width,
1599     ID_video_aspectratio,
1600     ID_video_subtitle,
1601     ID_video_crop,
1602     ID_video_teletext
1603 };
1604 COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
1605
1606 RuntimeNPObject::InvokeResult
1607 LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1608 {
1609     /* is plugin still running */
1610     if( _instance->pdata )
1611     {
1612         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1613         libvlc_exception_t ex;
1614         libvlc_exception_init(&ex);
1615
1616         libvlc_media_player_t *p_md = libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
1617         RETURN_ON_EXCEPTION(this,ex);
1618
1619         switch( index )
1620         {
1621             case ID_video_fullscreen:
1622             {
1623                 int val = libvlc_get_fullscreen(p_md, &ex);
1624                 libvlc_media_player_release(p_md);
1625                 RETURN_ON_EXCEPTION(this,ex);
1626                 BOOLEAN_TO_NPVARIANT(val, result);
1627                 return INVOKERESULT_NO_ERROR;
1628             }
1629             case ID_video_height:
1630             {
1631                 int val = libvlc_video_get_height(p_md, &ex);
1632                 libvlc_media_player_release(p_md);
1633                 RETURN_ON_EXCEPTION(this,ex);
1634                 INT32_TO_NPVARIANT(val, result);
1635                 return INVOKERESULT_NO_ERROR;
1636             }
1637             case ID_video_width:
1638             {
1639                 int val = libvlc_video_get_width(p_md, &ex);
1640                 libvlc_media_player_release(p_md);
1641                 RETURN_ON_EXCEPTION(this,ex);
1642                 INT32_TO_NPVARIANT(val, result);
1643                 return INVOKERESULT_NO_ERROR;
1644             }
1645             case ID_video_aspectratio:
1646             {
1647                 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1648                 libvlc_media_player_release(p_md);
1649                 RETURN_ON_EXCEPTION(this,ex);
1650                 if( !psz_aspect )
1651                     return INVOKERESULT_GENERIC_ERROR;
1652
1653                 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1654                 return INVOKERESULT_NO_ERROR;
1655             }
1656             case ID_video_subtitle:
1657             {
1658                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1659                 libvlc_media_player_release(p_md);
1660                 RETURN_ON_EXCEPTION(this,ex);
1661                 INT32_TO_NPVARIANT(i_spu, result);
1662                 return INVOKERESULT_NO_ERROR;
1663             }
1664             case ID_video_crop:
1665             {
1666                 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1667                 libvlc_media_player_release(p_md);
1668                 RETURN_ON_EXCEPTION(this,ex);
1669                 if( !psz_geometry )
1670                     return INVOKERESULT_GENERIC_ERROR;
1671
1672                 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1673                 return INVOKERESULT_NO_ERROR;
1674             }
1675             case ID_video_teletext:
1676             {
1677                 int i_page = libvlc_video_get_teletext(p_md, &ex);
1678                 libvlc_media_player_release(p_md);
1679                 RETURN_ON_EXCEPTION(this,ex);
1680                 INT32_TO_NPVARIANT(i_page, result);
1681                 return INVOKERESULT_NO_ERROR;
1682             }
1683         }
1684         libvlc_media_player_release(p_md);
1685     }
1686     return INVOKERESULT_GENERIC_ERROR;
1687 }
1688
1689 RuntimeNPObject::InvokeResult
1690 LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1691 {
1692     /* is plugin still running */
1693     if( _instance->pdata )
1694     {
1695         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1696         libvlc_exception_t ex;
1697         libvlc_exception_init(&ex);
1698
1699         libvlc_media_player_t *p_md = libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
1700         RETURN_ON_EXCEPTION(this,ex);
1701
1702         switch( index )
1703         {
1704             case ID_video_fullscreen:
1705             {
1706                 if( ! NPVARIANT_IS_BOOLEAN(value) )
1707                 {
1708                     libvlc_media_player_release(p_md);
1709                     return INVOKERESULT_INVALID_VALUE;
1710                 }
1711
1712                 int val = NPVARIANT_TO_BOOLEAN(value);
1713                 libvlc_set_fullscreen(p_md, val, &ex);
1714                 libvlc_media_player_release(p_md);
1715
1716                 RETURN_ON_EXCEPTION(this,ex);
1717                 return INVOKERESULT_NO_ERROR;
1718             }
1719             case ID_video_aspectratio:
1720             {
1721                 char *psz_aspect = NULL;
1722
1723                 if( ! NPVARIANT_IS_STRING(value) )
1724                 {
1725                     libvlc_media_player_release(p_md);
1726                     return INVOKERESULT_INVALID_VALUE;
1727                 }
1728
1729                 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1730                 if( !psz_aspect )
1731                 {
1732                     libvlc_media_player_release(p_md);
1733                     return INVOKERESULT_GENERIC_ERROR;
1734                 }
1735
1736                 libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1737                 free(psz_aspect);
1738                 libvlc_media_player_release(p_md);
1739                 RETURN_ON_EXCEPTION(this,ex);
1740
1741                 return INVOKERESULT_NO_ERROR;
1742             }
1743             case ID_video_subtitle:
1744             {
1745                 if( isNumberValue(value) )
1746                 {
1747                     libvlc_video_set_spu(p_md,
1748                                          numberValue(value), &ex);
1749                     libvlc_media_player_release(p_md);
1750                     RETURN_ON_EXCEPTION(this,ex);
1751
1752                     return INVOKERESULT_NO_ERROR;
1753                 }
1754                 libvlc_media_player_release(p_md);
1755                 return INVOKERESULT_INVALID_VALUE;
1756             }
1757             case ID_video_crop:
1758             {
1759                 char *psz_geometry = NULL;
1760
1761                 if( ! NPVARIANT_IS_STRING(value) )
1762                 {
1763                     libvlc_media_player_release(p_md);
1764                     return INVOKERESULT_INVALID_VALUE;
1765                 }
1766
1767                 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
1768                 if( !psz_geometry )
1769                 {
1770                     libvlc_media_player_release(p_md);
1771                     return INVOKERESULT_GENERIC_ERROR;
1772                 }
1773
1774                 libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
1775                 free(psz_geometry);
1776                 libvlc_media_player_release(p_md);
1777                 RETURN_ON_EXCEPTION(this,ex);
1778
1779                 return INVOKERESULT_NO_ERROR;
1780             }
1781             case ID_video_teletext:
1782             {
1783                 if( isNumberValue(value) )
1784                 {
1785                     libvlc_video_set_teletext(p_md,
1786                                          numberValue(value), &ex);
1787                     libvlc_media_player_release(p_md);
1788                     RETURN_ON_EXCEPTION(this,ex);
1789
1790                     return INVOKERESULT_NO_ERROR;
1791                 }
1792                 libvlc_media_player_release(p_md);
1793                 return INVOKERESULT_INVALID_VALUE;
1794             }
1795         }
1796         libvlc_media_player_release(p_md);
1797     }
1798     return INVOKERESULT_GENERIC_ERROR;
1799 }
1800
1801 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
1802 {
1803     "toggleFullscreen",
1804     "toggleTeletext"
1805 };
1806 COUNTNAMES(LibvlcVideoNPObject,methodCount,methodNames);
1807
1808 enum LibvlcVideoNPObjectMethodIds
1809 {
1810     ID_video_togglefullscreen,
1811     ID_video_toggleteletext
1812 };
1813
1814 RuntimeNPObject::InvokeResult
1815 LibvlcVideoNPObject::invoke(int index, const NPVariant *args,
1816                             uint32_t argCount, NPVariant &result)
1817 {
1818     /* is plugin still running */
1819     if( _instance->pdata )
1820     {
1821         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1822         libvlc_exception_t ex;
1823         libvlc_exception_init(&ex);
1824
1825         libvlc_media_player_t *p_md = libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
1826         RETURN_ON_EXCEPTION(this,ex);
1827
1828         switch( index )
1829         {
1830             case ID_video_togglefullscreen:
1831                 if( argCount == 0 )
1832                 {
1833                     libvlc_toggle_fullscreen(p_md, &ex);
1834                     libvlc_media_player_release(p_md);
1835                     RETURN_ON_EXCEPTION(this,ex);
1836                     VOID_TO_NPVARIANT(result);
1837                     return INVOKERESULT_NO_ERROR;
1838                 }
1839                 return INVOKERESULT_NO_SUCH_METHOD;
1840             case ID_video_toggleteletext:
1841                 if( argCount == 0 )
1842                 {
1843                     libvlc_toggle_teletext(p_md, &ex);
1844                     libvlc_media_player_release(p_md);
1845                     RETURN_ON_EXCEPTION(this,ex);
1846                     VOID_TO_NPVARIANT(result);
1847                     return INVOKERESULT_NO_ERROR;
1848                 }
1849                 return INVOKERESULT_NO_SUCH_METHOD;
1850             default:
1851                 return INVOKERESULT_NO_SUCH_METHOD;
1852         }
1853     }
1854     return INVOKERESULT_GENERIC_ERROR;
1855 }