]> git.sesse.net Git - vlc/blob - projects/activex/vlccontrol2.cpp
f4d639e400925d52c69e6c3ca34b5ebedc84e29b
[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
36 static inline
37 HRESULT _exception_bridge(VLCPlugin *p,REFIID riid, libvlc_exception_t *ex)
38 {
39     if( libvlc_exception_raised(ex) )
40     {
41         p->setErrorInfo(riid,libvlc_errmsg());
42         libvlc_exception_clear(ex);
43         return E_FAIL;
44     }
45     return NOERROR;
46 }
47
48 #define EMIT_EXCEPTION_BRIDGE( classname ) \
49     HRESULT classname::exception_bridge( libvlc_exception_t *ex ) \
50     { return _exception_bridge( _p_instance, IID_I##classname, ex ); }
51
52 EMIT_EXCEPTION_BRIDGE( VLCAudio )
53 EMIT_EXCEPTION_BRIDGE( VLCInput )
54 EMIT_EXCEPTION_BRIDGE( VLCMarquee )
55 EMIT_EXCEPTION_BRIDGE( VLCMessageIterator )
56 EMIT_EXCEPTION_BRIDGE( VLCMessages )
57 EMIT_EXCEPTION_BRIDGE( VLCLog )
58 EMIT_EXCEPTION_BRIDGE( VLCLogo )
59 EMIT_EXCEPTION_BRIDGE( VLCPlaylistItems )
60 EMIT_EXCEPTION_BRIDGE( VLCPlaylist )
61 EMIT_EXCEPTION_BRIDGE( VLCVideo )
62 EMIT_EXCEPTION_BRIDGE( VLCSubtitle )
63
64 #undef  EMIT_EXCEPTION_BRIDGE
65
66
67 VLCAudio::~VLCAudio()
68 {
69     if( _p_typeinfo )
70         _p_typeinfo->Release();
71 };
72
73 HRESULT VLCAudio::loadTypeInfo(void)
74 {
75     HRESULT hr = NOERROR;
76     if( NULL == _p_typeinfo )
77     {
78         ITypeLib *p_typelib;
79
80         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
81         if( SUCCEEDED(hr) )
82         {
83             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCAudio, &_p_typeinfo);
84             if( FAILED(hr) )
85             {
86                 _p_typeinfo = NULL;
87             }
88             p_typelib->Release();
89         }
90     }
91     return hr;
92 };
93
94 STDMETHODIMP VLCAudio::GetTypeInfoCount(UINT* pctInfo)
95 {
96     if( NULL == pctInfo )
97         return E_INVALIDARG;
98
99     if( SUCCEEDED(loadTypeInfo()) )
100         *pctInfo = 1;
101     else
102         *pctInfo = 0;
103
104     return NOERROR;
105 };
106
107 STDMETHODIMP VLCAudio::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
108 {
109     if( NULL == ppTInfo )
110         return E_INVALIDARG;
111
112     if( SUCCEEDED(loadTypeInfo()) )
113     {
114         _p_typeinfo->AddRef();
115         *ppTInfo = _p_typeinfo;
116         return NOERROR;
117     }
118     *ppTInfo = NULL;
119     return E_NOTIMPL;
120 };
121
122 STDMETHODIMP VLCAudio::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
123         UINT cNames, LCID lcid, DISPID* rgDispID)
124 {
125     if( SUCCEEDED(loadTypeInfo()) )
126     {
127         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
128     }
129     return E_NOTIMPL;
130 };
131
132 STDMETHODIMP VLCAudio::Invoke(DISPID dispIdMember, REFIID riid,
133         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
134         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
135 {
136     if( SUCCEEDED(loadTypeInfo()) )
137     {
138         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
139                 pVarResult, pExcepInfo, puArgErr);
140     }
141     return E_NOTIMPL;
142 };
143
144 STDMETHODIMP VLCAudio::get_mute(VARIANT_BOOL* mute)
145 {
146     if( NULL == mute )
147         return E_POINTER;
148
149     libvlc_instance_t* p_libvlc;
150     HRESULT hr = _p_instance->getVLC(&p_libvlc);
151     if( SUCCEEDED(hr) )
152         *mute = libvlc_audio_get_mute(p_libvlc) ?
153                         VARIANT_TRUE : VARIANT_FALSE;
154     return hr;
155 };
156
157 STDMETHODIMP VLCAudio::put_mute(VARIANT_BOOL mute)
158 {
159     libvlc_instance_t* p_libvlc;
160     HRESULT hr = _p_instance->getVLC(&p_libvlc);
161     if( SUCCEEDED(hr) )
162         libvlc_audio_set_mute(p_libvlc, VARIANT_FALSE != mute);
163     return hr;
164 };
165
166 STDMETHODIMP VLCAudio::get_volume(long* volume)
167 {
168     if( NULL == volume )
169         return E_POINTER;
170
171     libvlc_instance_t* p_libvlc;
172     HRESULT hr = _p_instance->getVLC(&p_libvlc);
173     if( SUCCEEDED(hr) )
174         *volume = libvlc_audio_get_volume(p_libvlc);
175     return hr;
176 };
177
178 STDMETHODIMP VLCAudio::put_volume(long volume)
179 {
180     libvlc_instance_t* p_libvlc;
181     HRESULT hr = _p_instance->getVLC(&p_libvlc);
182     if( SUCCEEDED(hr) )
183     {
184         libvlc_exception_t ex;
185         libvlc_exception_init(&ex);
186
187         libvlc_audio_set_volume(p_libvlc, volume, &ex);
188         hr = exception_bridge(&ex);
189     }
190     return hr;
191 };
192
193 STDMETHODIMP VLCAudio::get_track(long* track)
194 {
195     if( NULL == track )
196         return E_POINTER;
197
198     libvlc_media_player_t* p_md;
199     HRESULT hr = _p_instance->getMD(&p_md);
200     if( SUCCEEDED(hr) )
201     {
202         libvlc_exception_t ex;
203         libvlc_exception_init(&ex);
204
205         *track = libvlc_audio_get_track(p_md, &ex);
206         hr = exception_bridge(&ex);
207     }
208     return hr;
209 };
210
211 STDMETHODIMP VLCAudio::put_track(long track)
212 {
213     libvlc_media_player_t *p_md;
214     HRESULT hr = _p_instance->getMD(&p_md);
215     if( SUCCEEDED(hr) )
216     {
217         libvlc_exception_t ex;
218         libvlc_exception_init(&ex);
219
220         libvlc_audio_set_track(p_md, track, &ex);
221         hr = exception_bridge(&ex);
222     }
223     return hr;
224 };
225
226 STDMETHODIMP VLCAudio::get_count(long* trackNumber)
227 {
228     if( NULL == trackNumber )
229         return E_POINTER;
230
231     libvlc_media_player_t* p_md;
232     HRESULT hr = _p_instance->getMD(&p_md);
233     if( SUCCEEDED(hr) )
234     {
235         libvlc_exception_t ex;
236         libvlc_exception_init(&ex);
237         // get the number of audio track available and return it
238         *trackNumber = libvlc_audio_get_track_count(p_md, &ex);
239         hr = exception_bridge(&ex);
240     }
241     return hr;
242 };
243
244
245 STDMETHODIMP VLCAudio::description(long trackID, BSTR* name)
246 {
247     if( NULL == name )
248         return E_POINTER;
249
250     libvlc_media_player_t* p_md;
251     libvlc_exception_t ex;
252     libvlc_exception_init(&ex);
253
254     HRESULT hr = _p_instance->getMD(&p_md);
255     if( SUCCEEDED(hr) )
256     {
257         int i, i_limit;
258         const char *psz_name;
259         libvlc_track_description_t *p_trackDesc;
260
261         // get tracks description
262         p_trackDesc = libvlc_audio_get_track_description(p_md, &ex);
263         hr = exception_bridge(&ex);
264         if( FAILED(hr) )
265             return hr;
266
267         //get the number of available track
268         i_limit = libvlc_audio_get_track_count(p_md, &ex);
269         hr = exception_bridge(&ex);
270         if( FAILED(hr) )
271             return hr;
272
273         // check if the number given is a good one
274         if ( ( trackID > ( i_limit -1 ) ) || ( trackID < 0 ) )
275                 return E_FAIL;
276
277         // get the good trackDesc
278         for( i = 0 ; i < trackID ; i++ )
279         {
280             p_trackDesc = p_trackDesc->p_next;
281         }
282         // get the track name
283         psz_name = p_trackDesc->psz_name;
284
285         // return it
286         if( psz_name != NULL )
287         {
288             *name = BSTRFromCStr(CP_UTF8, psz_name);
289             return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
290         }
291         *name = NULL;
292         return E_FAIL;
293     }
294     return hr;
295 };
296
297 STDMETHODIMP VLCAudio::get_channel(long *channel)
298 {
299     if( NULL == channel )
300         return E_POINTER;
301
302     libvlc_instance_t* p_libvlc;
303     HRESULT hr = _p_instance->getVLC(&p_libvlc);
304     if( SUCCEEDED(hr) )
305     {
306         libvlc_exception_t ex;
307         libvlc_exception_init(&ex);
308
309         *channel = libvlc_audio_get_channel(p_libvlc, &ex);
310         hr = exception_bridge(&ex);
311     }
312     return hr;
313 };
314
315 STDMETHODIMP VLCAudio::put_channel(long channel)
316 {
317     libvlc_instance_t* p_libvlc;
318     HRESULT hr = _p_instance->getVLC(&p_libvlc);
319     if( SUCCEEDED(hr) )
320     {
321         libvlc_exception_t ex;
322         libvlc_exception_init(&ex);
323
324         libvlc_audio_set_channel(p_libvlc, channel, &ex);
325         hr = exception_bridge(&ex);
326     }
327     return hr;
328 };
329
330 STDMETHODIMP VLCAudio::toggleMute()
331 {
332     libvlc_instance_t* p_libvlc;
333     HRESULT hr = _p_instance->getVLC(&p_libvlc);
334     if( SUCCEEDED(hr) )
335         libvlc_audio_toggle_mute(p_libvlc);
336     return hr;
337 };
338
339 /****************************************************************************/
340
341 VLCInput::~VLCInput()
342 {
343     if( _p_typeinfo )
344         _p_typeinfo->Release();
345 };
346
347 HRESULT VLCInput::loadTypeInfo(void)
348 {
349     HRESULT hr = NOERROR;
350     if( NULL == _p_typeinfo )
351     {
352         ITypeLib *p_typelib;
353
354         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
355         if( SUCCEEDED(hr) )
356         {
357             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCInput, &_p_typeinfo);
358             if( FAILED(hr) )
359             {
360                 _p_typeinfo = NULL;
361             }
362             p_typelib->Release();
363         }
364     }
365     return hr;
366 };
367
368 STDMETHODIMP VLCInput::GetTypeInfoCount(UINT* pctInfo)
369 {
370     if( NULL == pctInfo )
371         return E_INVALIDARG;
372
373     if( SUCCEEDED(loadTypeInfo()) )
374         *pctInfo = 1;
375     else
376         *pctInfo = 0;
377
378     return NOERROR;
379 };
380
381 STDMETHODIMP VLCInput::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
382 {
383     if( NULL == ppTInfo )
384         return E_INVALIDARG;
385
386     if( SUCCEEDED(loadTypeInfo()) )
387     {
388         _p_typeinfo->AddRef();
389         *ppTInfo = _p_typeinfo;
390         return NOERROR;
391     }
392     *ppTInfo = NULL;
393     return E_NOTIMPL;
394 };
395
396 STDMETHODIMP VLCInput::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
397         UINT cNames, LCID lcid, DISPID* rgDispID)
398 {
399     if( SUCCEEDED(loadTypeInfo()) )
400     {
401         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
402     }
403     return E_NOTIMPL;
404 };
405
406 STDMETHODIMP VLCInput::Invoke(DISPID dispIdMember, REFIID riid,
407         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
408         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
409 {
410     if( SUCCEEDED(loadTypeInfo()) )
411     {
412         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
413                 pVarResult, pExcepInfo, puArgErr);
414     }
415     return E_NOTIMPL;
416 };
417
418 STDMETHODIMP VLCInput::get_length(double* length)
419 {
420     if( NULL == length )
421         return E_POINTER;
422     *length = 0;
423
424     libvlc_media_player_t *p_md;
425     HRESULT hr = _p_instance->getMD(&p_md);
426     if( SUCCEEDED(hr) )
427     {
428         libvlc_exception_t ex;
429         libvlc_exception_init(&ex);
430
431         *length = (double)libvlc_media_player_get_length(p_md, &ex);
432         hr = exception_bridge(&ex);
433     }
434     return hr;
435 };
436
437 STDMETHODIMP VLCInput::get_position(double* position)
438 {
439     if( NULL == position )
440         return E_POINTER;
441
442     *position = 0.0f;
443     libvlc_media_player_t *p_md;
444     HRESULT hr = _p_instance->getMD(&p_md);
445     if( SUCCEEDED(hr) )
446     {
447         libvlc_exception_t ex;
448         libvlc_exception_init(&ex);
449
450         *position = libvlc_media_player_get_position(p_md, &ex);
451         hr = exception_bridge(&ex);
452     }
453     return hr;
454 };
455
456 STDMETHODIMP VLCInput::put_position(double position)
457 {
458     libvlc_media_player_t *p_md;
459     HRESULT hr = _p_instance->getMD(&p_md);
460     if( SUCCEEDED(hr) )
461     {
462         libvlc_exception_t ex;
463         libvlc_exception_init(&ex);
464
465         libvlc_media_player_set_position(p_md, position, &ex);
466         hr = exception_bridge(&ex);
467     }
468     return hr;
469 };
470
471 STDMETHODIMP VLCInput::get_time(double* time)
472 {
473     if( NULL == time )
474         return E_POINTER;
475
476     libvlc_media_player_t *p_md;
477     HRESULT hr = _p_instance->getMD(&p_md);
478     if( SUCCEEDED(hr) )
479     {
480         libvlc_exception_t ex;
481         libvlc_exception_init(&ex);
482
483         *time = (double)libvlc_media_player_get_time(p_md, &ex);
484         hr = exception_bridge(&ex);
485     }
486     return hr;
487 };
488
489 STDMETHODIMP VLCInput::put_time(double time)
490 {
491     libvlc_media_player_t *p_md;
492     HRESULT hr = _p_instance->getMD(&p_md);
493     if( SUCCEEDED(hr) )
494     {
495         libvlc_exception_t ex;
496         libvlc_exception_init(&ex);
497
498         libvlc_media_player_set_time(p_md, (int64_t)time, &ex);
499         hr = exception_bridge(&ex);
500     }
501     return hr;
502 };
503
504 STDMETHODIMP VLCInput::get_state(long* state)
505 {
506     if( NULL == state )
507         return E_POINTER;
508
509     libvlc_media_player_t *p_md;
510     HRESULT hr = _p_instance->getMD(&p_md);
511     if( SUCCEEDED(hr) )
512     {
513         libvlc_exception_t ex;
514         libvlc_exception_init(&ex);
515
516         *state = libvlc_media_player_get_state(p_md, &ex);
517         if( libvlc_exception_raised(&ex) )
518         {
519             // don't fail, just return the idle state
520             *state = 0;
521             libvlc_exception_clear(&ex);
522         }
523     }
524     return hr;
525 };
526
527 STDMETHODIMP VLCInput::get_rate(double* rate)
528 {
529     if( NULL == rate )
530         return E_POINTER;
531
532     libvlc_media_player_t *p_md;
533     HRESULT hr = _p_instance->getMD(&p_md);
534     if( SUCCEEDED(hr) )
535     {
536         libvlc_exception_t ex;
537         libvlc_exception_init(&ex);
538
539         *rate = libvlc_media_player_get_rate(p_md, &ex);
540         hr = exception_bridge(&ex);
541     }
542     return hr;
543 };
544
545 STDMETHODIMP VLCInput::put_rate(double rate)
546 {
547     libvlc_media_player_t *p_md;
548     HRESULT hr = _p_instance->getMD(&p_md);
549     if( SUCCEEDED(hr) )
550     {
551         libvlc_exception_t ex;
552         libvlc_exception_init(&ex);
553
554         libvlc_media_player_set_rate(p_md, rate, &ex);
555         hr = exception_bridge(&ex);
556     }
557     return hr;
558 };
559
560 STDMETHODIMP VLCInput::get_fps(double* fps)
561 {
562     if( NULL == fps )
563         return E_POINTER;
564
565     *fps = 0.0;
566     libvlc_media_player_t *p_md;
567     HRESULT hr = _p_instance->getMD(&p_md);
568     if( SUCCEEDED(hr) )
569     {
570         libvlc_exception_t ex;
571         libvlc_exception_init(&ex);
572
573         *fps = libvlc_media_player_get_fps(p_md, &ex);
574         hr = exception_bridge(&ex);
575     }
576     return hr;
577 };
578
579 STDMETHODIMP VLCInput::get_hasVout(VARIANT_BOOL* hasVout)
580 {
581     if( NULL == hasVout )
582         return E_POINTER;
583
584     libvlc_media_player_t *p_md;
585     HRESULT hr = _p_instance->getMD(&p_md);
586     if( SUCCEEDED(hr) )
587     {
588         libvlc_exception_t ex;
589         libvlc_exception_init(&ex);
590
591         *hasVout = libvlc_media_player_has_vout(p_md, &ex) ?
592                                 VARIANT_TRUE : VARIANT_FALSE;
593         hr = exception_bridge(&ex);
594     }
595     return hr;
596 };
597
598 /****************************************************************************/
599
600 VLCLog::~VLCLog()
601 {
602     delete _p_vlcmessages;
603     if( _p_log )
604         libvlc_log_close(_p_log);
605
606     if( _p_typeinfo )
607         _p_typeinfo->Release();
608 };
609
610 HRESULT VLCLog::loadTypeInfo(void)
611 {
612     HRESULT hr = NOERROR;
613     if( NULL == _p_typeinfo )
614     {
615         ITypeLib *p_typelib;
616
617         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
618         if( SUCCEEDED(hr) )
619         {
620             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCLog, &_p_typeinfo);
621             if( FAILED(hr) )
622             {
623                 _p_typeinfo = NULL;
624             }
625             p_typelib->Release();
626         }
627     }
628     return hr;
629 };
630
631 STDMETHODIMP VLCLog::GetTypeInfoCount(UINT* pctInfo)
632 {
633     if( NULL == pctInfo )
634         return E_INVALIDARG;
635
636     if( SUCCEEDED(loadTypeInfo()) )
637         *pctInfo = 1;
638     else
639         *pctInfo = 0;
640
641     return NOERROR;
642 };
643
644 STDMETHODIMP VLCLog::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
645 {
646     if( NULL == ppTInfo )
647         return E_INVALIDARG;
648
649     if( SUCCEEDED(loadTypeInfo()) )
650     {
651         _p_typeinfo->AddRef();
652         *ppTInfo = _p_typeinfo;
653         return NOERROR;
654     }
655     *ppTInfo = NULL;
656     return E_NOTIMPL;
657 };
658
659 STDMETHODIMP VLCLog::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
660         UINT cNames, LCID lcid, DISPID* rgDispID)
661 {
662     if( SUCCEEDED(loadTypeInfo()) )
663     {
664         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
665     }
666     return E_NOTIMPL;
667 };
668
669 STDMETHODIMP VLCLog::Invoke(DISPID dispIdMember, REFIID riid,
670         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
671         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
672 {
673     if( SUCCEEDED(loadTypeInfo()) )
674     {
675         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
676                 pVarResult, pExcepInfo, puArgErr);
677     }
678     return E_NOTIMPL;
679 };
680
681 STDMETHODIMP VLCLog::get_messages(IVLCMessages** obj)
682 {
683     if( NULL == obj )
684         return E_POINTER;
685
686     *obj = _p_vlcmessages;
687     if( NULL != _p_vlcmessages )
688     {
689         _p_vlcmessages->AddRef();
690         return NOERROR;
691     }
692     return E_OUTOFMEMORY;
693 };
694
695 STDMETHODIMP VLCLog::get_verbosity(long* level)
696 {
697     if( NULL == level )
698         return E_POINTER;
699
700     if( _p_log )
701     {
702         libvlc_instance_t* p_libvlc;
703         HRESULT hr = _p_instance->getVLC(&p_libvlc);
704         if( SUCCEEDED(hr) )
705             *level = libvlc_get_log_verbosity(p_libvlc);
706         return hr;
707     }
708     else
709     {
710         /* log is not enabled, return -1 */
711         *level = -1;
712         return NOERROR;
713     }
714 };
715
716 STDMETHODIMP VLCLog::put_verbosity(long verbosity)
717 {
718     libvlc_instance_t* p_libvlc;
719     HRESULT hr = _p_instance->getVLC(&p_libvlc);
720     if( SUCCEEDED(hr) )
721     {
722         libvlc_exception_t ex;
723         libvlc_exception_init(&ex);
724
725         if( verbosity >= 0 )
726         {
727             if( ! _p_log )
728             {
729                 _p_log = libvlc_log_open(p_libvlc, &ex);
730                 hr = exception_bridge(&ex);
731             }
732             if( SUCCEEDED(hr) )
733                 libvlc_set_log_verbosity(p_libvlc, (unsigned)verbosity);
734         }
735         else if( _p_log )
736         {
737             /* close log  when verbosity is set to -1 */
738             libvlc_log_close(_p_log);
739             _p_log = NULL;
740         }
741         hr = exception_bridge(&ex);
742     }
743     return hr;
744 };
745
746 /****************************************************************************/
747
748 VLCMarquee::~VLCMarquee()
749 {
750     if( _p_typeinfo )
751         _p_typeinfo->Release();
752 };
753
754 HRESULT VLCMarquee::loadTypeInfo(void)
755 {
756     HRESULT hr = NOERROR;
757     if( NULL == _p_typeinfo )
758     {
759         ITypeLib *p_typelib;
760
761         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
762         if( SUCCEEDED(hr) )
763         {
764             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCMarquee, &_p_typeinfo);
765             if( FAILED(hr) )
766             {
767                 _p_typeinfo = NULL;
768             }
769             p_typelib->Release();
770         }
771     }
772     return hr;
773 };
774
775 STDMETHODIMP VLCMarquee::GetTypeInfoCount(UINT* pctInfo)
776 {
777     if( NULL == pctInfo )
778         return E_INVALIDARG;
779
780     if( SUCCEEDED(loadTypeInfo()) )
781         *pctInfo = 1;
782     else
783         *pctInfo = 0;
784
785     return NOERROR;
786 };
787
788 STDMETHODIMP VLCMarquee::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
789 {
790     if( NULL == ppTInfo )
791         return E_INVALIDARG;
792
793     if( SUCCEEDED(loadTypeInfo()) )
794     {
795         _p_typeinfo->AddRef();
796         *ppTInfo = _p_typeinfo;
797         return NOERROR;
798     }
799     *ppTInfo = NULL;
800     return E_NOTIMPL;
801 };
802
803 STDMETHODIMP VLCMarquee::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
804         UINT cNames, LCID lcid, DISPID* rgDispID)
805 {
806     if( SUCCEEDED(loadTypeInfo()) )
807     {
808         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
809     }
810     return E_NOTIMPL;
811 };
812
813 STDMETHODIMP VLCMarquee::Invoke(DISPID dispIdMember, REFIID riid,
814         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
815         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
816 {
817     if( SUCCEEDED(loadTypeInfo()) )
818     {
819         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
820                 pVarResult, pExcepInfo, puArgErr);
821     }
822     return E_NOTIMPL;
823 };
824
825 STDMETHODIMP VLCMarquee::enable()
826 {
827     libvlc_media_player_t *p_md;
828     HRESULT hr = _p_instance->getMD(&p_md);
829     if( SUCCEEDED(hr) )
830     {
831         libvlc_exception_t ex;
832         libvlc_exception_init(&ex);
833
834         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Enabled, true, &ex);
835         hr = exception_bridge(&ex);
836     }
837     return hr;
838 };
839
840 STDMETHODIMP VLCMarquee::disable()
841 {
842     libvlc_media_player_t *p_md;
843     HRESULT hr = _p_instance->getMD(&p_md);
844     if( SUCCEEDED(hr) )
845     {
846         libvlc_exception_t ex;
847         libvlc_exception_init(&ex);
848
849         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Enabled, false, &ex);
850         hr = exception_bridge(&ex);
851     }
852     return hr;
853 };
854
855 STDMETHODIMP VLCMarquee::color(long val)
856 {
857     libvlc_media_player_t *p_md;
858     HRESULT hr = _p_instance->getMD(&p_md);
859     if( SUCCEEDED(hr) )
860     {
861         libvlc_exception_t ex;
862         libvlc_exception_init(&ex);
863
864         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Color, val, &ex);
865         hr = exception_bridge(&ex);
866     }
867     return hr;
868 };
869
870 STDMETHODIMP VLCMarquee::opacity(long val)
871 {
872     libvlc_media_player_t *p_md;
873     HRESULT hr = _p_instance->getMD(&p_md);
874     if( SUCCEEDED(hr) )
875     {
876         libvlc_exception_t ex;
877         libvlc_exception_init(&ex);
878
879         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Opacity, val, &ex);
880         hr = exception_bridge(&ex);
881     }
882     return hr;
883 };
884
885 STDMETHODIMP VLCMarquee::position(long val)
886 {
887     libvlc_media_player_t *p_md;
888     HRESULT hr = _p_instance->getMD(&p_md);
889     if( SUCCEEDED(hr) )
890     {
891         libvlc_exception_t ex;
892         libvlc_exception_init(&ex);
893
894         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Position, val, &ex);
895         hr = exception_bridge(&ex);
896     }
897     return hr;
898 };
899
900 STDMETHODIMP VLCMarquee::refresh(long val)
901 {
902     libvlc_media_player_t *p_md;
903     HRESULT hr = _p_instance->getMD(&p_md);
904     if( SUCCEEDED(hr) )
905     {
906         libvlc_exception_t ex;
907         libvlc_exception_init(&ex);
908
909         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Refresh, val, &ex);
910         hr = exception_bridge(&ex);
911     }
912     return hr;
913 };
914
915 STDMETHODIMP VLCMarquee::size(long val)
916 {
917     libvlc_media_player_t *p_md;
918     HRESULT hr = _p_instance->getMD(&p_md);
919     if( SUCCEEDED(hr) )
920     {
921         libvlc_exception_t ex;
922         libvlc_exception_init(&ex);
923
924         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Size, val, &ex);
925         hr = exception_bridge(&ex);
926     }
927     return hr;
928 };
929
930 STDMETHODIMP VLCMarquee::text(BSTR text)
931 {
932     libvlc_media_player_t *p_md;
933     HRESULT hr = _p_instance->getMD(&p_md);
934     if( SUCCEEDED(hr) )
935     {
936         libvlc_exception_t ex;
937         libvlc_exception_init(&ex);
938
939         char *psz_text = CStrFromBSTR(CP_UTF8, text);
940         libvlc_video_set_marquee_option_as_string(p_md, libvlc_marquee_Text, psz_text, &ex);
941         hr = exception_bridge(&ex);
942         CoTaskMemFree(psz_text);
943     }
944     return hr;
945 };
946
947 STDMETHODIMP VLCMarquee::timeout(long val)
948 {
949     libvlc_media_player_t *p_md;
950     HRESULT hr = _p_instance->getMD(&p_md);
951     if( SUCCEEDED(hr) )
952     {
953         libvlc_exception_t ex;
954         libvlc_exception_init(&ex);
955
956         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Timeout, val, &ex);
957         hr = exception_bridge(&ex);
958     }
959     return hr;
960 };
961
962 STDMETHODIMP VLCMarquee::x(long val)
963 {
964     libvlc_media_player_t *p_md;
965     HRESULT hr = _p_instance->getMD(&p_md);
966     if( SUCCEEDED(hr) )
967     {
968         libvlc_exception_t ex;
969         libvlc_exception_init(&ex);
970
971         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_X, val, &ex);
972         hr = exception_bridge(&ex);
973     }
974     return hr;
975 };
976
977 STDMETHODIMP VLCMarquee::y(long val)
978 {
979     libvlc_media_player_t *p_md;
980     HRESULT hr = _p_instance->getMD(&p_md);
981     if( SUCCEEDED(hr) )
982     {
983         libvlc_exception_t ex;
984         libvlc_exception_init(&ex);
985
986         libvlc_video_set_marquee_option_as_int(p_md, libvlc_marquee_Y, val, &ex);
987         hr = exception_bridge(&ex);
988     }
989     return hr;
990 };
991
992 /****************************************************************************/
993
994 /* STL forward iterator used by VLCEnumIterator class to implement IEnumVARIANT */
995
996 class VLCMessageSTLIterator
997 {
998
999 public:
1000
1001     VLCMessageSTLIterator(IVLCMessageIterator* iter) : iter(iter), msg(NULL)
1002     {
1003         // get first message
1004         operator++();
1005     };
1006
1007     VLCMessageSTLIterator(const VLCMessageSTLIterator& other)
1008     {
1009         iter = other.iter;
1010         if( iter )
1011             iter->AddRef();
1012         msg = other.msg;
1013         if( msg )
1014             msg->AddRef();
1015     };
1016
1017     virtual ~VLCMessageSTLIterator()
1018     {
1019         if( msg )
1020             msg->Release();
1021
1022         if( iter )
1023             iter->Release();
1024     };
1025
1026     // we only need prefix ++ operator
1027     VLCMessageSTLIterator& operator++()
1028     {
1029         VARIANT_BOOL hasNext = VARIANT_FALSE;
1030         if( iter )
1031         {
1032             iter->get_hasNext(&hasNext);
1033
1034             if( msg )
1035             {
1036                 msg->Release();
1037                 msg = NULL;
1038             }
1039             if( VARIANT_TRUE == hasNext ) {
1040                 iter->next(&msg);
1041             }
1042         }
1043         return *this;
1044     };
1045
1046     VARIANT operator*() const
1047     {
1048         VARIANT v;
1049         VariantInit(&v);
1050         if( msg )
1051         {
1052             if( SUCCEEDED(msg->QueryInterface(IID_IDispatch,
1053                           (LPVOID*)&V_DISPATCH(&v))) )
1054             {
1055                 V_VT(&v) = VT_DISPATCH;
1056             }
1057         }
1058         return v;
1059     };
1060
1061     bool operator==(const VLCMessageSTLIterator& other) const
1062     {
1063         return msg == other.msg;
1064     };
1065
1066     bool operator!=(const VLCMessageSTLIterator& other) const
1067     {
1068         return msg != other.msg;
1069     };
1070
1071 private:
1072     IVLCMessageIterator* iter;
1073     IVLCMessage*         msg;
1074 };
1075
1076 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1077
1078 VLCMessages::~VLCMessages()
1079 {
1080     if( _p_typeinfo )
1081         _p_typeinfo->Release();
1082 };
1083
1084 HRESULT VLCMessages::loadTypeInfo(void)
1085 {
1086     HRESULT hr = NOERROR;
1087     if( NULL == _p_typeinfo )
1088     {
1089         ITypeLib *p_typelib;
1090
1091         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1092         if( SUCCEEDED(hr) )
1093         {
1094             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCMessages, &_p_typeinfo);
1095             if( FAILED(hr) )
1096             {
1097                 _p_typeinfo = NULL;
1098             }
1099             p_typelib->Release();
1100         }
1101     }
1102     return hr;
1103 };
1104
1105 STDMETHODIMP VLCMessages::GetTypeInfoCount(UINT* pctInfo)
1106 {
1107     if( NULL == pctInfo )
1108         return E_INVALIDARG;
1109
1110     if( SUCCEEDED(loadTypeInfo()) )
1111         *pctInfo = 1;
1112     else
1113         *pctInfo = 0;
1114
1115     return NOERROR;
1116 };
1117
1118 STDMETHODIMP VLCMessages::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1119 {
1120     if( NULL == ppTInfo )
1121         return E_INVALIDARG;
1122
1123     if( SUCCEEDED(loadTypeInfo()) )
1124     {
1125         _p_typeinfo->AddRef();
1126         *ppTInfo = _p_typeinfo;
1127         return NOERROR;
1128     }
1129     *ppTInfo = NULL;
1130     return E_NOTIMPL;
1131 };
1132
1133 STDMETHODIMP VLCMessages::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1134         UINT cNames, LCID lcid, DISPID* rgDispID)
1135 {
1136     if( SUCCEEDED(loadTypeInfo()) )
1137     {
1138         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1139     }
1140     return E_NOTIMPL;
1141 };
1142
1143 STDMETHODIMP VLCMessages::Invoke(DISPID dispIdMember, REFIID riid,
1144         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1145         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1146 {
1147     if( SUCCEEDED(loadTypeInfo()) )
1148     {
1149         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1150                 pVarResult, pExcepInfo, puArgErr);
1151     }
1152     return E_NOTIMPL;
1153 };
1154
1155 STDMETHODIMP VLCMessages::get__NewEnum(LPUNKNOWN* _NewEnum)
1156 {
1157     if( NULL == _NewEnum )
1158         return E_POINTER;
1159
1160     IVLCMessageIterator* iter = NULL;
1161     iterator(&iter);
1162
1163     *_NewEnum= new VLCEnumIterator<IID_IEnumVARIANT,
1164                        IEnumVARIANT,
1165                        VARIANT,
1166                        VLCMessageSTLIterator>
1167                        (VLCMessageSTLIterator(iter), VLCMessageSTLIterator(NULL));
1168
1169     return *_NewEnum ? S_OK : E_OUTOFMEMORY;
1170 };
1171
1172 STDMETHODIMP VLCMessages::clear()
1173 {
1174     libvlc_log_t *p_log = _p_vlclog->_p_log;
1175     if( p_log )
1176         libvlc_log_clear(p_log);
1177     return NOERROR;
1178 };
1179
1180 STDMETHODIMP VLCMessages::get_count(long* count)
1181 {
1182     if( NULL == count )
1183         return E_POINTER;
1184
1185     libvlc_log_t *p_log = _p_vlclog->_p_log;
1186     *count = libvlc_log_count(p_log);
1187     return S_OK;
1188 };
1189
1190 STDMETHODIMP VLCMessages::iterator(IVLCMessageIterator** iter)
1191 {
1192     if( NULL == iter )
1193         return E_POINTER;
1194
1195     *iter = new VLCMessageIterator(_p_instance, _p_vlclog);
1196
1197     return *iter ? S_OK : E_OUTOFMEMORY;
1198 };
1199
1200 /****************************************************************************/
1201
1202 VLCMessageIterator::VLCMessageIterator(VLCPlugin *p_instance, VLCLog* p_vlclog ) :
1203     _p_instance(p_instance),
1204     _p_typeinfo(NULL),
1205     _refcount(1),
1206     _p_vlclog(p_vlclog)
1207 {
1208     if( p_vlclog->_p_log )
1209     {
1210         _p_iter = libvlc_log_get_iterator(p_vlclog->_p_log, NULL);
1211     }
1212     else
1213         _p_iter = NULL;
1214 };
1215
1216 VLCMessageIterator::~VLCMessageIterator()
1217 {
1218     if( _p_iter )
1219         libvlc_log_iterator_free(_p_iter);
1220
1221     if( _p_typeinfo )
1222         _p_typeinfo->Release();
1223 };
1224
1225 HRESULT VLCMessageIterator::loadTypeInfo(void)
1226 {
1227     HRESULT hr = NOERROR;
1228     if( NULL == _p_typeinfo )
1229     {
1230         ITypeLib *p_typelib;
1231
1232         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1233         if( SUCCEEDED(hr) )
1234         {
1235             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCMessageIterator, &_p_typeinfo);
1236             if( FAILED(hr) )
1237             {
1238                 _p_typeinfo = NULL;
1239             }
1240             p_typelib->Release();
1241         }
1242     }
1243     return hr;
1244 };
1245
1246 STDMETHODIMP VLCMessageIterator::GetTypeInfoCount(UINT* pctInfo)
1247 {
1248     if( NULL == pctInfo )
1249         return E_INVALIDARG;
1250
1251     if( SUCCEEDED(loadTypeInfo()) )
1252         *pctInfo = 1;
1253     else
1254         *pctInfo = 0;
1255
1256     return NOERROR;
1257 };
1258
1259 STDMETHODIMP VLCMessageIterator::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1260 {
1261     if( NULL == ppTInfo )
1262         return E_INVALIDARG;
1263
1264     if( SUCCEEDED(loadTypeInfo()) )
1265     {
1266         _p_typeinfo->AddRef();
1267         *ppTInfo = _p_typeinfo;
1268         return NOERROR;
1269     }
1270     *ppTInfo = NULL;
1271     return E_NOTIMPL;
1272 };
1273
1274 STDMETHODIMP VLCMessageIterator::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1275         UINT cNames, LCID lcid, DISPID* rgDispID)
1276 {
1277     if( SUCCEEDED(loadTypeInfo()) )
1278     {
1279         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1280     }
1281     return E_NOTIMPL;
1282 };
1283
1284 STDMETHODIMP VLCMessageIterator::Invoke(DISPID dispIdMember, REFIID riid,
1285         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1286         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1287 {
1288     if( SUCCEEDED(loadTypeInfo()) )
1289     {
1290         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1291                 pVarResult, pExcepInfo, puArgErr);
1292     }
1293     return E_NOTIMPL;
1294 };
1295
1296 STDMETHODIMP VLCMessageIterator::get_hasNext(VARIANT_BOOL* hasNext)
1297 {
1298     if( NULL == hasNext )
1299         return E_POINTER;
1300
1301     if( _p_iter &&  _p_vlclog->_p_log )
1302     {
1303         *hasNext = libvlc_log_iterator_has_next(_p_iter) ?
1304                    VARIANT_TRUE : VARIANT_FALSE;
1305     }
1306     else
1307     {
1308         *hasNext = VARIANT_FALSE;
1309     }
1310     return S_OK;
1311 };
1312
1313 STDMETHODIMP VLCMessageIterator::next(IVLCMessage** message)
1314 {
1315     HRESULT hr = S_OK;
1316
1317     if( NULL == message )
1318         return E_POINTER;
1319
1320     if( _p_iter &&  _p_vlclog->_p_log )
1321     {
1322         struct libvlc_log_message_t buffer;
1323
1324         buffer.sizeof_msg = sizeof(buffer);
1325
1326         libvlc_exception_t ex;
1327         libvlc_exception_init(&ex);
1328
1329         libvlc_log_iterator_next(_p_iter, &buffer, &ex);
1330         *message = new VLCMessage(_p_instance, buffer);
1331         if( !message )
1332             hr = E_OUTOFMEMORY;
1333     }
1334     return hr;
1335 };
1336
1337 /****************************************************************************/
1338
1339 VLCMessage::~VLCMessage()
1340 {
1341     if( _p_typeinfo )
1342         _p_typeinfo->Release();
1343 };
1344
1345 HRESULT VLCMessage::loadTypeInfo(void)
1346 {
1347     HRESULT hr = NOERROR;
1348     if( NULL == _p_typeinfo )
1349     {
1350         ITypeLib *p_typelib;
1351
1352         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1353         if( SUCCEEDED(hr) )
1354         {
1355             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCMessage, &_p_typeinfo);
1356             if( FAILED(hr) )
1357             {
1358                 _p_typeinfo = NULL;
1359             }
1360             p_typelib->Release();
1361         }
1362     }
1363     return hr;
1364 };
1365
1366 STDMETHODIMP VLCMessage::GetTypeInfoCount(UINT* pctInfo)
1367 {
1368     if( NULL == pctInfo )
1369         return E_INVALIDARG;
1370
1371     if( SUCCEEDED(loadTypeInfo()) )
1372         *pctInfo = 1;
1373     else
1374         *pctInfo = 0;
1375
1376     return NOERROR;
1377 };
1378
1379 STDMETHODIMP VLCMessage::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1380 {
1381     if( NULL == ppTInfo )
1382         return E_INVALIDARG;
1383
1384     if( SUCCEEDED(loadTypeInfo()) )
1385     {
1386         _p_typeinfo->AddRef();
1387         *ppTInfo = _p_typeinfo;
1388         return NOERROR;
1389     }
1390     *ppTInfo = NULL;
1391     return E_NOTIMPL;
1392 };
1393
1394 STDMETHODIMP VLCMessage::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1395         UINT cNames, LCID lcid, DISPID* rgDispID)
1396 {
1397     if( SUCCEEDED(loadTypeInfo()) )
1398     {
1399         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1400     }
1401     return E_NOTIMPL;
1402 };
1403
1404 STDMETHODIMP VLCMessage::Invoke(DISPID dispIdMember, REFIID riid,
1405         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1406         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1407 {
1408     if( SUCCEEDED(loadTypeInfo()) )
1409     {
1410         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1411                 pVarResult, pExcepInfo, puArgErr);
1412     }
1413     return E_NOTIMPL;
1414 };
1415
1416 inline const char *msgSeverity(int sev)
1417 {
1418     switch( sev )
1419     {
1420         case 0:
1421             return "info";
1422         case 1:
1423             return "error";
1424         case 2:
1425             return "warning";
1426         default:
1427             return "debug";
1428     }
1429 };
1430
1431 STDMETHODIMP VLCMessage::get__Value(VARIANT* _Value)
1432 {
1433     if( NULL == _Value )
1434         return E_POINTER;
1435
1436     char buffer[256];
1437
1438     snprintf(buffer, sizeof(buffer), "%s %s %s: %s",
1439         _msg.psz_type, _msg.psz_name, msgSeverity(_msg.i_severity), _msg.psz_message);
1440
1441     V_VT(_Value) = VT_BSTR;
1442     V_BSTR(_Value) = BSTRFromCStr(CP_UTF8, buffer);
1443
1444     return S_OK;
1445 };
1446
1447 STDMETHODIMP VLCMessage::get_severity(long* level)
1448 {
1449     if( NULL == level )
1450         return E_POINTER;
1451
1452     *level = _msg.i_severity;
1453
1454     return S_OK;
1455 };
1456
1457 STDMETHODIMP VLCMessage::get_type(BSTR* type)
1458 {
1459     if( NULL == type )
1460         return E_POINTER;
1461
1462     *type = BSTRFromCStr(CP_UTF8, _msg.psz_type);
1463
1464     return NOERROR;
1465 };
1466
1467 STDMETHODIMP VLCMessage::get_name(BSTR* name)
1468 {
1469     if( NULL == name )
1470         return E_POINTER;
1471
1472     *name = BSTRFromCStr(CP_UTF8, _msg.psz_name);
1473
1474     return NOERROR;
1475 };
1476
1477 STDMETHODIMP VLCMessage::get_header(BSTR* header)
1478 {
1479     if( NULL == header )
1480         return E_POINTER;
1481
1482     *header = BSTRFromCStr(CP_UTF8, _msg.psz_header);
1483
1484     return NOERROR;
1485 };
1486
1487 STDMETHODIMP VLCMessage::get_message(BSTR* message)
1488 {
1489     if( NULL == message )
1490         return E_POINTER;
1491
1492     *message = BSTRFromCStr(CP_UTF8, _msg.psz_message);
1493
1494     return NOERROR;
1495 };
1496
1497 /****************************************************************************/
1498
1499 VLCPlaylistItems::~VLCPlaylistItems()
1500 {
1501     if( _p_typeinfo )
1502         _p_typeinfo->Release();
1503 };
1504
1505 HRESULT VLCPlaylistItems::loadTypeInfo(void)
1506 {
1507     HRESULT hr = NOERROR;
1508     if( NULL == _p_typeinfo )
1509     {
1510         ITypeLib *p_typelib;
1511
1512         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1513         if( SUCCEEDED(hr) )
1514         {
1515             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCPlaylistItems, &_p_typeinfo);
1516             if( FAILED(hr) )
1517             {
1518                 _p_typeinfo = NULL;
1519             }
1520             p_typelib->Release();
1521         }
1522     }
1523     return hr;
1524 };
1525
1526 STDMETHODIMP VLCPlaylistItems::GetTypeInfoCount(UINT* pctInfo)
1527 {
1528     if( NULL == pctInfo )
1529         return E_INVALIDARG;
1530
1531     if( SUCCEEDED(loadTypeInfo()) )
1532         *pctInfo = 1;
1533     else
1534         *pctInfo = 0;
1535
1536     return NOERROR;
1537 };
1538
1539 STDMETHODIMP VLCPlaylistItems::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1540 {
1541     if( NULL == ppTInfo )
1542         return E_INVALIDARG;
1543
1544     if( SUCCEEDED(loadTypeInfo()) )
1545     {
1546         _p_typeinfo->AddRef();
1547         *ppTInfo = _p_typeinfo;
1548         return NOERROR;
1549     }
1550     *ppTInfo = NULL;
1551     return E_NOTIMPL;
1552 };
1553
1554 STDMETHODIMP VLCPlaylistItems::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1555         UINT cNames, LCID lcid, DISPID* rgDispID)
1556 {
1557     if( SUCCEEDED(loadTypeInfo()) )
1558     {
1559         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1560     }
1561     return E_NOTIMPL;
1562 };
1563
1564 STDMETHODIMP VLCPlaylistItems::Invoke(DISPID dispIdMember, REFIID riid,
1565         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1566         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1567 {
1568     if( SUCCEEDED(loadTypeInfo()) )
1569     {
1570         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1571                 pVarResult, pExcepInfo, puArgErr);
1572     }
1573     return E_NOTIMPL;
1574 };
1575
1576 STDMETHODIMP VLCPlaylistItems::get_count(long* count)
1577 {
1578     if( NULL == count )
1579         return E_POINTER;
1580
1581     libvlc_exception_t ex;
1582     libvlc_exception_init(&ex);
1583
1584     *count = _p_instance->playlist_count(&ex);
1585     return exception_bridge(&ex);
1586 };
1587
1588 STDMETHODIMP VLCPlaylistItems::clear()
1589 {
1590     libvlc_exception_t ex;
1591     libvlc_exception_init(&ex);
1592
1593     _p_instance->playlist_clear(&ex);
1594     return exception_bridge(&ex);
1595 };
1596
1597 STDMETHODIMP VLCPlaylistItems::remove(long item)
1598 {
1599     libvlc_instance_t* p_libvlc;
1600     HRESULT hr = _p_instance->getVLC(&p_libvlc);
1601     if( SUCCEEDED(hr) )
1602     {
1603         libvlc_exception_t ex;
1604         libvlc_exception_init(&ex);
1605
1606         _p_instance->playlist_delete_item(item, &ex);
1607         hr = exception_bridge(&ex);
1608     }
1609     return hr;
1610 };
1611
1612 /****************************************************************************/
1613
1614 VLCPlaylist::~VLCPlaylist()
1615 {
1616     delete _p_vlcplaylistitems;
1617     if( _p_typeinfo )
1618         _p_typeinfo->Release();
1619 };
1620
1621 HRESULT VLCPlaylist::loadTypeInfo(void)
1622 {
1623     HRESULT hr = NOERROR;
1624     if( NULL == _p_typeinfo )
1625     {
1626         ITypeLib *p_typelib;
1627
1628         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1629         if( SUCCEEDED(hr) )
1630         {
1631             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCPlaylist, &_p_typeinfo);
1632             if( FAILED(hr) )
1633             {
1634                 _p_typeinfo = NULL;
1635             }
1636             p_typelib->Release();
1637         }
1638     }
1639     return hr;
1640 };
1641
1642 STDMETHODIMP VLCPlaylist::GetTypeInfoCount(UINT* pctInfo)
1643 {
1644     if( NULL == pctInfo )
1645         return E_INVALIDARG;
1646
1647     if( SUCCEEDED(loadTypeInfo()) )
1648         *pctInfo = 1;
1649     else
1650         *pctInfo = 0;
1651
1652     return NOERROR;
1653 };
1654
1655 STDMETHODIMP VLCPlaylist::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1656 {
1657     if( NULL == ppTInfo )
1658         return E_INVALIDARG;
1659
1660     if( SUCCEEDED(loadTypeInfo()) )
1661     {
1662         _p_typeinfo->AddRef();
1663         *ppTInfo = _p_typeinfo;
1664         return NOERROR;
1665     }
1666     *ppTInfo = NULL;
1667     return E_NOTIMPL;
1668 };
1669
1670 STDMETHODIMP VLCPlaylist::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1671         UINT cNames, LCID lcid, DISPID* rgDispID)
1672 {
1673     if( SUCCEEDED(loadTypeInfo()) )
1674     {
1675         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1676     }
1677     return E_NOTIMPL;
1678 };
1679
1680 STDMETHODIMP VLCPlaylist::Invoke(DISPID dispIdMember, REFIID riid,
1681         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1682         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1683 {
1684     if( SUCCEEDED(loadTypeInfo()) )
1685     {
1686         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1687                 pVarResult, pExcepInfo, puArgErr);
1688     }
1689     return E_NOTIMPL;
1690 };
1691
1692 STDMETHODIMP VLCPlaylist::get_itemCount(long* count)
1693 {
1694     if( NULL == count )
1695         return E_POINTER;
1696
1697     *count = 0;
1698     libvlc_exception_t ex;
1699     libvlc_exception_init(&ex);
1700
1701     *count = _p_instance->playlist_count(&ex);
1702     return exception_bridge(&ex);
1703 };
1704
1705 STDMETHODIMP VLCPlaylist::get_isPlaying(VARIANT_BOOL* isPlaying)
1706 {
1707     if( NULL == isPlaying )
1708         return E_POINTER;
1709
1710     libvlc_media_player_t *p_md;
1711     HRESULT hr = _p_instance->getMD(&p_md);
1712     if( SUCCEEDED(hr) )
1713     {
1714         libvlc_exception_t ex;
1715         libvlc_exception_init(&ex);
1716
1717         *isPlaying = libvlc_media_player_is_playing(p_md, &ex) ?
1718                      VARIANT_TRUE: VARIANT_FALSE;
1719         libvlc_exception_clear(&ex);
1720     }
1721     return hr;
1722 };
1723
1724 STDMETHODIMP VLCPlaylist::add(BSTR uri, VARIANT name, VARIANT options, long* item)
1725 {
1726     if( NULL == item )
1727         return E_POINTER;
1728
1729     if( 0 == SysStringLen(uri) )
1730         return E_INVALIDARG;
1731
1732     libvlc_instance_t* p_libvlc;
1733     HRESULT hr = _p_instance->getVLC(&p_libvlc);
1734     if( SUCCEEDED(hr) )
1735     {
1736         libvlc_exception_t ex;
1737         libvlc_exception_init(&ex);
1738
1739         char *psz_uri = NULL;
1740         if( SysStringLen(_p_instance->getBaseURL()) > 0 )
1741         {
1742             /*
1743             ** if the MRL a relative URL, we should end up with an absolute URL
1744             */
1745             LPWSTR abs_url = CombineURL(_p_instance->getBaseURL(), uri);
1746             if( NULL != abs_url )
1747             {
1748                 psz_uri = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
1749                 CoTaskMemFree(abs_url);
1750             }
1751             else
1752             {
1753                 psz_uri = CStrFromBSTR(CP_UTF8, uri);
1754             }
1755         }
1756         else
1757         {
1758             /*
1759             ** baseURL is empty, assume MRL is absolute
1760             */
1761             psz_uri = CStrFromBSTR(CP_UTF8, uri);
1762         }
1763
1764         if( NULL == psz_uri )
1765         {
1766             return E_OUTOFMEMORY;
1767         }
1768
1769         int i_options;
1770         char **ppsz_options;
1771
1772         hr = VLCControl::CreateTargetOptions(CP_UTF8, &options, &ppsz_options, &i_options);
1773         if( FAILED(hr) )
1774         {
1775             CoTaskMemFree(psz_uri);
1776             return hr;
1777         }
1778
1779         char *psz_name = NULL;
1780         VARIANT v_name;
1781         VariantInit(&v_name);
1782         if( SUCCEEDED(VariantChangeType(&v_name, &name, 0, VT_BSTR)) )
1783         {
1784             if( SysStringLen(V_BSTR(&v_name)) > 0 )
1785                 psz_name = CStrFromBSTR(CP_UTF8, V_BSTR(&v_name));
1786
1787             VariantClear(&v_name);
1788         }
1789
1790         *item = _p_instance->playlist_add_extended_untrusted(psz_uri,
1791                     i_options, const_cast<const char **>(ppsz_options), &ex);
1792
1793         VLCControl::FreeTargetOptions(ppsz_options, i_options);
1794         CoTaskMemFree(psz_uri);
1795         if( psz_name ) /* XXX Do we even need to check? */
1796             CoTaskMemFree(psz_name);
1797         hr = exception_bridge(&ex);
1798     }
1799     return hr;
1800 };
1801
1802 STDMETHODIMP VLCPlaylist::play()
1803 {
1804     libvlc_exception_t ex;
1805     libvlc_exception_init(&ex);
1806
1807     _p_instance->playlist_play(&ex);
1808     return exception_bridge(&ex);
1809 };
1810
1811 STDMETHODIMP VLCPlaylist::playItem(long item)
1812 {
1813     libvlc_exception_t ex;
1814     libvlc_exception_init(&ex);
1815
1816     _p_instance->playlist_play_item(item,&ex);
1817     return exception_bridge(&ex);;
1818 };
1819
1820 STDMETHODIMP VLCPlaylist::togglePause()
1821 {
1822     libvlc_media_player_t* p_md;
1823     HRESULT hr = _p_instance->getMD(&p_md);
1824     if( SUCCEEDED(hr) )
1825     {
1826         libvlc_exception_t ex;
1827         libvlc_exception_init(&ex);
1828
1829         libvlc_media_player_pause(p_md, &ex);
1830         hr = exception_bridge(&ex);;
1831     }
1832     return hr;
1833 };
1834
1835 STDMETHODIMP VLCPlaylist::stop()
1836 {
1837     libvlc_media_player_t *p_md;
1838     HRESULT hr = _p_instance->getMD(&p_md);
1839     if( SUCCEEDED(hr) )
1840     {
1841         libvlc_exception_t ex;
1842         libvlc_exception_init(&ex);
1843
1844         libvlc_media_player_stop(p_md, &ex);
1845         hr = exception_bridge(&ex);;
1846     }
1847     return hr;
1848 };
1849
1850 STDMETHODIMP VLCPlaylist::next()
1851 {
1852     libvlc_exception_t ex;
1853     libvlc_exception_init(&ex);
1854
1855     _p_instance->playlist_next(&ex);
1856     return exception_bridge(&ex);;
1857 };
1858
1859 STDMETHODIMP VLCPlaylist::prev()
1860 {
1861     libvlc_exception_t ex;
1862     libvlc_exception_init(&ex);
1863
1864     _p_instance->playlist_prev(&ex);
1865     return exception_bridge(&ex);;
1866 };
1867
1868 STDMETHODIMP VLCPlaylist::clear()
1869 {
1870     libvlc_exception_t ex;
1871     libvlc_exception_init(&ex);
1872
1873     _p_instance->playlist_clear(&ex);
1874     return exception_bridge(&ex);;
1875 };
1876
1877 STDMETHODIMP VLCPlaylist::removeItem(long item)
1878 {
1879     libvlc_instance_t* p_libvlc;
1880     HRESULT hr = _p_instance->getVLC(&p_libvlc);
1881     if( SUCCEEDED(hr) )
1882     {
1883         libvlc_exception_t ex;
1884         libvlc_exception_init(&ex);
1885
1886         _p_instance->playlist_delete_item(item, &ex);
1887         hr = exception_bridge(&ex);;
1888     }
1889     return hr;
1890 };
1891
1892 STDMETHODIMP VLCPlaylist::get_items(IVLCPlaylistItems** obj)
1893 {
1894     if( NULL == obj )
1895         return E_POINTER;
1896
1897     *obj = _p_vlcplaylistitems;
1898     if( NULL != _p_vlcplaylistitems )
1899     {
1900         _p_vlcplaylistitems->AddRef();
1901         return NOERROR;
1902     }
1903     return E_OUTOFMEMORY;
1904 };
1905
1906 /****************************************************************************/
1907
1908 VLCSubtitle::~VLCSubtitle()
1909 {
1910     if( _p_typeinfo )
1911         _p_typeinfo->Release();
1912 };
1913
1914 HRESULT VLCSubtitle::loadTypeInfo(void)
1915 {
1916     HRESULT hr = NOERROR;
1917     if( NULL == _p_typeinfo )
1918     {
1919         ITypeLib *p_typelib;
1920
1921         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1922         if( SUCCEEDED(hr) )
1923         {
1924             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCSubtitle, &_p_typeinfo);
1925             if( FAILED(hr) )
1926             {
1927                 _p_typeinfo = NULL;
1928             }
1929             p_typelib->Release();
1930         }
1931     }
1932     return hr;
1933 };
1934
1935 STDMETHODIMP VLCSubtitle::GetTypeInfoCount(UINT* pctInfo)
1936 {
1937     if( NULL == pctInfo )
1938         return E_INVALIDARG;
1939
1940     if( SUCCEEDED(loadTypeInfo()) )
1941         *pctInfo = 1;
1942     else
1943         *pctInfo = 0;
1944
1945     return NOERROR;
1946 };
1947
1948 STDMETHODIMP VLCSubtitle::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1949 {
1950     if( NULL == ppTInfo )
1951         return E_INVALIDARG;
1952
1953     if( SUCCEEDED(loadTypeInfo()) )
1954     {
1955         _p_typeinfo->AddRef();
1956         *ppTInfo = _p_typeinfo;
1957         return NOERROR;
1958     }
1959     *ppTInfo = NULL;
1960     return E_NOTIMPL;
1961 };
1962
1963 STDMETHODIMP VLCSubtitle::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1964         UINT cNames, LCID lcid, DISPID* rgDispID)
1965 {
1966     if( SUCCEEDED(loadTypeInfo()) )
1967     {
1968         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1969     }
1970     return E_NOTIMPL;
1971 };
1972
1973 STDMETHODIMP VLCSubtitle::Invoke(DISPID dispIdMember, REFIID riid,
1974         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1975         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1976 {
1977     if( SUCCEEDED(loadTypeInfo()) )
1978     {
1979         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1980                 pVarResult, pExcepInfo, puArgErr);
1981     }
1982     return E_NOTIMPL;
1983 };
1984
1985 STDMETHODIMP VLCSubtitle::get_track(long* spu)
1986 {
1987     if( NULL == spu )
1988         return E_POINTER;
1989
1990     libvlc_media_player_t *p_md;
1991     HRESULT hr = _p_instance->getMD(&p_md);
1992     if( SUCCEEDED(hr) )
1993     {
1994         libvlc_exception_t ex;
1995         libvlc_exception_init(&ex);
1996
1997         *spu = libvlc_video_get_spu(p_md, &ex);
1998         hr = exception_bridge(&ex);
1999     }
2000     return hr;
2001 };
2002
2003 STDMETHODIMP VLCSubtitle::put_track(long spu)
2004 {
2005     libvlc_media_player_t *p_md;
2006     HRESULT hr = _p_instance->getMD(&p_md);
2007     if( SUCCEEDED(hr) )
2008     {
2009         libvlc_exception_t ex;
2010         libvlc_exception_init(&ex);
2011
2012         libvlc_video_set_spu(p_md, spu, &ex);
2013         hr = exception_bridge(&ex);
2014     }
2015     return hr;
2016 };
2017
2018 STDMETHODIMP VLCSubtitle::get_count(long* spuNumber)
2019 {
2020     if( NULL == spuNumber )
2021         return E_POINTER;
2022
2023     libvlc_media_player_t *p_md;
2024     HRESULT hr = _p_instance->getMD(&p_md);
2025     if( SUCCEEDED(hr) )
2026     {
2027         libvlc_exception_t ex;
2028         libvlc_exception_init(&ex);
2029         // get the number of video subtitle available and return it
2030         *spuNumber = libvlc_video_get_spu_count(p_md, &ex);
2031         hr = exception_bridge(&ex);
2032     }
2033     return hr;
2034 };
2035
2036
2037 STDMETHODIMP VLCSubtitle::description(long nameID, BSTR* name)
2038 {
2039     if( NULL == name )
2040        return E_POINTER;
2041
2042     libvlc_media_player_t* p_md;
2043     libvlc_exception_t ex;
2044     libvlc_exception_init(&ex);
2045
2046     HRESULT hr = _p_instance->getMD(&p_md);
2047     if( SUCCEEDED(hr) )
2048     {
2049         int i, i_limit;
2050         const char *psz_name;
2051         libvlc_track_description_t *p_spuDesc;
2052
2053         // get subtitles description
2054         p_spuDesc = libvlc_video_get_spu_description(p_md, &ex);
2055         hr = exception_bridge(&ex);
2056         if( FAILED(hr) )
2057             return hr;
2058
2059         // get the number of available subtitle
2060         i_limit = libvlc_video_get_spu_count(p_md, &ex);
2061         hr = exception_bridge(&ex);
2062         if( FAILED(hr) )
2063             return hr;
2064
2065         // check if the number given is a good one
2066         if ( ( nameID > ( i_limit -1 ) ) || ( nameID < 0 ) )
2067             return E_FAIL;
2068
2069         // get the good spuDesc
2070         for( i = 0 ; i < nameID ; i++ )
2071         {
2072             p_spuDesc = p_spuDesc->p_next;
2073         }
2074         // get the subtitle name
2075         psz_name = p_spuDesc->psz_name;
2076
2077         // return it
2078         if( psz_name != NULL )
2079         {
2080             *name = BSTRFromCStr(CP_UTF8, psz_name);
2081             return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
2082         }
2083         *name = NULL;
2084         return E_FAIL;
2085     }
2086     return hr;
2087 };
2088
2089 /****************************************************************************/
2090
2091 VLCVideo::~VLCVideo()
2092 {
2093     delete _p_vlcmarquee;
2094     delete _p_vlclogo;
2095     if( _p_typeinfo )
2096         _p_typeinfo->Release();
2097 };
2098
2099 HRESULT VLCVideo::loadTypeInfo(void)
2100 {
2101     HRESULT hr = NOERROR;
2102     if( NULL == _p_typeinfo )
2103     {
2104         ITypeLib *p_typelib;
2105
2106         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
2107         if( SUCCEEDED(hr) )
2108         {
2109             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCVideo, &_p_typeinfo);
2110             if( FAILED(hr) )
2111             {
2112                 _p_typeinfo = NULL;
2113             }
2114             p_typelib->Release();
2115         }
2116     }
2117     return hr;
2118 };
2119
2120 STDMETHODIMP VLCVideo::GetTypeInfoCount(UINT* pctInfo)
2121 {
2122     if( NULL == pctInfo )
2123         return E_INVALIDARG;
2124
2125     if( SUCCEEDED(loadTypeInfo()) )
2126         *pctInfo = 1;
2127     else
2128         *pctInfo = 0;
2129
2130     return NOERROR;
2131 };
2132
2133 STDMETHODIMP VLCVideo::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
2134 {
2135     if( NULL == ppTInfo )
2136         return E_INVALIDARG;
2137
2138     if( SUCCEEDED(loadTypeInfo()) )
2139     {
2140         _p_typeinfo->AddRef();
2141         *ppTInfo = _p_typeinfo;
2142         return NOERROR;
2143     }
2144     *ppTInfo = NULL;
2145     return E_NOTIMPL;
2146 };
2147
2148 STDMETHODIMP VLCVideo::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
2149         UINT cNames, LCID lcid, DISPID* rgDispID)
2150 {
2151     if( SUCCEEDED(loadTypeInfo()) )
2152     {
2153         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
2154     }
2155     return E_NOTIMPL;
2156 };
2157
2158 STDMETHODIMP VLCVideo::Invoke(DISPID dispIdMember, REFIID riid,
2159         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
2160         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
2161 {
2162     if( SUCCEEDED(loadTypeInfo()) )
2163     {
2164         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
2165                 pVarResult, pExcepInfo, puArgErr);
2166     }
2167     return E_NOTIMPL;
2168 };
2169
2170 STDMETHODIMP VLCVideo::get_fullscreen(VARIANT_BOOL* fullscreen)
2171 {
2172     if( NULL == fullscreen )
2173         return E_POINTER;
2174
2175     libvlc_media_player_t *p_md;
2176     HRESULT hr = _p_instance->getMD(&p_md);
2177     if( SUCCEEDED(hr) )
2178     {
2179         libvlc_exception_t ex;
2180         libvlc_exception_init(&ex);
2181
2182         *fullscreen = libvlc_get_fullscreen(p_md, &ex) ?
2183                       VARIANT_TRUE : VARIANT_FALSE;
2184         hr = exception_bridge(&ex);
2185     }
2186     return hr;
2187 };
2188
2189 STDMETHODIMP VLCVideo::put_fullscreen(VARIANT_BOOL fullscreen)
2190 {
2191     libvlc_media_player_t *p_md;
2192     HRESULT hr = _p_instance->getMD(&p_md);
2193     if( SUCCEEDED(hr) )
2194     {
2195         libvlc_exception_t ex;
2196         libvlc_exception_init(&ex);
2197
2198         libvlc_set_fullscreen(p_md, VARIANT_FALSE != fullscreen, &ex);
2199         hr = exception_bridge(&ex);
2200     }
2201     return hr;
2202 };
2203
2204 STDMETHODIMP VLCVideo::get_width(long* width)
2205 {
2206     if( NULL == width )
2207         return E_POINTER;
2208
2209     libvlc_media_player_t *p_md;
2210     HRESULT hr = _p_instance->getMD(&p_md);
2211     if( SUCCEEDED(hr) )
2212     {
2213         libvlc_exception_t ex;
2214         libvlc_exception_init(&ex);
2215
2216         *width = libvlc_video_get_width(p_md, &ex);
2217         hr = exception_bridge(&ex);
2218     }
2219     return hr;
2220 };
2221
2222 STDMETHODIMP VLCVideo::get_height(long* height)
2223 {
2224     if( NULL == height )
2225         return E_POINTER;
2226
2227     libvlc_media_player_t *p_md;
2228     HRESULT hr = _p_instance->getMD(&p_md);
2229     if( SUCCEEDED(hr) )
2230     {
2231         libvlc_exception_t ex;
2232         libvlc_exception_init(&ex);
2233
2234         *height = libvlc_video_get_height(p_md, &ex);
2235         hr = exception_bridge(&ex);
2236     }
2237     return hr;
2238 };
2239
2240 STDMETHODIMP VLCVideo::get_aspectRatio(BSTR* aspect)
2241 {
2242     if( NULL == aspect )
2243         return E_POINTER;
2244
2245     libvlc_media_player_t *p_md;
2246     HRESULT hr = _p_instance->getMD(&p_md);
2247     if( SUCCEEDED(hr) )
2248     {
2249         libvlc_exception_t ex;
2250         libvlc_exception_init(&ex);
2251
2252         char *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
2253
2254         hr = exception_bridge(&ex);
2255         if( SUCCEEDED(hr) && NULL != psz_aspect )
2256         {
2257             *aspect = BSTRFromCStr(CP_UTF8, psz_aspect);
2258             if( NULL == *aspect )
2259                 hr = E_OUTOFMEMORY;
2260         } else if( NULL == psz_aspect) hr = E_OUTOFMEMORY; // strdup("") failed
2261         free( psz_aspect );
2262     }
2263     return hr;
2264 };
2265
2266 STDMETHODIMP VLCVideo::put_aspectRatio(BSTR aspect)
2267 {
2268     if( NULL == aspect )
2269         return E_POINTER;
2270
2271     libvlc_media_player_t *p_md;
2272     HRESULT hr = _p_instance->getMD(&p_md);
2273     if( SUCCEEDED(hr) )
2274     {
2275         libvlc_exception_t ex;
2276         libvlc_exception_init(&ex);
2277
2278         char *psz_aspect = CStrFromBSTR(CP_UTF8, aspect);
2279         if( NULL == psz_aspect )
2280         {
2281             return E_OUTOFMEMORY;
2282         }
2283
2284         libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
2285
2286         CoTaskMemFree(psz_aspect);
2287         hr = exception_bridge(&ex);
2288     }
2289     return hr;
2290 };
2291
2292 STDMETHODIMP VLCVideo::get_subtitle(long* spu)
2293 {
2294     if( NULL == spu )
2295         return E_POINTER;
2296
2297     libvlc_media_player_t *p_md;
2298     HRESULT hr = _p_instance->getMD(&p_md);
2299     if( SUCCEEDED(hr) )
2300     {
2301         libvlc_exception_t ex;
2302         libvlc_exception_init(&ex);
2303
2304         *spu = libvlc_video_get_spu(p_md, &ex);
2305         hr = exception_bridge(&ex);
2306     }
2307     return hr;
2308 };
2309
2310 STDMETHODIMP VLCVideo::put_subtitle(long spu)
2311 {
2312     libvlc_media_player_t *p_md;
2313     HRESULT hr = _p_instance->getMD(&p_md);
2314     if( SUCCEEDED(hr) )
2315     {
2316         libvlc_exception_t ex;
2317         libvlc_exception_init(&ex);
2318
2319         libvlc_video_set_spu(p_md, spu, &ex);
2320         hr = exception_bridge(&ex);
2321     }
2322     return hr;
2323 };
2324
2325 STDMETHODIMP VLCVideo::get_crop(BSTR* geometry)
2326 {
2327     if( NULL == geometry )
2328         return E_POINTER;
2329
2330     libvlc_media_player_t *p_md;
2331     HRESULT hr = _p_instance->getMD(&p_md);
2332     if( SUCCEEDED(hr) )
2333     {
2334         libvlc_exception_t ex;
2335         libvlc_exception_init(&ex);
2336
2337         char *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
2338
2339         hr = exception_bridge(&ex);
2340         if( SUCCEEDED(&ex) && NULL != psz_geometry )
2341         {
2342             *geometry = BSTRFromCStr(CP_UTF8, psz_geometry);
2343             if( NULL == geometry ) hr = E_OUTOFMEMORY;
2344         } else if( NULL == psz_geometry ) hr = E_OUTOFMEMORY;
2345         free( psz_geometry );
2346     }
2347     return hr;
2348 };
2349
2350 STDMETHODIMP VLCVideo::put_crop(BSTR geometry)
2351 {
2352     if( NULL == geometry )
2353         return E_POINTER;
2354
2355     if( 0 == SysStringLen(geometry) )
2356         return E_INVALIDARG;
2357
2358     libvlc_media_player_t *p_md;
2359     HRESULT hr = _p_instance->getMD(&p_md);
2360     if( SUCCEEDED(hr) )
2361     {
2362         libvlc_exception_t ex;
2363         libvlc_exception_init(&ex);
2364
2365         char *psz_geometry = CStrFromBSTR(CP_UTF8, geometry);
2366         if( NULL == psz_geometry )
2367         {
2368             return E_OUTOFMEMORY;
2369         }
2370
2371         libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
2372
2373         CoTaskMemFree(psz_geometry);
2374         hr = exception_bridge(&ex);
2375     }
2376     return hr;
2377 };
2378
2379 STDMETHODIMP VLCVideo::get_teletext(long* page)
2380 {
2381     if( NULL == page )
2382         return E_POINTER;
2383
2384     libvlc_media_player_t *p_md;
2385     HRESULT hr = _p_instance->getMD(&p_md);
2386     if( SUCCEEDED(hr) )
2387     {
2388         libvlc_exception_t ex;
2389         libvlc_exception_init(&ex);
2390
2391         *page = libvlc_video_get_teletext(p_md, &ex);
2392         hr = exception_bridge(&ex);
2393     }
2394     return hr;
2395 };
2396
2397 STDMETHODIMP VLCVideo::put_teletext(long page)
2398 {
2399     libvlc_media_player_t *p_md;
2400     HRESULT hr = _p_instance->getMD(&p_md);
2401     if( SUCCEEDED(hr) )
2402     {
2403         libvlc_exception_t ex;
2404         libvlc_exception_init(&ex);
2405
2406         libvlc_video_set_teletext(p_md, page, &ex);
2407         hr = exception_bridge(&ex);
2408     }
2409     return hr;
2410 };
2411
2412 STDMETHODIMP VLCVideo::deinterlaceDisable()
2413 {
2414     libvlc_media_player_t *p_md;
2415     HRESULT hr = _p_instance->getMD(&p_md);
2416     if( SUCCEEDED(hr) )
2417     {
2418         libvlc_exception_t ex;
2419         libvlc_exception_init(&ex);
2420
2421         libvlc_video_set_deinterlace(p_md, 0, "", &ex);
2422         hr = exception_bridge(&ex);
2423     }
2424     return hr;
2425 };
2426
2427 STDMETHODIMP VLCVideo::deinterlaceEnable(BSTR mode)
2428 {
2429     libvlc_media_player_t *p_md;
2430     HRESULT hr = _p_instance->getMD(&p_md);
2431     if( SUCCEEDED(hr) )
2432     {
2433         libvlc_exception_t ex;
2434         libvlc_exception_init(&ex);
2435         /* get deinterlace mode from the user */
2436         char *psz_mode = CStrFromBSTR(CP_UTF8, mode);
2437         /* enable deinterlace filter if possible */
2438         libvlc_video_set_deinterlace(p_md, 1, psz_mode, &ex);
2439         hr = exception_bridge(&ex);
2440         CoTaskMemFree(psz_mode);
2441     }
2442     return hr;
2443 };
2444
2445 STDMETHODIMP VLCVideo::takeSnapshot(LPPICTUREDISP* picture)
2446 {
2447     if( NULL == picture )
2448         return E_POINTER;
2449
2450     libvlc_media_player_t *p_md;
2451     HRESULT hr = _p_instance->getMD(&p_md);
2452     if( SUCCEEDED(hr) )
2453     {
2454         libvlc_exception_t ex;
2455         libvlc_exception_init(&ex);
2456
2457         static int uniqueId = 0;
2458         TCHAR path[MAX_PATH+1];
2459
2460         int pathlen = GetTempPath(MAX_PATH-24, path);
2461         if( (0 == pathlen) || (pathlen > (MAX_PATH-24)) )
2462             return E_FAIL;
2463
2464         /* check temp directory path by openning it */
2465         {
2466             HANDLE dirHandle = CreateFile(path, GENERIC_READ,
2467                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
2468                        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2469             if( INVALID_HANDLE_VALUE == dirHandle )
2470             {
2471                 _p_instance->setErrorInfo(IID_IVLCVideo,
2472                         "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
2473                 return E_FAIL;
2474             }
2475             else
2476             {
2477                 BY_HANDLE_FILE_INFORMATION bhfi;
2478                 BOOL res = GetFileInformationByHandle(dirHandle, &bhfi);
2479                 CloseHandle(dirHandle);
2480                 if( !res || !(bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
2481                 {
2482                     _p_instance->setErrorInfo(IID_IVLCVideo,
2483                             "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
2484                     return E_FAIL;
2485                 }
2486             }
2487         }
2488
2489         TCHAR filepath[MAX_PATH+1];
2490
2491         _stprintf(filepath, TEXT("%sAXVLC%lXS%lX.bmp"),
2492                  path, GetCurrentProcessId(), ++uniqueId);
2493
2494 #ifdef _UNICODE
2495         /* reuse path storage for UTF8 string */
2496         char *psz_filepath = (char *)path;
2497         WCHAR* wpath = filepath;
2498 #else
2499         char *psz_filepath = path;
2500         /* first convert to unicode using current code page */
2501         WCHAR wpath[MAX_PATH+1];
2502         if( 0 == MultiByteToWideChar(CP_ACP, 0, filepath, -1,
2503                                      wpath, sizeof(wpath)/sizeof(WCHAR)) )
2504             return E_FAIL;
2505 #endif
2506         /* convert to UTF8 */
2507         pathlen = WideCharToMultiByte(CP_UTF8, 0, wpath, -1,
2508                                       psz_filepath, sizeof(path), NULL, NULL);
2509         // fail if path is 0 or too short (i.e pathlen is the same as
2510         // storage size)
2511
2512         if( (0 == pathlen) || (sizeof(path) == pathlen) )
2513             return E_FAIL;
2514
2515         /* take snapshot into file */
2516         libvlc_video_take_snapshot(p_md, psz_filepath, 0, 0, &ex);
2517         hr = exception_bridge(&ex);
2518         if( SUCCEEDED(hr) )
2519         {
2520             /* open snapshot file */
2521             HANDLE snapPic = LoadImage(NULL, filepath, IMAGE_BITMAP, 0, 0,
2522                                        LR_CREATEDIBSECTION|LR_LOADFROMFILE);
2523             if( snapPic )
2524             {
2525                 PICTDESC snapDesc;
2526
2527                 snapDesc.cbSizeofstruct = sizeof(PICTDESC);
2528                 snapDesc.picType        = PICTYPE_BITMAP;
2529                 snapDesc.bmp.hbitmap    = (HBITMAP)snapPic;
2530                 snapDesc.bmp.hpal       = NULL;
2531
2532                 hr = OleCreatePictureIndirect(&snapDesc, IID_IPictureDisp,
2533                                               TRUE, (LPVOID*)picture);
2534                 if( FAILED(hr) )
2535                 {
2536                     *picture = NULL;
2537                     DeleteObject(snapPic);
2538                 }
2539             }
2540             DeleteFile(filepath);
2541         }
2542     }
2543     return hr;
2544 };
2545
2546 STDMETHODIMP VLCVideo::toggleFullscreen()
2547 {
2548     libvlc_media_player_t *p_md;
2549     HRESULT hr = _p_instance->getMD(&p_md);
2550     if( SUCCEEDED(hr) )
2551     {
2552         libvlc_exception_t ex;
2553         libvlc_exception_init(&ex);
2554
2555         libvlc_toggle_fullscreen(p_md, &ex);
2556         hr = exception_bridge(&ex);
2557     }
2558     return hr;
2559 };
2560
2561 STDMETHODIMP VLCVideo::toggleTeletext()
2562 {
2563     libvlc_media_player_t *p_md;
2564     HRESULT hr = _p_instance->getMD(&p_md);
2565     if( SUCCEEDED(hr) )
2566     {
2567         libvlc_exception_t ex;
2568         libvlc_exception_init(&ex);
2569
2570         libvlc_toggle_teletext(p_md, &ex);
2571         hr = exception_bridge(&ex);
2572     }
2573     return hr;
2574 };
2575
2576 STDMETHODIMP VLCVideo::get_marquee(IVLCMarquee** obj)
2577 {
2578     if( NULL == obj )
2579         return E_POINTER;
2580
2581     *obj = _p_vlcmarquee;
2582     if( NULL != _p_vlcmarquee )
2583     {
2584         _p_vlcmarquee->AddRef();
2585         return NOERROR;
2586     }
2587     return E_OUTOFMEMORY;
2588 };
2589
2590 STDMETHODIMP VLCVideo::get_logo(IVLCLogo** obj)
2591 {
2592     if( NULL == obj )
2593         return E_POINTER;
2594
2595     *obj = _p_vlclogo;
2596     if( NULL != _p_vlclogo )
2597     {
2598         _p_vlclogo->AddRef();
2599         return NOERROR;
2600     }
2601     return E_OUTOFMEMORY;
2602 }
2603
2604
2605 /****************************************************************************/
2606
2607 HRESULT VLCLogo::loadTypeInfo(void)
2608 {
2609     HRESULT hr = NOERROR;
2610     if( NULL == _p_typeinfo )
2611     {
2612         ITypeLib *p_typelib;
2613
2614         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
2615         if( SUCCEEDED(hr) )
2616         {
2617             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCLogo, &_p_typeinfo);
2618             if( FAILED(hr) )
2619             {
2620                 _p_typeinfo = NULL;
2621             }
2622             p_typelib->Release();
2623         }
2624     }
2625     return hr;
2626 }
2627
2628 STDMETHODIMP VLCLogo::GetTypeInfoCount(UINT* pctInfo)
2629 {
2630     if( NULL == pctInfo )
2631         return E_INVALIDARG;
2632
2633     if( SUCCEEDED(loadTypeInfo()) )
2634         *pctInfo = 1;
2635     else
2636         *pctInfo = 0;
2637
2638     return NOERROR;
2639 }
2640
2641 STDMETHODIMP VLCLogo::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
2642 {
2643     if( NULL == ppTInfo )
2644         return E_INVALIDARG;
2645
2646     if( SUCCEEDED(loadTypeInfo()) )
2647     {
2648         _p_typeinfo->AddRef();
2649         *ppTInfo = _p_typeinfo;
2650         return NOERROR;
2651     }
2652     *ppTInfo = NULL;
2653     return E_NOTIMPL;
2654 }
2655
2656 STDMETHODIMP VLCLogo::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
2657         UINT cNames, LCID lcid, DISPID* rgDispID)
2658 {
2659     if( SUCCEEDED(loadTypeInfo()) )
2660         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
2661     return E_NOTIMPL;
2662 }
2663
2664 STDMETHODIMP VLCLogo::Invoke(DISPID dispIdMember, REFIID riid,
2665         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
2666         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
2667 {
2668     if( SUCCEEDED(loadTypeInfo()) )
2669     {
2670         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags,
2671                           pDispParams, pVarResult, pExcepInfo, puArgErr);
2672     }
2673     return E_NOTIMPL;
2674 }
2675
2676
2677 HRESULT VLCLogo::do_put_int(unsigned idx, LONG val)
2678 {
2679     libvlc_media_player_t *p_md;
2680     HRESULT hr = _p_instance->getMD(&p_md);
2681     if( SUCCEEDED(hr) )
2682     {
2683         libvlc_exception_t ex;
2684         libvlc_exception_init(&ex);
2685         libvlc_video_set_logo_int(p_md, idx, val, &ex);
2686         hr = exception_bridge(&ex);
2687     }
2688     return hr;
2689 }
2690
2691 HRESULT VLCLogo::do_get_int(unsigned idx, LONG *val)
2692 {
2693     if( NULL == val )
2694         return E_POINTER;
2695
2696     libvlc_media_player_t *p_md;
2697     HRESULT hr = _p_instance->getMD(&p_md);
2698     if( SUCCEEDED(hr) )
2699     {
2700         libvlc_exception_t ex;
2701         libvlc_exception_init(&ex);
2702         *val = libvlc_video_get_logo_int(p_md, idx, &ex);
2703         hr = exception_bridge(&ex);
2704     }
2705     return hr;
2706 }
2707 STDMETHODIMP VLCLogo::file(BSTR fname)
2708 {
2709     libvlc_media_player_t *p_md;
2710     HRESULT hr = _p_instance->getMD(&p_md);
2711
2712     char *n = CStrFromBSTR(CP_UTF8, fname);
2713     if( !n ) hr = E_OUTOFMEMORY;
2714
2715     if( SUCCEEDED(hr) )
2716     {
2717         libvlc_exception_t ex;
2718         libvlc_exception_init(&ex);
2719         libvlc_video_set_logo_string(p_md, libvlc_logo_file, n, &ex);
2720         hr = exception_bridge(&ex);
2721     }
2722
2723     CoTaskMemFree(n);
2724     return hr;
2725 }
2726
2727 struct posidx_s { const char *n; size_t i; };
2728 static const posidx_s posidx[] = {
2729     { "center",        0 },
2730     { "left",          1 },
2731     { "right",         2 },
2732     { "top",           4 },
2733     { "bottom",        8 },
2734     { "top-left",      5 },
2735     { "top-right",     6 },
2736     { "bottom-left",   9 },
2737     { "bottom-right", 10 },
2738 };
2739 enum { num_posidx = sizeof(posidx)/sizeof(*posidx) };
2740 STDMETHODIMP VLCLogo::get_position(BSTR* val)
2741 {
2742     if( NULL == val )
2743         return E_POINTER;
2744
2745     LONG i;
2746     HRESULT hr = do_get_int(libvlc_logo_position, &i);
2747
2748     if(SUCCEEDED(hr))
2749     {
2750         const char *n="undefined";
2751
2752         for( const posidx_s *h=posidx; h<posidx+num_posidx; ++h )
2753             if( i == h->i )
2754             {
2755                 n=h->n;
2756                 break;
2757             }
2758         *val = BSTRFromCStr(CP_UTF8, n);
2759     }
2760     return hr;
2761 }
2762 STDMETHODIMP VLCLogo::put_position(BSTR val)
2763 {
2764     char *n = CStrFromBSTR(CP_UTF8, val);
2765     if( !n ) return E_OUTOFMEMORY;
2766
2767     HRESULT hr = E_NOTIMPL;
2768
2769     const posidx_s *h;
2770     for( h=posidx; h<posidx+num_posidx; ++h )
2771         if( !strcasecmp( n, h->n ) )
2772         {
2773             hr = do_put_int(libvlc_logo_position,h->i);
2774             break;
2775         }
2776
2777     if( h == posidx+num_posidx )
2778         hr = E_INVALIDARG;
2779
2780     CoTaskMemFree(n);
2781     return hr;
2782 }
2783
2784 /****************************************************************************/
2785
2786 VLCControl2::VLCControl2(VLCPlugin *p_instance) :
2787     _p_instance(p_instance),
2788     _p_typeinfo(NULL),
2789     _p_vlcaudio(new VLCAudio(p_instance)),
2790     _p_vlcinput(new VLCInput(p_instance)),
2791     _p_vlclog(new VLCLog(p_instance)),
2792     _p_vlcplaylist(new VLCPlaylist(p_instance)),
2793     _p_vlcsubtitle(new VLCSubtitle(p_instance)),
2794     _p_vlcvideo(new VLCVideo(p_instance))
2795 {
2796 }
2797
2798 VLCControl2::~VLCControl2()
2799 {
2800     delete _p_vlcvideo;
2801     delete _p_vlcsubtitle;
2802     delete _p_vlcplaylist;
2803     delete _p_vlclog;
2804     delete _p_vlcinput;
2805     delete _p_vlcaudio;
2806     if( _p_typeinfo )
2807         _p_typeinfo->Release();
2808 };
2809
2810 HRESULT VLCControl2::loadTypeInfo(void)
2811 {
2812     HRESULT hr = NOERROR;
2813     if( NULL == _p_typeinfo )
2814     {
2815         ITypeLib *p_typelib;
2816
2817         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
2818         if( SUCCEEDED(hr) )
2819         {
2820             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl2, &_p_typeinfo);
2821             if( FAILED(hr) )
2822             {
2823                 _p_typeinfo = NULL;
2824             }
2825             p_typelib->Release();
2826         }
2827     }
2828     return hr;
2829 };
2830
2831 STDMETHODIMP VLCControl2::GetTypeInfoCount(UINT* pctInfo)
2832 {
2833     if( NULL == pctInfo )
2834         return E_INVALIDARG;
2835
2836     if( SUCCEEDED(loadTypeInfo()) )
2837         *pctInfo = 1;
2838     else
2839         *pctInfo = 0;
2840
2841     return NOERROR;
2842 };
2843
2844 STDMETHODIMP VLCControl2::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
2845 {
2846     if( NULL == ppTInfo )
2847         return E_INVALIDARG;
2848
2849     if( SUCCEEDED(loadTypeInfo()) )
2850     {
2851         _p_typeinfo->AddRef();
2852         *ppTInfo = _p_typeinfo;
2853         return NOERROR;
2854     }
2855     *ppTInfo = NULL;
2856     return E_NOTIMPL;
2857 };
2858
2859 STDMETHODIMP VLCControl2::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
2860         UINT cNames, LCID lcid, DISPID* rgDispID)
2861 {
2862     if( SUCCEEDED(loadTypeInfo()) )
2863     {
2864         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
2865     }
2866     return E_NOTIMPL;
2867 };
2868
2869 STDMETHODIMP VLCControl2::Invoke(DISPID dispIdMember, REFIID riid,
2870         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
2871         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
2872 {
2873     if( SUCCEEDED(loadTypeInfo()) )
2874     {
2875         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
2876                 pVarResult, pExcepInfo, puArgErr);
2877     }
2878     return E_NOTIMPL;
2879 };
2880
2881 STDMETHODIMP VLCControl2::get_AutoLoop(VARIANT_BOOL *autoloop)
2882 {
2883     if( NULL == autoloop )
2884         return E_POINTER;
2885
2886     *autoloop = _p_instance->getAutoLoop() ? VARIANT_TRUE: VARIANT_FALSE;
2887     return S_OK;
2888 };
2889
2890 STDMETHODIMP VLCControl2::put_AutoLoop(VARIANT_BOOL autoloop)
2891 {
2892     _p_instance->setAutoLoop((VARIANT_FALSE != autoloop) ? TRUE: FALSE);
2893     return S_OK;
2894 };
2895
2896 STDMETHODIMP VLCControl2::get_AutoPlay(VARIANT_BOOL *autoplay)
2897 {
2898     if( NULL == autoplay )
2899         return E_POINTER;
2900
2901     *autoplay = _p_instance->getAutoPlay() ? VARIANT_TRUE: VARIANT_FALSE;
2902     return S_OK;
2903 };
2904
2905 STDMETHODIMP VLCControl2::put_AutoPlay(VARIANT_BOOL autoplay)
2906 {
2907     _p_instance->setAutoPlay((VARIANT_FALSE != autoplay) ? TRUE: FALSE);
2908     return S_OK;
2909 };
2910
2911 STDMETHODIMP VLCControl2::get_BaseURL(BSTR *url)
2912 {
2913     if( NULL == url )
2914         return E_POINTER;
2915
2916     *url = SysAllocStringLen(_p_instance->getBaseURL(),
2917                 SysStringLen(_p_instance->getBaseURL()));
2918     return NOERROR;
2919 };
2920
2921 STDMETHODIMP VLCControl2::put_BaseURL(BSTR mrl)
2922 {
2923     _p_instance->setBaseURL(mrl);
2924
2925     return S_OK;
2926 };
2927
2928 STDMETHODIMP VLCControl2::get_MRL(BSTR *mrl)
2929 {
2930     if( NULL == mrl )
2931         return E_POINTER;
2932
2933     *mrl = SysAllocStringLen(_p_instance->getMRL(),
2934                 SysStringLen(_p_instance->getMRL()));
2935     return NOERROR;
2936 };
2937
2938 STDMETHODIMP VLCControl2::put_MRL(BSTR mrl)
2939 {
2940     _p_instance->setMRL(mrl);
2941
2942     return S_OK;
2943 };
2944
2945
2946 STDMETHODIMP VLCControl2::get_Toolbar(VARIANT_BOOL *visible)
2947 {
2948     if( NULL == visible )
2949         return E_POINTER;
2950
2951     /*
2952      * Note to developers
2953      *
2954      * Returning the _b_toolbar is closer to the method specification.
2955      * But returning True when toolbar is not implemented so not displayed
2956      * could be bad for ActiveX users which rely on this value to show their
2957      * own toolbar if not provided by the ActiveX.
2958      *
2959      * This is the reason why FALSE is returned, until toolbar get implemented.
2960      */
2961
2962     /* DISABLED for now */
2963     //  *visible = _p_instance->getShowToolbar() ? VARIANT_TRUE: VARIANT_FALSE;
2964
2965     *visible = VARIANT_FALSE;
2966
2967     return S_OK;
2968 };
2969
2970 STDMETHODIMP VLCControl2::put_Toolbar(VARIANT_BOOL visible)
2971 {
2972     _p_instance->setShowToolbar((VARIANT_FALSE != visible) ? TRUE: FALSE);
2973     return S_OK;
2974 };
2975
2976
2977 STDMETHODIMP VLCControl2::get_StartTime(long *seconds)
2978 {
2979     if( NULL == seconds )
2980         return E_POINTER;
2981
2982     *seconds = _p_instance->getStartTime();
2983
2984     return S_OK;
2985 };
2986
2987 STDMETHODIMP VLCControl2::put_StartTime(long seconds)
2988 {
2989     _p_instance->setStartTime(seconds);
2990
2991     return NOERROR;
2992 };
2993
2994 STDMETHODIMP VLCControl2::get_VersionInfo(BSTR *version)
2995 {
2996     if( NULL == version )
2997         return E_POINTER;
2998
2999     const char *versionStr = libvlc_get_version();
3000     if( NULL != versionStr )
3001     {
3002         *version = BSTRFromCStr(CP_UTF8, versionStr);
3003
3004         return (NULL == *version) ? E_OUTOFMEMORY : NOERROR;
3005     }
3006     *version = NULL;
3007     return E_FAIL;
3008 };
3009
3010 STDMETHODIMP VLCControl2::get_Visible(VARIANT_BOOL *isVisible)
3011 {
3012     if( NULL == isVisible )
3013         return E_POINTER;
3014
3015     *isVisible = _p_instance->getVisible() ? VARIANT_TRUE : VARIANT_FALSE;
3016
3017     return NOERROR;
3018 };
3019
3020 STDMETHODIMP VLCControl2::put_Visible(VARIANT_BOOL isVisible)
3021 {
3022     _p_instance->setVisible(isVisible != VARIANT_FALSE);
3023
3024     return NOERROR;
3025 };
3026
3027 STDMETHODIMP VLCControl2::get_Volume(long *volume)
3028 {
3029     if( NULL == volume )
3030         return E_POINTER;
3031
3032     *volume  = _p_instance->getVolume();
3033     return NOERROR;
3034 };
3035
3036 STDMETHODIMP VLCControl2::put_Volume(long volume)
3037 {
3038     _p_instance->setVolume(volume);
3039     return NOERROR;
3040 };
3041
3042 STDMETHODIMP VLCControl2::get_BackColor(OLE_COLOR *backcolor)
3043 {
3044     if( NULL == backcolor )
3045         return E_POINTER;
3046
3047     *backcolor  = _p_instance->getBackColor();
3048     return NOERROR;
3049 };
3050
3051 STDMETHODIMP VLCControl2::put_BackColor(OLE_COLOR backcolor)
3052 {
3053     _p_instance->setBackColor(backcolor);
3054     return NOERROR;
3055 };
3056
3057 STDMETHODIMP VLCControl2::get_audio(IVLCAudio** obj)
3058 {
3059     if( NULL == obj )
3060         return E_POINTER;
3061
3062     *obj = _p_vlcaudio;
3063     if( NULL != _p_vlcaudio )
3064     {
3065         _p_vlcaudio->AddRef();
3066         return NOERROR;
3067     }
3068     return E_OUTOFMEMORY;
3069 };
3070
3071 STDMETHODIMP VLCControl2::get_input(IVLCInput** obj)
3072 {
3073     if( NULL == obj )
3074         return E_POINTER;
3075
3076     *obj = _p_vlcinput;
3077     if( NULL != _p_vlcinput )
3078     {
3079         _p_vlcinput->AddRef();
3080         return NOERROR;
3081     }
3082     return E_OUTOFMEMORY;
3083 };
3084
3085 STDMETHODIMP VLCControl2::get_log(IVLCLog** obj)
3086 {
3087     if( NULL == obj )
3088         return E_POINTER;
3089
3090     *obj = _p_vlclog;
3091     if( NULL != _p_vlclog )
3092     {
3093         _p_vlclog->AddRef();
3094         return NOERROR;
3095     }
3096     return E_OUTOFMEMORY;
3097 };
3098
3099 STDMETHODIMP VLCControl2::get_playlist(IVLCPlaylist** obj)
3100 {
3101     if( NULL == obj )
3102         return E_POINTER;
3103
3104     *obj = _p_vlcplaylist;
3105     if( NULL != _p_vlcplaylist )
3106     {
3107         _p_vlcplaylist->AddRef();
3108         return NOERROR;
3109     }
3110     return E_OUTOFMEMORY;
3111 };
3112
3113 STDMETHODIMP VLCControl2::get_subtitle(IVLCSubtitle** obj)
3114 {
3115     if( NULL == obj )
3116         return E_POINTER;
3117
3118     *obj = _p_vlcsubtitle;
3119     if( NULL != _p_vlcsubtitle )
3120     {
3121         _p_vlcsubtitle->AddRef();
3122         return NOERROR;
3123     }
3124     return E_OUTOFMEMORY;
3125 };
3126
3127 STDMETHODIMP VLCControl2::get_video(IVLCVideo** obj)
3128 {
3129     if( NULL == obj )
3130         return E_POINTER;
3131
3132     *obj = _p_vlcvideo;
3133     if( NULL != _p_vlcvideo )
3134     {
3135         _p_vlcvideo->AddRef();
3136         return NOERROR;
3137     }
3138     return E_OUTOFMEMORY;
3139 };