]> git.sesse.net Git - vlc/blob - projects/activex/vlccontrol2.cpp
mozilla: factorize.
[vlc] / projects / activex / vlccontrol2.cpp
1 /*****************************************************************************
2  * vlccontrol2.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * Copyright (C) 2010 M2X BV
6  *
7  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
8  *          Jean-Paul Saman <jpsaman _at_ m2x _dot_ nl>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include <stdio.h>
26 #include <shlwapi.h>
27 #include <wininet.h>
28 #include <tchar.h>
29
30 #include "utils.h"
31 #include "plugin.h"
32 #include "vlccontrol2.h"
33 #include "vlccontrol.h"
34
35 #include "position.h"
36
37 // ---------
38
39 HRESULT VLCInterfaceBase::report_exception(REFIID riid, libvlc_exception_t *ex)
40 {
41     _plug->setErrorInfo(riid,libvlc_errmsg());
42     libvlc_exception_clear(ex);
43     return E_FAIL;
44 }
45
46 HRESULT VLCInterfaceBase::loadTypeInfo(REFIID riid)
47 {
48     // if( _ti ) return NOERROR; // unnecessairy
49
50     ITypeLib *p_typelib;
51     HRESULT hr = _plug->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
52     if( SUCCEEDED(hr) )
53     {
54         hr = p_typelib->GetTypeInfoOfGuid(riid, &_ti);
55         if( FAILED(hr) ) _ti = NULL;
56         p_typelib->Release();
57     }
58     return hr;
59 }
60
61 #define BIND_INTERFACE( class ) \
62     template<> REFIID VLCInterface<class, I##class>::_riid = IID_I##class;
63
64 BIND_INTERFACE( VLCAudio )
65 BIND_INTERFACE( VLCInput )
66 BIND_INTERFACE( VLCMarquee )
67 BIND_INTERFACE( VLCLogo )
68 BIND_INTERFACE( VLCDeinterlace )
69 BIND_INTERFACE( VLCPlaylistItems )
70 BIND_INTERFACE( VLCPlaylist )
71 BIND_INTERFACE( VLCVideo )
72 BIND_INTERFACE( VLCSubtitle )
73
74 #undef  BIND_INTERFACE
75
76 template<class I> static inline
77 HRESULT object_get(I **dst, I *src)
78 {
79     if( NULL == dst )
80         return E_POINTER;
81
82     *dst = src;
83     if( NULL != src )
84     {
85         src->AddRef();
86         return NOERROR;
87     }
88     return E_OUTOFMEMORY;
89 }
90
91 static inline
92 VARIANT_BOOL varbool(bool b) { return b ? VARIANT_TRUE : VARIANT_FALSE; }
93
94 // ---------
95
96 STDMETHODIMP VLCAudio::get_mute(VARIANT_BOOL* mute)
97 {
98     if( NULL == mute )
99         return E_POINTER;
100
101     libvlc_instance_t* p_libvlc;
102     HRESULT hr = getVLC(&p_libvlc);
103     if( SUCCEEDED(hr) )
104         *mute = varbool( libvlc_audio_get_mute(p_libvlc) );
105     return hr;
106 };
107
108 STDMETHODIMP VLCAudio::put_mute(VARIANT_BOOL mute)
109 {
110     libvlc_instance_t* p_libvlc;
111     HRESULT hr = getVLC(&p_libvlc);
112     if( SUCCEEDED(hr) )
113         libvlc_audio_set_mute(p_libvlc, VARIANT_FALSE != mute);
114     return hr;
115 };
116
117 STDMETHODIMP VLCAudio::get_volume(long* volume)
118 {
119     if( NULL == volume )
120         return E_POINTER;
121
122     libvlc_instance_t* p_libvlc;
123     HRESULT hr = getVLC(&p_libvlc);
124     if( SUCCEEDED(hr) )
125         *volume = libvlc_audio_get_volume(p_libvlc);
126     return hr;
127 };
128
129 STDMETHODIMP VLCAudio::put_volume(long volume)
130 {
131     libvlc_instance_t* p_libvlc;
132     HRESULT hr = getVLC(&p_libvlc);
133     if( SUCCEEDED(hr) )
134     {
135         libvlc_exception_t ex;
136         libvlc_exception_init(&ex);
137
138         libvlc_audio_set_volume(p_libvlc, volume, &ex);
139         hr = exception_bridge(&ex);
140     }
141     return hr;
142 };
143
144 STDMETHODIMP VLCAudio::get_track(long* track)
145 {
146     if( NULL == track )
147         return E_POINTER;
148
149     libvlc_media_player_t* p_md;
150     HRESULT hr = getMD(&p_md);
151     if( SUCCEEDED(hr) )
152     {
153         libvlc_exception_t ex;
154         libvlc_exception_init(&ex);
155
156         *track = libvlc_audio_get_track(p_md, &ex);
157         hr = exception_bridge(&ex);
158     }
159     return hr;
160 };
161
162 STDMETHODIMP VLCAudio::put_track(long track)
163 {
164     libvlc_media_player_t *p_md;
165     HRESULT hr = getMD(&p_md);
166     if( SUCCEEDED(hr) )
167     {
168         libvlc_exception_t ex;
169         libvlc_exception_init(&ex);
170
171         libvlc_audio_set_track(p_md, track, &ex);
172         hr = exception_bridge(&ex);
173     }
174     return hr;
175 };
176
177 STDMETHODIMP VLCAudio::get_count(long* trackNumber)
178 {
179     if( NULL == trackNumber )
180         return E_POINTER;
181
182     libvlc_media_player_t* p_md;
183     HRESULT hr = getMD(&p_md);
184     if( SUCCEEDED(hr) )
185     {
186         libvlc_exception_t ex;
187         libvlc_exception_init(&ex);
188         // get the number of audio track available and return it
189         *trackNumber = libvlc_audio_get_track_count(p_md, &ex);
190         hr = exception_bridge(&ex);
191     }
192     return hr;
193 };
194
195
196 STDMETHODIMP VLCAudio::description(long trackID, BSTR* name)
197 {
198     if( NULL == name )
199         return E_POINTER;
200
201     libvlc_media_player_t* p_md;
202     libvlc_exception_t ex;
203     libvlc_exception_init(&ex);
204
205     HRESULT hr = getMD(&p_md);
206     if( SUCCEEDED(hr) )
207     {
208         int i, i_limit;
209         const char *psz_name;
210         libvlc_track_description_t *p_trackDesc;
211
212         // get tracks description
213         p_trackDesc = libvlc_audio_get_track_description(p_md, &ex);
214         hr = exception_bridge(&ex);
215         if( FAILED(hr) )
216             return hr;
217
218         //get the number of available track
219         i_limit = libvlc_audio_get_track_count(p_md, &ex);
220         hr = exception_bridge(&ex);
221         if( FAILED(hr) )
222             return hr;
223
224         // check if the number given is a good one
225         if ( ( trackID > ( i_limit -1 ) ) || ( trackID < 0 ) )
226                 return E_FAIL;
227
228         // get the good trackDesc
229         for( i = 0 ; i < trackID ; i++ )
230         {
231             p_trackDesc = p_trackDesc->p_next;
232         }
233         // get the track name
234         psz_name = p_trackDesc->psz_name;
235
236         // return it
237         if( psz_name != NULL )
238         {
239             *name = BSTRFromCStr(CP_UTF8, psz_name);
240             return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
241         }
242         *name = NULL;
243         return E_FAIL;
244     }
245     return hr;
246 };
247
248 STDMETHODIMP VLCAudio::get_channel(long *channel)
249 {
250     if( NULL == channel )
251         return E_POINTER;
252
253     libvlc_instance_t* p_libvlc;
254     HRESULT hr = getVLC(&p_libvlc);
255     if( SUCCEEDED(hr) )
256     {
257         libvlc_exception_t ex;
258         libvlc_exception_init(&ex);
259
260         *channel = libvlc_audio_get_channel(p_libvlc, &ex);
261         hr = exception_bridge(&ex);
262     }
263     return hr;
264 };
265
266 STDMETHODIMP VLCAudio::put_channel(long channel)
267 {
268     libvlc_instance_t* p_libvlc;
269     HRESULT hr = getVLC(&p_libvlc);
270     if( SUCCEEDED(hr) )
271     {
272         libvlc_exception_t ex;
273         libvlc_exception_init(&ex);
274
275         libvlc_audio_set_channel(p_libvlc, channel, &ex);
276         hr = exception_bridge(&ex);
277     }
278     return hr;
279 };
280
281 STDMETHODIMP VLCAudio::toggleMute()
282 {
283     libvlc_instance_t* p_libvlc;
284     HRESULT hr = getVLC(&p_libvlc);
285     if( SUCCEEDED(hr) )
286         libvlc_audio_toggle_mute(p_libvlc);
287     return hr;
288 };
289
290 /****************************************************************************/
291
292 STDMETHODIMP VLCDeinterlace::disable()
293 {
294     libvlc_media_player_t *p_md;
295     HRESULT hr = getMD(&p_md);
296     if( SUCCEEDED(hr) )
297     {
298         libvlc_exception_t ex;
299         libvlc_exception_init(&ex);
300
301         libvlc_video_set_deinterlace(p_md, 0, "", &ex);
302         hr = exception_bridge(&ex);
303     }
304     return hr;
305 }
306
307 STDMETHODIMP VLCDeinterlace::enable(BSTR mode)
308 {
309     libvlc_media_player_t *p_md;
310     HRESULT hr = getMD(&p_md);
311     if( SUCCEEDED(hr) )
312     {
313         libvlc_exception_t ex;
314         libvlc_exception_init(&ex);
315         char *psz_mode = CStrFromBSTR(CP_UTF8, mode);
316         libvlc_video_set_deinterlace(p_md, 1, psz_mode, &ex);
317         CoTaskMemFree(psz_mode);
318         hr = exception_bridge(&ex);
319     }
320     return hr;
321 }
322
323 /****************************************************************************/
324
325 STDMETHODIMP VLCInput::get_length(double* length)
326 {
327     if( NULL == length )
328         return E_POINTER;
329     *length = 0;
330
331     libvlc_media_player_t *p_md;
332     HRESULT hr = getMD(&p_md);
333     if( SUCCEEDED(hr) )
334     {
335         libvlc_exception_t ex;
336         libvlc_exception_init(&ex);
337
338         *length = (double)libvlc_media_player_get_length(p_md, &ex);
339         hr = exception_bridge(&ex);
340     }
341     return hr;
342 };
343
344 STDMETHODIMP VLCInput::get_position(double* position)
345 {
346     if( NULL == position )
347         return E_POINTER;
348
349     *position = 0.0f;
350     libvlc_media_player_t *p_md;
351     HRESULT hr = getMD(&p_md);
352     if( SUCCEEDED(hr) )
353     {
354         libvlc_exception_t ex;
355         libvlc_exception_init(&ex);
356
357         *position = libvlc_media_player_get_position(p_md, &ex);
358         hr = exception_bridge(&ex);
359     }
360     return hr;
361 };
362
363 STDMETHODIMP VLCInput::put_position(double position)
364 {
365     libvlc_media_player_t *p_md;
366     HRESULT hr = getMD(&p_md);
367     if( SUCCEEDED(hr) )
368     {
369         libvlc_exception_t ex;
370         libvlc_exception_init(&ex);
371
372         libvlc_media_player_set_position(p_md, position, &ex);
373         hr = exception_bridge(&ex);
374     }
375     return hr;
376 };
377
378 STDMETHODIMP VLCInput::get_time(double* time)
379 {
380     if( NULL == time )
381         return E_POINTER;
382
383     libvlc_media_player_t *p_md;
384     HRESULT hr = getMD(&p_md);
385     if( SUCCEEDED(hr) )
386     {
387         libvlc_exception_t ex;
388         libvlc_exception_init(&ex);
389
390         *time = (double)libvlc_media_player_get_time(p_md, &ex);
391         hr = exception_bridge(&ex);
392     }
393     return hr;
394 };
395
396 STDMETHODIMP VLCInput::put_time(double time)
397 {
398     libvlc_media_player_t *p_md;
399     HRESULT hr = getMD(&p_md);
400     if( SUCCEEDED(hr) )
401     {
402         libvlc_exception_t ex;
403         libvlc_exception_init(&ex);
404
405         libvlc_media_player_set_time(p_md, (int64_t)time, &ex);
406         hr = exception_bridge(&ex);
407     }
408     return hr;
409 };
410
411 STDMETHODIMP VLCInput::get_state(long* state)
412 {
413     if( NULL == state )
414         return E_POINTER;
415
416     libvlc_media_player_t *p_md;
417     HRESULT hr = getMD(&p_md);
418     if( SUCCEEDED(hr) )
419     {
420         libvlc_exception_t ex;
421         libvlc_exception_init(&ex);
422
423         *state = libvlc_media_player_get_state(p_md);
424         if( libvlc_exception_raised(&ex) )
425         {
426             // don't fail, just return the idle state
427             *state = 0;
428             libvlc_exception_clear(&ex);
429         }
430     }
431     return hr;
432 };
433
434 STDMETHODIMP VLCInput::get_rate(double* rate)
435 {
436     if( NULL == rate )
437         return E_POINTER;
438
439     libvlc_media_player_t *p_md;
440     HRESULT hr = getMD(&p_md);
441     if( SUCCEEDED(hr) )
442     {
443         libvlc_exception_t ex;
444         libvlc_exception_init(&ex);
445
446         *rate = libvlc_media_player_get_rate(p_md, &ex);
447         hr = exception_bridge(&ex);
448     }
449     return hr;
450 };
451
452 STDMETHODIMP VLCInput::put_rate(double rate)
453 {
454     libvlc_media_player_t *p_md;
455     HRESULT hr = getMD(&p_md);
456     if( SUCCEEDED(hr) )
457     {
458         libvlc_exception_t ex;
459         libvlc_exception_init(&ex);
460
461         libvlc_media_player_set_rate(p_md, rate, &ex);
462         hr = exception_bridge(&ex);
463     }
464     return hr;
465 };
466
467 STDMETHODIMP VLCInput::get_fps(double* fps)
468 {
469     if( NULL == fps )
470         return E_POINTER;
471
472     *fps = 0.0;
473     libvlc_media_player_t *p_md;
474     HRESULT hr = getMD(&p_md);
475     if( SUCCEEDED(hr) )
476     {
477         libvlc_exception_t ex;
478         libvlc_exception_init(&ex);
479
480         *fps = libvlc_media_player_get_fps(p_md, &ex);
481         hr = exception_bridge(&ex);
482     }
483     return hr;
484 };
485
486 STDMETHODIMP VLCInput::get_hasVout(VARIANT_BOOL* hasVout)
487 {
488     if( NULL == hasVout )
489         return E_POINTER;
490
491     libvlc_media_player_t *p_md;
492     HRESULT hr = getMD(&p_md);
493     if( SUCCEEDED(hr) )
494     {
495         libvlc_exception_t ex;
496         libvlc_exception_init(&ex);
497
498         *hasVout = varbool( libvlc_media_player_has_vout(p_md, &ex) );
499         hr = exception_bridge(&ex);
500     }
501     return hr;
502 };
503
504 /****************************************************************************/
505
506 HRESULT VLCMarquee::do_put_int(unsigned idx, LONG val)
507 {
508     libvlc_media_player_t *p_md;
509     HRESULT hr = getMD(&p_md);
510     if( SUCCEEDED(hr) )
511     {
512         libvlc_exception_t ex;
513         libvlc_exception_init(&ex);
514         libvlc_video_set_marquee_int(p_md, idx, val, &ex);
515         hr = exception_bridge(&ex);
516     }
517     return hr;
518 }
519
520 HRESULT VLCMarquee::do_get_int(unsigned idx, LONG *val)
521 {
522     if( NULL == val )
523         return E_POINTER;
524
525     libvlc_media_player_t *p_md;
526     HRESULT hr = getMD(&p_md);
527     if( SUCCEEDED(hr) )
528     {
529         libvlc_exception_t ex;
530         libvlc_exception_init(&ex);
531         *val = libvlc_video_get_marquee_int(p_md, idx, &ex);
532         hr = exception_bridge(&ex);
533     }
534     return hr;
535 }
536
537 STDMETHODIMP VLCMarquee::get_position(BSTR* val)
538 {
539     if( NULL == val )
540         return E_POINTER;
541
542     LONG i;
543     HRESULT hr = do_get_int(libvlc_marquee_Position, &i);
544
545     if(SUCCEEDED(hr))
546         *val = BSTRFromCStr(CP_UTF8, position_bynumber(i));
547
548     return hr;
549 }
550
551 STDMETHODIMP VLCMarquee::put_position(BSTR val)
552 {
553     char *n = CStrFromBSTR(CP_UTF8, val);
554     if( !n ) return E_OUTOFMEMORY;
555
556     size_t i;
557     HRESULT hr;
558     if( position_byname( n, i ) )
559         hr = do_put_int(libvlc_marquee_Position,i);
560     else
561         hr = E_INVALIDARG;
562
563     CoTaskMemFree(n);
564     return hr;
565 }
566
567 STDMETHODIMP VLCMarquee::get_text(BSTR *val)
568 {
569     char *psz;
570     if( NULL == val )
571         return E_POINTER;
572
573     libvlc_media_player_t *p_md;
574     HRESULT hr = getMD(&p_md);
575     if( SUCCEEDED(hr) )
576     {
577         libvlc_exception_t ex;
578         libvlc_exception_init(&ex);
579
580         psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text, &ex);
581
582         hr = exception_bridge(&ex);
583         if(SUCCEEDED(hr))
584             *val = BSTRFromCStr(CP_UTF8, psz);
585     }
586     return hr;
587 }
588
589 STDMETHODIMP VLCMarquee::put_text(BSTR val)
590 {
591     libvlc_media_player_t *p_md;
592     HRESULT hr = getMD(&p_md);
593     if( SUCCEEDED(hr) )
594     {
595         libvlc_exception_t ex;
596         libvlc_exception_init(&ex);
597
598         char *psz_text = CStrFromBSTR(CP_UTF8, val);
599         libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
600                                         psz_text, &ex);
601         hr = exception_bridge(&ex);
602         CoTaskMemFree(psz_text);
603     }
604     return hr;
605 }
606
607 /****************************************************************************/
608
609 STDMETHODIMP VLCPlaylistItems::get_count(long* count)
610 {
611     if( NULL == count )
612         return E_POINTER;
613
614     libvlc_exception_t ex;
615     libvlc_exception_init(&ex);
616
617     *count = Instance()->playlist_count(&ex);
618     return exception_bridge(&ex);
619 };
620
621 STDMETHODIMP VLCPlaylistItems::clear()
622 {
623     libvlc_exception_t ex;
624     libvlc_exception_init(&ex);
625
626     Instance()->playlist_clear(&ex);
627     return exception_bridge(&ex);
628 };
629
630 STDMETHODIMP VLCPlaylistItems::remove(long item)
631 {
632     libvlc_instance_t* p_libvlc;
633     HRESULT hr = getVLC(&p_libvlc);
634     if( SUCCEEDED(hr) )
635     {
636         libvlc_exception_t ex;
637         libvlc_exception_init(&ex);
638
639         Instance()->playlist_delete_item(item, &ex);
640         hr = exception_bridge(&ex);
641     }
642     return hr;
643 };
644
645 /****************************************************************************/
646
647 STDMETHODIMP VLCPlaylist::get_itemCount(long* count)
648 {
649     if( NULL == count )
650         return E_POINTER;
651
652     *count = 0;
653     libvlc_exception_t ex;
654     libvlc_exception_init(&ex);
655
656     *count = Instance()->playlist_count(&ex);
657     return exception_bridge(&ex);
658 };
659
660 STDMETHODIMP VLCPlaylist::get_isPlaying(VARIANT_BOOL* isPlaying)
661 {
662     if( NULL == isPlaying )
663         return E_POINTER;
664
665     libvlc_media_player_t *p_md;
666     HRESULT hr = getMD(&p_md);
667     if( SUCCEEDED(hr) )
668     {
669         libvlc_exception_t ex;
670         libvlc_exception_init(&ex);
671
672         *isPlaying = varbool( libvlc_media_player_is_playing(p_md) );
673         libvlc_exception_clear(&ex);
674     }
675     return hr;
676 };
677
678 STDMETHODIMP VLCPlaylist::add(BSTR uri, VARIANT name, VARIANT options, long* item)
679 {
680     if( NULL == item )
681         return E_POINTER;
682
683     if( 0 == SysStringLen(uri) )
684         return E_INVALIDARG;
685
686     libvlc_instance_t* p_libvlc;
687     HRESULT hr = getVLC(&p_libvlc);
688     if( SUCCEEDED(hr) )
689     {
690         libvlc_exception_t ex;
691         libvlc_exception_init(&ex);
692
693         char *psz_uri = NULL;
694         if( SysStringLen(Instance()->getBaseURL()) > 0 )
695         {
696             /*
697             ** if the MRL a relative URL, we should end up with an absolute URL
698             */
699             LPWSTR abs_url = CombineURL(Instance()->getBaseURL(), uri);
700             if( NULL != abs_url )
701             {
702                 psz_uri = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
703                 CoTaskMemFree(abs_url);
704             }
705             else
706             {
707                 psz_uri = CStrFromBSTR(CP_UTF8, uri);
708             }
709         }
710         else
711         {
712             /*
713             ** baseURL is empty, assume MRL is absolute
714             */
715             psz_uri = CStrFromBSTR(CP_UTF8, uri);
716         }
717
718         if( NULL == psz_uri )
719         {
720             return E_OUTOFMEMORY;
721         }
722
723         int i_options;
724         char **ppsz_options;
725
726         hr = VLCControl::CreateTargetOptions(CP_UTF8, &options, &ppsz_options, &i_options);
727         if( FAILED(hr) )
728         {
729             CoTaskMemFree(psz_uri);
730             return hr;
731         }
732
733         char *psz_name = NULL;
734         VARIANT v_name;
735         VariantInit(&v_name);
736         if( SUCCEEDED(VariantChangeType(&v_name, &name, 0, VT_BSTR)) )
737         {
738             if( SysStringLen(V_BSTR(&v_name)) > 0 )
739                 psz_name = CStrFromBSTR(CP_UTF8, V_BSTR(&v_name));
740
741             VariantClear(&v_name);
742         }
743
744         *item = Instance()->playlist_add_extended_untrusted(psz_uri,
745                     i_options, const_cast<const char **>(ppsz_options), &ex);
746
747         VLCControl::FreeTargetOptions(ppsz_options, i_options);
748         CoTaskMemFree(psz_uri);
749         if( psz_name ) /* XXX Do we even need to check? */
750             CoTaskMemFree(psz_name);
751         hr = exception_bridge(&ex);
752     }
753     return hr;
754 };
755
756 STDMETHODIMP VLCPlaylist::play()
757 {
758     libvlc_exception_t ex;
759     libvlc_exception_init(&ex);
760
761     Instance()->playlist_play(&ex);
762     return exception_bridge(&ex);
763 };
764
765 STDMETHODIMP VLCPlaylist::playItem(long item)
766 {
767     libvlc_exception_t ex;
768     libvlc_exception_init(&ex);
769
770     Instance()->playlist_play_item(item,&ex);
771     return exception_bridge(&ex);;
772 };
773
774 STDMETHODIMP VLCPlaylist::togglePause()
775 {
776     libvlc_media_player_t* p_md;
777     HRESULT hr = getMD(&p_md);
778     if( SUCCEEDED(hr) )
779     {
780         libvlc_exception_t ex;
781         libvlc_exception_init(&ex);
782
783         libvlc_media_player_pause(p_md, &ex);
784         hr = exception_bridge(&ex);;
785     }
786     return hr;
787 };
788
789 STDMETHODIMP VLCPlaylist::stop()
790 {
791     libvlc_media_player_t *p_md;
792     HRESULT hr = getMD(&p_md);
793     if( SUCCEEDED(hr) )
794     {
795         libvlc_exception_t ex;
796         libvlc_exception_init(&ex);
797
798         libvlc_media_player_stop(p_md);
799         hr = exception_bridge(&ex);;
800     }
801     return hr;
802 };
803
804 STDMETHODIMP VLCPlaylist::next()
805 {
806     libvlc_exception_t ex;
807     libvlc_exception_init(&ex);
808
809     Instance()->playlist_next(&ex);
810     return exception_bridge(&ex);;
811 };
812
813 STDMETHODIMP VLCPlaylist::prev()
814 {
815     libvlc_exception_t ex;
816     libvlc_exception_init(&ex);
817
818     Instance()->playlist_prev(&ex);
819     return exception_bridge(&ex);;
820 };
821
822 STDMETHODIMP VLCPlaylist::clear()
823 {
824     libvlc_exception_t ex;
825     libvlc_exception_init(&ex);
826
827     Instance()->playlist_clear(&ex);
828     return exception_bridge(&ex);;
829 };
830
831 STDMETHODIMP VLCPlaylist::removeItem(long item)
832 {
833     libvlc_instance_t* p_libvlc;
834     HRESULT hr = getVLC(&p_libvlc);
835     if( SUCCEEDED(hr) )
836     {
837         libvlc_exception_t ex;
838         libvlc_exception_init(&ex);
839
840         Instance()->playlist_delete_item(item, &ex);
841         hr = exception_bridge(&ex);;
842     }
843     return hr;
844 };
845
846 STDMETHODIMP VLCPlaylist::get_items(IVLCPlaylistItems** obj)
847 {
848     if( NULL == obj )
849         return E_POINTER;
850
851     *obj = _p_vlcplaylistitems;
852     if( NULL != _p_vlcplaylistitems )
853     {
854         _p_vlcplaylistitems->AddRef();
855         return NOERROR;
856     }
857     return E_OUTOFMEMORY;
858 };
859
860 /****************************************************************************/
861
862 STDMETHODIMP VLCSubtitle::get_track(long* spu)
863 {
864     if( NULL == spu )
865         return E_POINTER;
866
867     libvlc_media_player_t *p_md;
868     HRESULT hr = getMD(&p_md);
869     if( SUCCEEDED(hr) )
870     {
871         libvlc_exception_t ex;
872         libvlc_exception_init(&ex);
873
874         *spu = libvlc_video_get_spu(p_md, &ex);
875         hr = exception_bridge(&ex);
876     }
877     return hr;
878 };
879
880 STDMETHODIMP VLCSubtitle::put_track(long spu)
881 {
882     libvlc_media_player_t *p_md;
883     HRESULT hr = getMD(&p_md);
884     if( SUCCEEDED(hr) )
885     {
886         libvlc_exception_t ex;
887         libvlc_exception_init(&ex);
888
889         libvlc_video_set_spu(p_md, spu, &ex);
890         hr = exception_bridge(&ex);
891     }
892     return hr;
893 };
894
895 STDMETHODIMP VLCSubtitle::get_count(long* spuNumber)
896 {
897     if( NULL == spuNumber )
898         return E_POINTER;
899
900     libvlc_media_player_t *p_md;
901     HRESULT hr = getMD(&p_md);
902     if( SUCCEEDED(hr) )
903     {
904         libvlc_exception_t ex;
905         libvlc_exception_init(&ex);
906         // get the number of video subtitle available and return it
907         *spuNumber = libvlc_video_get_spu_count(p_md, &ex);
908         hr = exception_bridge(&ex);
909     }
910     return hr;
911 };
912
913
914 STDMETHODIMP VLCSubtitle::description(long nameID, BSTR* name)
915 {
916     if( NULL == name )
917        return E_POINTER;
918
919     libvlc_media_player_t* p_md;
920     libvlc_exception_t ex;
921     libvlc_exception_init(&ex);
922
923     HRESULT hr = getMD(&p_md);
924     if( SUCCEEDED(hr) )
925     {
926         int i, i_limit;
927         const char *psz_name;
928         libvlc_track_description_t *p_spuDesc;
929
930         // get subtitles description
931         p_spuDesc = libvlc_video_get_spu_description(p_md, &ex);
932         hr = exception_bridge(&ex);
933         if( FAILED(hr) )
934             return hr;
935
936         // get the number of available subtitle
937         i_limit = libvlc_video_get_spu_count(p_md, &ex);
938         hr = exception_bridge(&ex);
939         if( FAILED(hr) )
940             return hr;
941
942         // check if the number given is a good one
943         if ( ( nameID > ( i_limit -1 ) ) || ( nameID < 0 ) )
944             return E_FAIL;
945
946         // get the good spuDesc
947         for( i = 0 ; i < nameID ; i++ )
948         {
949             p_spuDesc = p_spuDesc->p_next;
950         }
951         // get the subtitle name
952         psz_name = p_spuDesc->psz_name;
953
954         // return it
955         if( psz_name != NULL )
956         {
957             *name = BSTRFromCStr(CP_UTF8, psz_name);
958             return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
959         }
960         *name = NULL;
961         return E_FAIL;
962     }
963     return hr;
964 };
965
966 /****************************************************************************/
967
968 STDMETHODIMP VLCVideo::get_fullscreen(VARIANT_BOOL* fullscreen)
969 {
970     if( NULL == fullscreen )
971         return E_POINTER;
972
973     libvlc_media_player_t *p_md;
974     HRESULT hr = getMD(&p_md);
975     if( SUCCEEDED(hr) )
976     {
977         libvlc_exception_t ex;
978         libvlc_exception_init(&ex);
979
980         *fullscreen = varbool( libvlc_get_fullscreen(p_md, &ex) );
981         hr = exception_bridge(&ex);
982     }
983     return hr;
984 };
985
986 STDMETHODIMP VLCVideo::put_fullscreen(VARIANT_BOOL fullscreen)
987 {
988     libvlc_media_player_t *p_md;
989     HRESULT hr = getMD(&p_md);
990     if( SUCCEEDED(hr) )
991     {
992         libvlc_exception_t ex;
993         libvlc_exception_init(&ex);
994
995         libvlc_set_fullscreen(p_md, VARIANT_FALSE != fullscreen, &ex);
996         hr = exception_bridge(&ex);
997     }
998     return hr;
999 };
1000
1001 STDMETHODIMP VLCVideo::get_width(long* width)
1002 {
1003     if( NULL == width )
1004         return E_POINTER;
1005
1006     libvlc_media_player_t *p_md;
1007     HRESULT hr = getMD(&p_md);
1008     if( SUCCEEDED(hr) )
1009     {
1010         libvlc_exception_t ex;
1011         libvlc_exception_init(&ex);
1012
1013         *width = libvlc_video_get_width(p_md, &ex);
1014         hr = exception_bridge(&ex);
1015     }
1016     return hr;
1017 };
1018
1019 STDMETHODIMP VLCVideo::get_height(long* height)
1020 {
1021     if( NULL == height )
1022         return E_POINTER;
1023
1024     libvlc_media_player_t *p_md;
1025     HRESULT hr = getMD(&p_md);
1026     if( SUCCEEDED(hr) )
1027     {
1028         libvlc_exception_t ex;
1029         libvlc_exception_init(&ex);
1030
1031         *height = libvlc_video_get_height(p_md, &ex);
1032         hr = exception_bridge(&ex);
1033     }
1034     return hr;
1035 };
1036
1037 STDMETHODIMP VLCVideo::get_aspectRatio(BSTR* aspect)
1038 {
1039     if( NULL == aspect )
1040         return E_POINTER;
1041
1042     libvlc_media_player_t *p_md;
1043     HRESULT hr = getMD(&p_md);
1044     if( SUCCEEDED(hr) )
1045     {
1046         libvlc_exception_t ex;
1047         libvlc_exception_init(&ex);
1048
1049         char *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1050
1051         hr = exception_bridge(&ex);
1052         if( SUCCEEDED(hr) && NULL != psz_aspect )
1053         {
1054             *aspect = BSTRFromCStr(CP_UTF8, psz_aspect);
1055             if( NULL == *aspect )
1056                 hr = E_OUTOFMEMORY;
1057         } else if( NULL == psz_aspect) hr = E_OUTOFMEMORY; // strdup("") failed
1058         free( psz_aspect );
1059     }
1060     return hr;
1061 };
1062
1063 STDMETHODIMP VLCVideo::put_aspectRatio(BSTR aspect)
1064 {
1065     if( NULL == aspect )
1066         return E_POINTER;
1067
1068     libvlc_media_player_t *p_md;
1069     HRESULT hr = getMD(&p_md);
1070     if( SUCCEEDED(hr) )
1071     {
1072         libvlc_exception_t ex;
1073         libvlc_exception_init(&ex);
1074
1075         char *psz_aspect = CStrFromBSTR(CP_UTF8, aspect);
1076         if( NULL == psz_aspect )
1077         {
1078             return E_OUTOFMEMORY;
1079         }
1080
1081         libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1082
1083         CoTaskMemFree(psz_aspect);
1084         hr = exception_bridge(&ex);
1085     }
1086     return hr;
1087 };
1088
1089 STDMETHODIMP VLCVideo::get_subtitle(long* spu)
1090 {
1091     if( NULL == spu )
1092         return E_POINTER;
1093
1094     libvlc_media_player_t *p_md;
1095     HRESULT hr = getMD(&p_md);
1096     if( SUCCEEDED(hr) )
1097     {
1098         libvlc_exception_t ex;
1099         libvlc_exception_init(&ex);
1100
1101         *spu = libvlc_video_get_spu(p_md, &ex);
1102         hr = exception_bridge(&ex);
1103     }
1104     return hr;
1105 };
1106
1107 STDMETHODIMP VLCVideo::put_subtitle(long spu)
1108 {
1109     libvlc_media_player_t *p_md;
1110     HRESULT hr = getMD(&p_md);
1111     if( SUCCEEDED(hr) )
1112     {
1113         libvlc_exception_t ex;
1114         libvlc_exception_init(&ex);
1115
1116         libvlc_video_set_spu(p_md, spu, &ex);
1117         hr = exception_bridge(&ex);
1118     }
1119     return hr;
1120 };
1121
1122 STDMETHODIMP VLCVideo::get_crop(BSTR* geometry)
1123 {
1124     if( NULL == geometry )
1125         return E_POINTER;
1126
1127     libvlc_media_player_t *p_md;
1128     HRESULT hr = getMD(&p_md);
1129     if( SUCCEEDED(hr) )
1130     {
1131         libvlc_exception_t ex;
1132         libvlc_exception_init(&ex);
1133
1134         char *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1135
1136         hr = exception_bridge(&ex);
1137         if( SUCCEEDED(&ex) && NULL != psz_geometry )
1138         {
1139             *geometry = BSTRFromCStr(CP_UTF8, psz_geometry);
1140             if( NULL == geometry ) hr = E_OUTOFMEMORY;
1141         } else if( NULL == psz_geometry ) hr = E_OUTOFMEMORY;
1142         free( psz_geometry );
1143     }
1144     return hr;
1145 };
1146
1147 STDMETHODIMP VLCVideo::put_crop(BSTR geometry)
1148 {
1149     if( NULL == geometry )
1150         return E_POINTER;
1151
1152     if( 0 == SysStringLen(geometry) )
1153         return E_INVALIDARG;
1154
1155     libvlc_media_player_t *p_md;
1156     HRESULT hr = getMD(&p_md);
1157     if( SUCCEEDED(hr) )
1158     {
1159         libvlc_exception_t ex;
1160         libvlc_exception_init(&ex);
1161
1162         char *psz_geometry = CStrFromBSTR(CP_UTF8, geometry);
1163         if( NULL == psz_geometry )
1164         {
1165             return E_OUTOFMEMORY;
1166         }
1167
1168         libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
1169
1170         CoTaskMemFree(psz_geometry);
1171         hr = exception_bridge(&ex);
1172     }
1173     return hr;
1174 };
1175
1176 STDMETHODIMP VLCVideo::get_teletext(long* page)
1177 {
1178     if( NULL == page )
1179         return E_POINTER;
1180
1181     libvlc_media_player_t *p_md;
1182     HRESULT hr = getMD(&p_md);
1183 #if 0
1184     if( SUCCEEDED(hr) )
1185     {
1186         libvlc_exception_t ex;
1187         libvlc_exception_init(&ex);
1188
1189         *page = libvlc_video_get_teletext(p_md);
1190         hr = exception_bridge(&ex);
1191     }
1192 #endif
1193     return hr;
1194 };
1195
1196 STDMETHODIMP VLCVideo::put_teletext(long page)
1197 {
1198 #warning Broken
1199     libvlc_media_player_t *p_md;
1200     HRESULT hr = getMD(&p_md);
1201 #if 0
1202     if( SUCCEEDED(hr) )
1203     {
1204         libvlc_exception_t ex;
1205         libvlc_exception_init(&ex);
1206
1207         libvlc_video_set_teletext(p_md, page);
1208         hr = exception_bridge(&ex);
1209     }
1210 #endif
1211     return hr;
1212 };
1213
1214 STDMETHODIMP VLCVideo::takeSnapshot(LPPICTUREDISP* picture)
1215 {
1216     if( NULL == picture )
1217         return E_POINTER;
1218
1219     libvlc_media_player_t *p_md;
1220     HRESULT hr = getMD(&p_md);
1221     if( SUCCEEDED(hr) )
1222     {
1223         libvlc_exception_t ex;
1224         libvlc_exception_init(&ex);
1225
1226         static int uniqueId = 0;
1227         TCHAR path[MAX_PATH+1];
1228
1229         int pathlen = GetTempPath(MAX_PATH-24, path);
1230         if( (0 == pathlen) || (pathlen > (MAX_PATH-24)) )
1231             return E_FAIL;
1232
1233         /* check temp directory path by openning it */
1234         {
1235             HANDLE dirHandle = CreateFile(path, GENERIC_READ,
1236                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
1237                        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1238             if( INVALID_HANDLE_VALUE == dirHandle )
1239             {
1240                 Instance()->setErrorInfo(IID_IVLCVideo,
1241                         "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
1242                 return E_FAIL;
1243             }
1244             else
1245             {
1246                 BY_HANDLE_FILE_INFORMATION bhfi;
1247                 BOOL res = GetFileInformationByHandle(dirHandle, &bhfi);
1248                 CloseHandle(dirHandle);
1249                 if( !res || !(bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
1250                 {
1251                     Instance()->setErrorInfo(IID_IVLCVideo,
1252                             "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
1253                     return E_FAIL;
1254                 }
1255             }
1256         }
1257
1258         TCHAR filepath[MAX_PATH+1];
1259
1260         _stprintf(filepath, TEXT("%sAXVLC%lXS%lX.bmp"),
1261                  path, GetCurrentProcessId(), ++uniqueId);
1262
1263 #ifdef _UNICODE
1264         /* reuse path storage for UTF8 string */
1265         char *psz_filepath = (char *)path;
1266         WCHAR* wpath = filepath;
1267 #else
1268         char *psz_filepath = path;
1269         /* first convert to unicode using current code page */
1270         WCHAR wpath[MAX_PATH+1];
1271         if( 0 == MultiByteToWideChar(CP_ACP, 0, filepath, -1,
1272                                      wpath, sizeof(wpath)/sizeof(WCHAR)) )
1273             return E_FAIL;
1274 #endif
1275         /* convert to UTF8 */
1276         pathlen = WideCharToMultiByte(CP_UTF8, 0, wpath, -1,
1277                                       psz_filepath, sizeof(path), NULL, NULL);
1278         // fail if path is 0 or too short (i.e pathlen is the same as
1279         // storage size)
1280
1281         if( (0 == pathlen) || (sizeof(path) == pathlen) )
1282             return E_FAIL;
1283
1284         /* take snapshot into file */
1285         libvlc_video_take_snapshot(p_md, psz_filepath, 0, 0, &ex);
1286         hr = exception_bridge(&ex);
1287         if( SUCCEEDED(hr) )
1288         {
1289             /* open snapshot file */
1290             HANDLE snapPic = LoadImage(NULL, filepath, IMAGE_BITMAP, 0, 0,
1291                                        LR_CREATEDIBSECTION|LR_LOADFROMFILE);
1292             if( snapPic )
1293             {
1294                 PICTDESC snapDesc;
1295
1296                 snapDesc.cbSizeofstruct = sizeof(PICTDESC);
1297                 snapDesc.picType        = PICTYPE_BITMAP;
1298                 snapDesc.bmp.hbitmap    = (HBITMAP)snapPic;
1299                 snapDesc.bmp.hpal       = NULL;
1300
1301                 hr = OleCreatePictureIndirect(&snapDesc, IID_IPictureDisp,
1302                                               TRUE, (LPVOID*)picture);
1303                 if( FAILED(hr) )
1304                 {
1305                     *picture = NULL;
1306                     DeleteObject(snapPic);
1307                 }
1308             }
1309             DeleteFile(filepath);
1310         }
1311     }
1312     return hr;
1313 };
1314
1315 STDMETHODIMP VLCVideo::toggleFullscreen()
1316 {
1317     libvlc_media_player_t *p_md;
1318     HRESULT hr = getMD(&p_md);
1319     if( SUCCEEDED(hr) )
1320     {
1321         libvlc_exception_t ex;
1322         libvlc_exception_init(&ex);
1323
1324         libvlc_toggle_fullscreen(p_md, &ex);
1325         hr = exception_bridge(&ex);
1326     }
1327     return hr;
1328 };
1329
1330 STDMETHODIMP VLCVideo::toggleTeletext()
1331 {
1332     libvlc_media_player_t *p_md;
1333     HRESULT hr = getMD(&p_md);
1334     if( SUCCEEDED(hr) )
1335     {
1336         libvlc_exception_t ex;
1337         libvlc_exception_init(&ex);
1338
1339         libvlc_toggle_teletext(p_md, &ex);
1340         hr = exception_bridge(&ex);
1341     }
1342     return hr;
1343 };
1344
1345 STDMETHODIMP VLCVideo::get_marquee(IVLCMarquee** obj)
1346 {
1347     return object_get(obj,_p_vlcmarquee);
1348 }
1349
1350 STDMETHODIMP VLCVideo::get_logo(IVLCLogo** obj)
1351 {
1352     return object_get(obj,_p_vlclogo);
1353 }
1354
1355 STDMETHODIMP VLCVideo::get_deinterlace(IVLCDeinterlace** obj)
1356 {
1357     return object_get(obj,_p_vlcdeint);
1358 }
1359
1360
1361 /****************************************************************************/
1362
1363 HRESULT VLCLogo::do_put_int(unsigned idx, LONG val)
1364 {
1365     libvlc_media_player_t *p_md;
1366     HRESULT hr = getMD(&p_md);
1367     if( SUCCEEDED(hr) )
1368     {
1369         libvlc_exception_t ex;
1370         libvlc_exception_init(&ex);
1371         libvlc_video_set_logo_int(p_md, idx, val, &ex);
1372         hr = exception_bridge(&ex);
1373     }
1374     return hr;
1375 }
1376
1377 HRESULT VLCLogo::do_get_int(unsigned idx, LONG *val)
1378 {
1379     if( NULL == val )
1380         return E_POINTER;
1381
1382     libvlc_media_player_t *p_md;
1383     HRESULT hr = getMD(&p_md);
1384     if( SUCCEEDED(hr) )
1385     {
1386         libvlc_exception_t ex;
1387         libvlc_exception_init(&ex);
1388         *val = libvlc_video_get_logo_int(p_md, idx, &ex);
1389         hr = exception_bridge(&ex);
1390     }
1391     return hr;
1392 }
1393
1394 STDMETHODIMP VLCLogo::file(BSTR fname)
1395 {
1396     libvlc_media_player_t *p_md;
1397     HRESULT hr = getMD(&p_md);
1398
1399     char *n = CStrFromBSTR(CP_UTF8, fname);
1400     if( !n ) hr = E_OUTOFMEMORY;
1401
1402     if( SUCCEEDED(hr) )
1403     {
1404         libvlc_exception_t ex;
1405         libvlc_exception_init(&ex);
1406         libvlc_video_set_logo_string(p_md, libvlc_logo_file, n, &ex);
1407         hr = exception_bridge(&ex);
1408     }
1409
1410     CoTaskMemFree(n);
1411     return hr;
1412 }
1413
1414 STDMETHODIMP VLCLogo::get_position(BSTR* val)
1415 {
1416     if( NULL == val )
1417         return E_POINTER;
1418
1419     LONG i;
1420     HRESULT hr = do_get_int(libvlc_logo_position, &i);
1421
1422     if(SUCCEEDED(hr))
1423         *val = BSTRFromCStr(CP_UTF8, position_bynumber(i));
1424
1425     return hr;
1426 }
1427
1428 STDMETHODIMP VLCLogo::put_position(BSTR val)
1429 {
1430     char *n = CStrFromBSTR(CP_UTF8, val);
1431     if( !n ) return E_OUTOFMEMORY;
1432
1433     size_t i;
1434     HRESULT hr;
1435     if( position_byname( n, i ) )
1436         hr = do_put_int(libvlc_logo_position,i);
1437     else
1438         hr = E_INVALIDARG;
1439
1440     CoTaskMemFree(n);
1441     return hr;
1442 }
1443
1444 /****************************************************************************/
1445
1446 VLCControl2::VLCControl2(VLCPlugin *p_instance) :
1447     _p_instance(p_instance),
1448     _p_typeinfo(NULL),
1449     _p_vlcaudio(new VLCAudio(p_instance)),
1450     _p_vlcinput(new VLCInput(p_instance)),
1451     _p_vlcplaylist(new VLCPlaylist(p_instance)),
1452     _p_vlcsubtitle(new VLCSubtitle(p_instance)),
1453     _p_vlcvideo(new VLCVideo(p_instance))
1454 {
1455 }
1456
1457 VLCControl2::~VLCControl2()
1458 {
1459     delete _p_vlcvideo;
1460     delete _p_vlcsubtitle;
1461     delete _p_vlcplaylist;
1462     delete _p_vlcinput;
1463     delete _p_vlcaudio;
1464     if( _p_typeinfo )
1465         _p_typeinfo->Release();
1466 };
1467
1468 HRESULT VLCControl2::loadTypeInfo(void)
1469 {
1470     HRESULT hr = NOERROR;
1471     if( NULL == _p_typeinfo )
1472     {
1473         ITypeLib *p_typelib;
1474
1475         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1476         if( SUCCEEDED(hr) )
1477         {
1478             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl2, &_p_typeinfo);
1479             if( FAILED(hr) )
1480             {
1481                 _p_typeinfo = NULL;
1482             }
1483             p_typelib->Release();
1484         }
1485     }
1486     return hr;
1487 };
1488
1489 STDMETHODIMP VLCControl2::GetTypeInfoCount(UINT* pctInfo)
1490 {
1491     if( NULL == pctInfo )
1492         return E_INVALIDARG;
1493
1494     if( SUCCEEDED(loadTypeInfo()) )
1495         *pctInfo = 1;
1496     else
1497         *pctInfo = 0;
1498
1499     return NOERROR;
1500 };
1501
1502 STDMETHODIMP VLCControl2::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1503 {
1504     if( NULL == ppTInfo )
1505         return E_INVALIDARG;
1506
1507     if( SUCCEEDED(loadTypeInfo()) )
1508     {
1509         _p_typeinfo->AddRef();
1510         *ppTInfo = _p_typeinfo;
1511         return NOERROR;
1512     }
1513     *ppTInfo = NULL;
1514     return E_NOTIMPL;
1515 };
1516
1517 STDMETHODIMP VLCControl2::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1518         UINT cNames, LCID lcid, DISPID* rgDispID)
1519 {
1520     if( SUCCEEDED(loadTypeInfo()) )
1521     {
1522         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1523     }
1524     return E_NOTIMPL;
1525 };
1526
1527 STDMETHODIMP VLCControl2::Invoke(DISPID dispIdMember, REFIID riid,
1528         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1529         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1530 {
1531     if( SUCCEEDED(loadTypeInfo()) )
1532     {
1533         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1534                 pVarResult, pExcepInfo, puArgErr);
1535     }
1536     return E_NOTIMPL;
1537 };
1538
1539 STDMETHODIMP VLCControl2::get_AutoLoop(VARIANT_BOOL *autoloop)
1540 {
1541     if( NULL == autoloop )
1542         return E_POINTER;
1543
1544     *autoloop = varbool( _p_instance->getAutoLoop() );
1545     return S_OK;
1546 };
1547
1548 STDMETHODIMP VLCControl2::put_AutoLoop(VARIANT_BOOL autoloop)
1549 {
1550     _p_instance->setAutoLoop((VARIANT_FALSE != autoloop) ? TRUE: FALSE);
1551     return S_OK;
1552 };
1553
1554 STDMETHODIMP VLCControl2::get_AutoPlay(VARIANT_BOOL *autoplay)
1555 {
1556     if( NULL == autoplay )
1557         return E_POINTER;
1558
1559     *autoplay = varbool( _p_instance->getAutoPlay() );
1560     return S_OK;
1561 };
1562
1563 STDMETHODIMP VLCControl2::put_AutoPlay(VARIANT_BOOL autoplay)
1564 {
1565     _p_instance->setAutoPlay((VARIANT_FALSE != autoplay) ? TRUE: FALSE);
1566     return S_OK;
1567 };
1568
1569 STDMETHODIMP VLCControl2::get_BaseURL(BSTR *url)
1570 {
1571     if( NULL == url )
1572         return E_POINTER;
1573
1574     *url = SysAllocStringLen(_p_instance->getBaseURL(),
1575                 SysStringLen(_p_instance->getBaseURL()));
1576     return NOERROR;
1577 };
1578
1579 STDMETHODIMP VLCControl2::put_BaseURL(BSTR mrl)
1580 {
1581     _p_instance->setBaseURL(mrl);
1582
1583     return S_OK;
1584 };
1585
1586 STDMETHODIMP VLCControl2::get_MRL(BSTR *mrl)
1587 {
1588     if( NULL == mrl )
1589         return E_POINTER;
1590
1591     *mrl = SysAllocStringLen(_p_instance->getMRL(),
1592                 SysStringLen(_p_instance->getMRL()));
1593     return NOERROR;
1594 };
1595
1596 STDMETHODIMP VLCControl2::put_MRL(BSTR mrl)
1597 {
1598     _p_instance->setMRL(mrl);
1599
1600     return S_OK;
1601 };
1602
1603
1604 STDMETHODIMP VLCControl2::get_Toolbar(VARIANT_BOOL *visible)
1605 {
1606     if( NULL == visible )
1607         return E_POINTER;
1608
1609     /*
1610      * Note to developers
1611      *
1612      * Returning the _b_toolbar is closer to the method specification.
1613      * But returning True when toolbar is not implemented so not displayed
1614      * could be bad for ActiveX users which rely on this value to show their
1615      * own toolbar if not provided by the ActiveX.
1616      *
1617      * This is the reason why FALSE is returned, until toolbar get implemented.
1618      */
1619
1620     /* DISABLED for now */
1621     //  *visible = varbool( _p_instance->getShowToolbar() );
1622
1623     *visible = VARIANT_FALSE;
1624
1625     return S_OK;
1626 };
1627
1628 STDMETHODIMP VLCControl2::put_Toolbar(VARIANT_BOOL visible)
1629 {
1630     _p_instance->setShowToolbar((VARIANT_FALSE != visible) ? TRUE: FALSE);
1631     return S_OK;
1632 };
1633
1634
1635 STDMETHODIMP VLCControl2::get_StartTime(long *seconds)
1636 {
1637     if( NULL == seconds )
1638         return E_POINTER;
1639
1640     *seconds = _p_instance->getStartTime();
1641
1642     return S_OK;
1643 };
1644
1645 STDMETHODIMP VLCControl2::put_StartTime(long seconds)
1646 {
1647     _p_instance->setStartTime(seconds);
1648
1649     return NOERROR;
1650 };
1651
1652 STDMETHODIMP VLCControl2::get_VersionInfo(BSTR *version)
1653 {
1654     if( NULL == version )
1655         return E_POINTER;
1656
1657     const char *versionStr = libvlc_get_version();
1658     if( NULL != versionStr )
1659     {
1660         *version = BSTRFromCStr(CP_UTF8, versionStr);
1661
1662         return (NULL == *version) ? E_OUTOFMEMORY : NOERROR;
1663     }
1664     *version = NULL;
1665     return E_FAIL;
1666 };
1667
1668 STDMETHODIMP VLCControl2::get_Visible(VARIANT_BOOL *isVisible)
1669 {
1670     if( NULL == isVisible )
1671         return E_POINTER;
1672
1673     *isVisible = varbool( _p_instance->getVisible() );
1674
1675     return NOERROR;
1676 };
1677
1678 STDMETHODIMP VLCControl2::put_Visible(VARIANT_BOOL isVisible)
1679 {
1680     _p_instance->setVisible(isVisible != VARIANT_FALSE);
1681
1682     return NOERROR;
1683 };
1684
1685 STDMETHODIMP VLCControl2::get_Volume(long *volume)
1686 {
1687     if( NULL == volume )
1688         return E_POINTER;
1689
1690     *volume  = _p_instance->getVolume();
1691     return NOERROR;
1692 };
1693
1694 STDMETHODIMP VLCControl2::put_Volume(long volume)
1695 {
1696     _p_instance->setVolume(volume);
1697     return NOERROR;
1698 };
1699
1700 STDMETHODIMP VLCControl2::get_BackColor(OLE_COLOR *backcolor)
1701 {
1702     if( NULL == backcolor )
1703         return E_POINTER;
1704
1705     *backcolor  = _p_instance->getBackColor();
1706     return NOERROR;
1707 };
1708
1709 STDMETHODIMP VLCControl2::put_BackColor(OLE_COLOR backcolor)
1710 {
1711     _p_instance->setBackColor(backcolor);
1712     return NOERROR;
1713 };
1714
1715 STDMETHODIMP VLCControl2::get_audio(IVLCAudio** obj)
1716 {
1717     return object_get(obj,_p_vlcaudio);
1718 }
1719
1720 STDMETHODIMP VLCControl2::get_input(IVLCInput** obj)
1721 {
1722     return object_get(obj,_p_vlcinput);
1723 }
1724
1725 STDMETHODIMP VLCControl2::get_playlist(IVLCPlaylist** obj)
1726 {
1727     return object_get(obj,_p_vlcplaylist);
1728 }
1729
1730 STDMETHODIMP VLCControl2::get_subtitle(IVLCSubtitle** obj)
1731 {
1732     return object_get(obj,_p_vlcsubtitle);
1733 }
1734
1735 STDMETHODIMP VLCControl2::get_video(IVLCVideo** obj)
1736 {
1737     return object_get(obj,_p_vlcvideo);
1738 }