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