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