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