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