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