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