]> git.sesse.net Git - vlc/blob - projects/mozilla/control/npolibvlc.cpp
mozilla: protect calls to libvlc_playlist_isplaying()
[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                 libvlc_playlist_lock(p_plugin->getVLC());
1353                 int val = libvlc_playlist_isplaying(p_plugin->getVLC(), &ex);
1354                 libvlc_playlist_unlock(p_plugin->getVLC());
1355                 if( libvlc_exception_raised(&ex) )
1356                 {
1357                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1358                     libvlc_exception_clear(&ex);
1359                     return INVOKERESULT_GENERIC_ERROR;
1360                 }
1361                 BOOLEAN_TO_NPVARIANT(val, result);
1362                 return INVOKERESULT_NO_ERROR;
1363             }
1364             case ID_playlist_items:
1365             {
1366                 // create child object in lazyman fashion to avoid ownership problem with firefox
1367                 if( ! playlistItemsObj )
1368                     playlistItemsObj = NPN_CreateObject(_instance, RuntimeNPClass<LibvlcPlaylistItemsNPObject>::getClass());
1369                 OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistItemsObj), result);
1370                 return INVOKERESULT_NO_ERROR;
1371             }
1372             default:
1373                 ;
1374         }
1375     }
1376     return INVOKERESULT_GENERIC_ERROR;
1377 }
1378
1379 const NPUTF8 * const LibvlcPlaylistNPObject::methodNames[] =
1380 {
1381     "add",
1382     "play",
1383     "playItem",
1384     "togglePause",
1385     "stop",
1386     "next",
1387     "prev",
1388     "clear", /* deprecated */
1389     "removeItem", /* deprecated */
1390 };
1391
1392 const int LibvlcPlaylistNPObject::methodCount = sizeof(LibvlcPlaylistNPObject::methodNames)/sizeof(NPUTF8 *);
1393
1394 enum LibvlcPlaylistNPObjectMethodIds
1395 {
1396     ID_playlist_add,
1397     ID_playlist_play,
1398     ID_playlist_playItem,
1399     ID_playlist_togglepause,
1400     ID_playlist_stop,
1401     ID_playlist_next,
1402     ID_playlist_prev,
1403     ID_playlist_clear,
1404     ID_playlist_removeitem
1405 };
1406
1407 RuntimeNPObject::InvokeResult LibvlcPlaylistNPObject::invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result)
1408 {
1409     /* is plugin still running */
1410     if( _instance->pdata )
1411     {
1412         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1413         libvlc_exception_t ex;
1414         libvlc_exception_init(&ex);
1415
1416         switch( index )
1417         {
1418             case ID_playlist_add:
1419             {
1420                 if( (argCount < 1) || (argCount > 3) )
1421                     return INVOKERESULT_NO_SUCH_METHOD;
1422
1423                 char *url = NULL;
1424
1425                 // grab URL
1426                 if( NPVARIANT_IS_STRING(args[0]) )
1427                 {
1428                     char *s = stringValue(NPVARIANT_TO_STRING(args[0]));
1429                     if( s )
1430                     {
1431                         url = p_plugin->getAbsoluteURL(s);
1432                         if( url )
1433                             free(s);
1434                         else
1435                             // problem with combining url, use argument
1436                             url = s;
1437                     }
1438                     else
1439                         return INVOKERESULT_OUT_OF_MEMORY;
1440                 }
1441                 else
1442                     return INVOKERESULT_NO_SUCH_METHOD;
1443
1444                 char *name = NULL;
1445
1446                 // grab name if available
1447                 if( argCount > 1 )
1448                 {
1449                     if( NPVARIANT_IS_NULL(args[1]) )
1450                     {
1451                         // do nothing
1452                     }
1453                     else if( NPVARIANT_IS_STRING(args[1]) )
1454                     {
1455                         name = stringValue(NPVARIANT_TO_STRING(args[1]));
1456                     }
1457                     else
1458                     {
1459                         free(url);
1460                         return INVOKERESULT_INVALID_VALUE;
1461                     }
1462                 }
1463
1464                 int i_options = 0;
1465                 char** ppsz_options = NULL;
1466
1467                 // grab options if available
1468                 if( argCount > 2 )
1469                 {
1470                     if( NPVARIANT_IS_NULL(args[2]) )
1471                     {
1472                         // do nothing
1473                     }
1474                     else if( NPVARIANT_IS_STRING(args[2]) )
1475                     {
1476                         parseOptions(NPVARIANT_TO_STRING(args[2]), &i_options, &ppsz_options);
1477
1478                     }
1479                     else if( NPVARIANT_IS_OBJECT(args[2]) )
1480                     {
1481                         parseOptions(NPVARIANT_TO_OBJECT(args[2]), &i_options, &ppsz_options);
1482                     }
1483                     else
1484                     {
1485                         free(url);
1486                         free(name);
1487                         return INVOKERESULT_INVALID_VALUE;
1488                     }
1489                 }
1490
1491                 int item = libvlc_playlist_add_extended_untrusted(p_plugin->getVLC(),
1492                                                                   url,
1493                                                                   name,
1494                                                                   i_options,
1495                                                                   const_cast<const char **>(ppsz_options),
1496                                                                   &ex);
1497                 free(url);
1498                 free(name);
1499                 for( int i=0; i< i_options; ++i )
1500                 {
1501                     free(ppsz_options[i]);
1502                 }
1503                 free(ppsz_options);
1504
1505                 if( libvlc_exception_raised(&ex) )
1506                 {
1507                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1508                     libvlc_exception_clear(&ex);
1509                     return INVOKERESULT_GENERIC_ERROR;
1510                 }
1511                 else
1512                 {
1513                     INT32_TO_NPVARIANT(item, result);
1514                     return INVOKERESULT_NO_ERROR;
1515                 }
1516             }
1517             case ID_playlist_play:
1518                 if( argCount == 0 )
1519                 {
1520                     libvlc_playlist_play(p_plugin->getVLC(), -1, 0, NULL, &ex);
1521                     if( libvlc_exception_raised(&ex) )
1522                     {
1523                         NPN_SetException(this, libvlc_exception_get_message(&ex));
1524                         libvlc_exception_clear(&ex);
1525                         return INVOKERESULT_GENERIC_ERROR;
1526                     }
1527                     else
1528                     {
1529                         VOID_TO_NPVARIANT(result);
1530                         return INVOKERESULT_NO_ERROR;
1531                     }
1532                 }
1533                 return INVOKERESULT_NO_SUCH_METHOD;
1534             case ID_playlist_playItem:
1535                 if( (argCount == 1) && isNumberValue(args[0]) )
1536                 {
1537                     libvlc_playlist_play(p_plugin->getVLC(), numberValue(args[0]), 0, NULL, &ex);
1538                     if( libvlc_exception_raised(&ex) )
1539                     {
1540                         NPN_SetException(this, libvlc_exception_get_message(&ex));
1541                         libvlc_exception_clear(&ex);
1542                         return INVOKERESULT_GENERIC_ERROR;
1543                     }
1544                     else
1545                     {
1546                         VOID_TO_NPVARIANT(result);
1547                         return INVOKERESULT_NO_ERROR;
1548                     }
1549                 }
1550                 return INVOKERESULT_NO_SUCH_METHOD;
1551             case ID_playlist_togglepause:
1552                 if( argCount == 0 )
1553                 {
1554                     libvlc_playlist_pause(p_plugin->getVLC(), &ex);
1555                     if( libvlc_exception_raised(&ex) )
1556                     {
1557                         NPN_SetException(this, libvlc_exception_get_message(&ex));
1558                         libvlc_exception_clear(&ex);
1559                         return INVOKERESULT_GENERIC_ERROR;
1560                     }
1561                     else
1562                     {
1563                         VOID_TO_NPVARIANT(result);
1564                         return INVOKERESULT_NO_ERROR;
1565                     }
1566                 }
1567                 return INVOKERESULT_NO_SUCH_METHOD;
1568             case ID_playlist_stop:
1569                 if( argCount == 0 )
1570                 {
1571                     libvlc_playlist_stop(p_plugin->getVLC(), &ex);
1572                     if( libvlc_exception_raised(&ex) )
1573                     {
1574                         NPN_SetException(this, libvlc_exception_get_message(&ex));
1575                         libvlc_exception_clear(&ex);
1576                         return INVOKERESULT_GENERIC_ERROR;
1577                     }
1578                     else
1579                     {
1580                         VOID_TO_NPVARIANT(result);
1581                         return INVOKERESULT_NO_ERROR;
1582                     }
1583                 }
1584                 return INVOKERESULT_NO_SUCH_METHOD;
1585             case ID_playlist_next:
1586                 if( argCount == 0 )
1587                 {
1588                     libvlc_playlist_next(p_plugin->getVLC(), &ex);
1589                     if( libvlc_exception_raised(&ex) )
1590                     {
1591                         NPN_SetException(this, libvlc_exception_get_message(&ex));
1592                         libvlc_exception_clear(&ex);
1593                         return INVOKERESULT_GENERIC_ERROR;
1594                     }
1595                     else
1596                     {
1597                         VOID_TO_NPVARIANT(result);
1598                         return INVOKERESULT_NO_ERROR;
1599                     }
1600                 }
1601                 return INVOKERESULT_NO_SUCH_METHOD;
1602             case ID_playlist_prev:
1603                 if( argCount == 0 )
1604                 {
1605                     libvlc_playlist_prev(p_plugin->getVLC(), &ex);
1606                     if( libvlc_exception_raised(&ex) )
1607                     {
1608                         NPN_SetException(this, libvlc_exception_get_message(&ex));
1609                         libvlc_exception_clear(&ex);
1610                         return INVOKERESULT_GENERIC_ERROR;
1611                     }
1612                     else
1613                     {
1614                         VOID_TO_NPVARIANT(result);
1615                         return INVOKERESULT_NO_ERROR;
1616                     }
1617                 }
1618                 return INVOKERESULT_NO_SUCH_METHOD;
1619             case ID_playlist_clear: /* deprecated */
1620                 if( argCount == 0 )
1621                 {
1622                     libvlc_playlist_clear(p_plugin->getVLC(), &ex);
1623                     if( libvlc_exception_raised(&ex) )
1624                     {
1625                         NPN_SetException(this, libvlc_exception_get_message(&ex));
1626                         libvlc_exception_clear(&ex);
1627                         return INVOKERESULT_GENERIC_ERROR;
1628                     }
1629                     else
1630                     {
1631                         VOID_TO_NPVARIANT(result);
1632                         return INVOKERESULT_NO_ERROR;
1633                     }
1634                 }
1635                 return INVOKERESULT_NO_SUCH_METHOD;
1636             case ID_playlist_removeitem: /* deprecated */
1637                 if( (argCount == 1) && isNumberValue(args[0]) )
1638                 {
1639                     libvlc_playlist_delete_item(p_plugin->getVLC(), numberValue(args[0]), &ex);
1640                     if( libvlc_exception_raised(&ex) )
1641                     {
1642                         NPN_SetException(this, libvlc_exception_get_message(&ex));
1643                         libvlc_exception_clear(&ex);
1644                         return INVOKERESULT_GENERIC_ERROR;
1645                     }
1646                     else
1647                     {
1648                         VOID_TO_NPVARIANT(result);
1649                         return INVOKERESULT_NO_ERROR;
1650                     }
1651                 }
1652                 return INVOKERESULT_NO_SUCH_METHOD;
1653             default:
1654                 ;
1655         }
1656     }
1657     return INVOKERESULT_GENERIC_ERROR;
1658 }
1659
1660 void LibvlcPlaylistNPObject::parseOptions(const NPString &nps, int *i_options, char*** ppsz_options)
1661 {
1662     if( nps.utf8length )
1663     {
1664         char *s = stringValue(nps);
1665         char *val = s;
1666         if( val )
1667         {
1668             long capacity = 16;
1669             char **options = (char **)malloc(capacity*sizeof(char *));
1670             if( options )
1671             {
1672                 int nOptions = 0;
1673
1674                 char *end = val + nps.utf8length;
1675                 while( val < end )
1676                 {
1677                     // skip leading blanks
1678                     while( (val < end)
1679                         && ((*val == ' ' ) || (*val == '\t')) )
1680                         ++val;
1681
1682                     char *start = val;
1683                     // skip till we get a blank character
1684                     while( (val < end)
1685                         && (*val != ' ' )
1686                         && (*val != '\t') )
1687                     {
1688                         char c = *(val++);
1689                         if( ('\'' == c) || ('"' == c) )
1690                         {
1691                             // skip till end of string
1692                             while( (val < end) && (*(val++) != c ) );
1693                         }
1694                     }
1695
1696                     if( val > start )
1697                     {
1698                         if( nOptions == capacity )
1699                         {
1700                             capacity += 16;
1701                             char **moreOptions = (char **)realloc(options, capacity*sizeof(char*)); 
1702                             if( ! moreOptions )
1703                             {
1704                                 /* failed to allocate more memory */
1705                                 free(s);
1706                                 /* return what we got so far */
1707                                 *i_options = nOptions;
1708                                 *ppsz_options = options;
1709                                 return;
1710                             }
1711                             options = moreOptions;
1712                         }
1713                         *(val++) = '\0';
1714                         options[nOptions++] = strdup(start);
1715                     }
1716                     else
1717                         // must be end of string
1718                         break;
1719                 }
1720                 *i_options = nOptions;
1721                 *ppsz_options = options;
1722             }
1723             free(s);
1724         }
1725     }
1726 }
1727
1728 void LibvlcPlaylistNPObject::parseOptions(NPObject *obj, int *i_options, char*** ppsz_options)
1729 {
1730     /* WARNING: Safari does not implement NPN_HasProperty/NPN_HasMethod */
1731
1732     NPVariant value;
1733
1734     /* we are expecting to have a Javascript Array object */
1735     NPIdentifier propId = NPN_GetStringIdentifier("length");
1736     if( NPN_GetProperty(_instance, obj, propId, &value) )
1737     {
1738         int count = numberValue(value);
1739         NPN_ReleaseVariantValue(&value);
1740
1741         if( count )
1742         {
1743             long capacity = 16;
1744             char **options = (char **)malloc(capacity*sizeof(char *));
1745             if( options )
1746             {
1747                 int nOptions = 0;
1748
1749                 while( nOptions < count )
1750                 {
1751                     propId = NPN_GetIntIdentifier(nOptions);
1752                     if( ! NPN_GetProperty(_instance, obj, propId, &value) )
1753                         /* return what we got so far */
1754                         break;
1755
1756                     if( ! NPVARIANT_IS_STRING(value) )
1757                     {
1758                         /* return what we got so far */
1759                         NPN_ReleaseVariantValue(&value);
1760                         break;
1761                     }
1762
1763                     if( nOptions == capacity )
1764                     {
1765                         capacity += 16;
1766                         char **moreOptions = (char **)realloc(options, capacity*sizeof(char*)); 
1767                         if( ! moreOptions )
1768                         {
1769                             /* failed to allocate more memory */
1770                             NPN_ReleaseVariantValue(&value);
1771                             /* return what we got so far */
1772                             *i_options = nOptions;
1773                             *ppsz_options = options;
1774                             break;
1775                         }
1776                         options = moreOptions;
1777                     }
1778
1779                     options[nOptions++] = stringValue(value);
1780                 }
1781                 *i_options = nOptions;
1782                 *ppsz_options = options;
1783             }
1784         }
1785     }
1786 }
1787
1788 /*
1789 ** implementation of libvlc video object
1790 */
1791
1792 const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] = 
1793 {
1794     "fullscreen",
1795     "height",
1796     "width",
1797     "aspectRatio",
1798     "subtitle",
1799     "crop",
1800     "teletext"
1801 };
1802
1803 enum LibvlcVideoNPObjectPropertyIds
1804 {
1805     ID_video_fullscreen,
1806     ID_video_height,
1807     ID_video_width,
1808     ID_video_aspectratio,
1809     ID_video_subtitle,
1810     ID_video_crop,
1811     ID_video_teletext
1812 };
1813
1814 const int LibvlcVideoNPObject::propertyCount = sizeof(LibvlcVideoNPObject::propertyNames)/sizeof(NPUTF8 *);
1815
1816 RuntimeNPObject::InvokeResult LibvlcVideoNPObject::getProperty(int index, NPVariant &result)
1817 {
1818     /* is plugin still running */
1819     if( _instance->pdata )
1820     {
1821         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1822         libvlc_exception_t ex;
1823         libvlc_exception_init(&ex);
1824
1825         libvlc_media_player_t *p_md = libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
1826         if( libvlc_exception_raised(&ex) )
1827         {
1828             NPN_SetException(this, libvlc_exception_get_message(&ex));
1829             libvlc_exception_clear(&ex);
1830             return INVOKERESULT_GENERIC_ERROR;
1831         }
1832
1833         switch( index )
1834         {
1835             case ID_video_fullscreen:
1836             {
1837                 int val = libvlc_get_fullscreen(p_md, &ex);
1838                 libvlc_media_player_release(p_md);
1839                 if( libvlc_exception_raised(&ex) )
1840                 {
1841                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1842                     libvlc_exception_clear(&ex);
1843                     return INVOKERESULT_GENERIC_ERROR;
1844                 }
1845                 BOOLEAN_TO_NPVARIANT(val, result);
1846                 return INVOKERESULT_NO_ERROR;
1847             }
1848             case ID_video_height:
1849             {
1850                 int val = libvlc_video_get_height(p_md, &ex);
1851                 libvlc_media_player_release(p_md);
1852                 if( libvlc_exception_raised(&ex) )
1853                 {
1854                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1855                     libvlc_exception_clear(&ex);
1856                     return INVOKERESULT_GENERIC_ERROR;
1857                 }
1858                 INT32_TO_NPVARIANT(val, result);
1859                 return INVOKERESULT_NO_ERROR;
1860             }
1861             case ID_video_width:
1862             {
1863                 int val = libvlc_video_get_width(p_md, &ex);
1864                 libvlc_media_player_release(p_md);
1865                 if( libvlc_exception_raised(&ex) )
1866                 {
1867                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1868                     libvlc_exception_clear(&ex);
1869                     return INVOKERESULT_GENERIC_ERROR;
1870                 }
1871                 INT32_TO_NPVARIANT(val, result);
1872                 return INVOKERESULT_NO_ERROR;
1873             }
1874             case ID_video_aspectratio:
1875             {
1876                 NPUTF8 *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1877                 libvlc_media_player_release(p_md);
1878                 if( libvlc_exception_raised(&ex) )
1879                 {
1880                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1881                     libvlc_exception_clear(&ex);
1882                     return INVOKERESULT_GENERIC_ERROR;
1883                 }
1884                 if( !psz_aspect )
1885                     return INVOKERESULT_GENERIC_ERROR;
1886
1887                 STRINGZ_TO_NPVARIANT(psz_aspect, result);
1888                 return INVOKERESULT_NO_ERROR;
1889             }
1890             case ID_video_subtitle:
1891             {
1892                 int i_spu = libvlc_video_get_spu(p_md, &ex);
1893                 libvlc_media_player_release(p_md);
1894                 if( libvlc_exception_raised(&ex) )
1895                 {
1896                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1897                     libvlc_exception_clear(&ex);
1898                     return INVOKERESULT_GENERIC_ERROR;
1899                 }
1900                 INT32_TO_NPVARIANT(i_spu, result);
1901                 return INVOKERESULT_NO_ERROR;
1902             }
1903             case ID_video_crop:
1904             {
1905                 NPUTF8 *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1906                 libvlc_media_player_release(p_md);
1907                 if( libvlc_exception_raised(&ex) )
1908                 {
1909                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1910                     libvlc_exception_clear(&ex);
1911                     return INVOKERESULT_GENERIC_ERROR;
1912                 }
1913                 if( !psz_geometry )
1914                     return INVOKERESULT_GENERIC_ERROR;
1915
1916                 STRINGZ_TO_NPVARIANT(psz_geometry, result);
1917                 return INVOKERESULT_NO_ERROR;
1918             }
1919             case ID_video_teletext:
1920             {
1921                 int i_page = libvlc_video_get_teletext(p_md, &ex);
1922                 libvlc_media_player_release(p_md);
1923                 if( libvlc_exception_raised(&ex) )
1924                 {
1925                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1926                     libvlc_exception_clear(&ex);
1927                     return INVOKERESULT_GENERIC_ERROR;
1928                 }
1929                 INT32_TO_NPVARIANT(i_page, result);
1930                 return INVOKERESULT_NO_ERROR;
1931             }
1932         }
1933         libvlc_media_player_release(p_md);
1934     }
1935     return INVOKERESULT_GENERIC_ERROR;
1936 }
1937
1938 RuntimeNPObject::InvokeResult LibvlcVideoNPObject::setProperty(int index, const NPVariant &value)
1939 {
1940     /* is plugin still running */
1941     if( _instance->pdata )
1942     {
1943         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
1944         libvlc_exception_t ex;
1945         libvlc_exception_init(&ex);
1946
1947         libvlc_media_player_t *p_md = libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
1948         if( libvlc_exception_raised(&ex) )
1949         {
1950             NPN_SetException(this, libvlc_exception_get_message(&ex));
1951             libvlc_exception_clear(&ex);
1952             return INVOKERESULT_GENERIC_ERROR;
1953         }
1954
1955         switch( index )
1956         {
1957             case ID_video_fullscreen:
1958             {
1959                 if( ! NPVARIANT_IS_BOOLEAN(value) )
1960                 {
1961                     libvlc_media_player_release(p_md);
1962                     return INVOKERESULT_INVALID_VALUE;
1963                 }
1964
1965                 int val = NPVARIANT_TO_BOOLEAN(value);
1966                 libvlc_set_fullscreen(p_md, val, &ex);
1967                 libvlc_media_player_release(p_md);
1968
1969                 if( libvlc_exception_raised(&ex) )
1970                 {
1971                     NPN_SetException(this, libvlc_exception_get_message(&ex));
1972                     libvlc_exception_clear(&ex);
1973                     return INVOKERESULT_GENERIC_ERROR;
1974                 }
1975                 return INVOKERESULT_NO_ERROR;
1976             }
1977             case ID_video_aspectratio:
1978             {
1979                 char *psz_aspect = NULL;
1980
1981                 if( ! NPVARIANT_IS_STRING(value) )
1982                 {
1983                     libvlc_media_player_release(p_md);
1984                     return INVOKERESULT_INVALID_VALUE;
1985                 }
1986
1987                 psz_aspect = stringValue(NPVARIANT_TO_STRING(value));
1988                 if( !psz_aspect )
1989                 {
1990                     libvlc_media_player_release(p_md);
1991                     return INVOKERESULT_GENERIC_ERROR;
1992                 }
1993
1994                 libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1995                 free(psz_aspect);
1996                 libvlc_media_player_release(p_md);
1997
1998                 if( libvlc_exception_raised(&ex) )
1999                 {
2000                     NPN_SetException(this, libvlc_exception_get_message(&ex));
2001                     libvlc_exception_clear(&ex);
2002                     return INVOKERESULT_GENERIC_ERROR;
2003                 }
2004                 return INVOKERESULT_NO_ERROR;
2005             }
2006             case ID_video_subtitle:
2007             {
2008                 if( isNumberValue(value) )
2009                 {
2010                     libvlc_video_set_spu(p_md,
2011                                          numberValue(value), &ex);
2012                     libvlc_media_player_release(p_md);
2013                     if( libvlc_exception_raised(&ex) )
2014                     {
2015                         NPN_SetException(this, libvlc_exception_get_message(&ex));
2016                         libvlc_exception_clear(&ex);
2017                         return INVOKERESULT_GENERIC_ERROR;
2018                     }
2019                     return INVOKERESULT_NO_ERROR;
2020                 }
2021                 libvlc_media_player_release(p_md);
2022                 return INVOKERESULT_INVALID_VALUE;
2023             }
2024             case ID_video_crop:
2025             {
2026                 char *psz_geometry = NULL;
2027
2028                 if( ! NPVARIANT_IS_STRING(value) )
2029                 {
2030                     libvlc_media_player_release(p_md);
2031                     return INVOKERESULT_INVALID_VALUE;
2032                 }
2033
2034                 psz_geometry = stringValue(NPVARIANT_TO_STRING(value));
2035                 if( !psz_geometry )
2036                 {
2037                     libvlc_media_player_release(p_md);
2038                     return INVOKERESULT_GENERIC_ERROR;
2039                 }
2040
2041                 libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
2042                 free(psz_geometry);
2043                 libvlc_media_player_release(p_md);
2044
2045                 if( libvlc_exception_raised(&ex) )
2046                 {
2047                     NPN_SetException(this, libvlc_exception_get_message(&ex));
2048                     libvlc_exception_clear(&ex);
2049                     return INVOKERESULT_GENERIC_ERROR;
2050                 }
2051                 return INVOKERESULT_NO_ERROR;
2052             }
2053             case ID_video_teletext:
2054             {
2055                 if( isNumberValue(value) )
2056                 {
2057                     libvlc_video_set_teletext(p_md,
2058                                          numberValue(value), &ex);
2059                     libvlc_media_player_release(p_md);
2060                     if( libvlc_exception_raised(&ex) )
2061                     {
2062                         NPN_SetException(this, libvlc_exception_get_message(&ex));
2063                         libvlc_exception_clear(&ex);
2064                         return INVOKERESULT_GENERIC_ERROR;
2065                     }
2066                     return INVOKERESULT_NO_ERROR;
2067                 }
2068                 libvlc_media_player_release(p_md);
2069                 return INVOKERESULT_INVALID_VALUE;
2070             }
2071         }
2072         libvlc_media_player_release(p_md);
2073     }
2074     return INVOKERESULT_GENERIC_ERROR;
2075 }
2076
2077 const NPUTF8 * const LibvlcVideoNPObject::methodNames[] =
2078 {
2079     "toggleFullscreen",
2080     "toggleTeletext"
2081 };
2082
2083 enum LibvlcVideoNPObjectMethodIds
2084 {
2085     ID_video_togglefullscreen,
2086     ID_video_toggleteletext
2087 };
2088
2089 const int LibvlcVideoNPObject::methodCount = sizeof(LibvlcVideoNPObject::methodNames)/sizeof(NPUTF8 *);
2090
2091 RuntimeNPObject::InvokeResult LibvlcVideoNPObject::invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result)
2092 {
2093     /* is plugin still running */
2094     if( _instance->pdata )
2095     {
2096         VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(_instance->pdata);
2097         libvlc_exception_t ex;
2098         libvlc_exception_init(&ex);
2099
2100         libvlc_media_player_t *p_md = libvlc_playlist_get_media_player(p_plugin->getVLC(), &ex);
2101         if( libvlc_exception_raised(&ex) )
2102         {
2103             NPN_SetException(this, libvlc_exception_get_message(&ex));
2104             libvlc_exception_clear(&ex);
2105             return INVOKERESULT_GENERIC_ERROR;
2106         }
2107
2108         switch( index )
2109         {
2110             case ID_video_togglefullscreen:
2111                 if( argCount == 0 )
2112                 {
2113                     libvlc_toggle_fullscreen(p_md, &ex);
2114                     libvlc_media_player_release(p_md);
2115                     if( libvlc_exception_raised(&ex) )
2116                     {
2117                         NPN_SetException(this, libvlc_exception_get_message(&ex));
2118                         libvlc_exception_clear(&ex);
2119                         return INVOKERESULT_GENERIC_ERROR;
2120                     }
2121                     else
2122                     {
2123                         VOID_TO_NPVARIANT(result);
2124                         return INVOKERESULT_NO_ERROR;
2125                     }
2126                 }
2127                 else
2128                 {
2129                     /* cannot get md, probably not playing */
2130                     if( libvlc_exception_raised(&ex) )
2131                     {
2132                         NPN_SetException(this, libvlc_exception_get_message(&ex));
2133                         libvlc_exception_clear(&ex);
2134                     }
2135                     return INVOKERESULT_GENERIC_ERROR;
2136                 }
2137                 return INVOKERESULT_NO_SUCH_METHOD;
2138             case ID_video_toggleteletext:
2139                 if( argCount == 0 )
2140                 {
2141                     libvlc_toggle_teletext(p_md, &ex);
2142                     libvlc_media_player_release(p_md);
2143                     if( libvlc_exception_raised(&ex) )
2144                     {
2145                         NPN_SetException(this, libvlc_exception_get_message(&ex));
2146                         libvlc_exception_clear(&ex);
2147                         return INVOKERESULT_GENERIC_ERROR;
2148                     }
2149                     else
2150                     {
2151                         VOID_TO_NPVARIANT(result);
2152                         return INVOKERESULT_NO_ERROR;
2153                     }
2154                 }
2155                 else
2156                 {
2157                     /* cannot get md, probably not playing */
2158                     if( libvlc_exception_raised(&ex) )
2159                     {
2160                         NPN_SetException(this, libvlc_exception_get_message(&ex));
2161                         libvlc_exception_clear(&ex);
2162                     }
2163                     return INVOKERESULT_GENERIC_ERROR;
2164                 }
2165                 return INVOKERESULT_NO_SUCH_METHOD;
2166             default:
2167                 return INVOKERESULT_NO_SUCH_METHOD;
2168         }
2169     }
2170     return INVOKERESULT_GENERIC_ERROR;
2171 }
2172