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