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