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