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