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