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