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