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