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