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