]> git.sesse.net Git - vlc/blob - projects/activex/vlccontrol2.cpp
activex plugin: Replace duplicated get_object methods with calls to
[vlc] / projects / activex / vlccontrol2.cpp
1 /*****************************************************************************
2  * vlccontrol2.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * Copyright (C) 2010 M2X BV
6  *
7  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
8  *          Jean-Paul Saman <jpsaman _at_ m2x _dot_ nl>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include <stdio.h>
26 #include <shlwapi.h>
27 #include <wininet.h>
28 #include <tchar.h>
29
30 #include "utils.h"
31 #include "plugin.h"
32 #include "vlccontrol2.h"
33 #include "vlccontrol.h"
34
35 #include "position.h"
36
37 // ---------
38
39 HRESULT VLCInterfaceBase::report_exception(REFIID riid, libvlc_exception_t *ex)
40 {
41     _plug->setErrorInfo(riid,libvlc_errmsg());
42     libvlc_exception_clear(ex);
43     return E_FAIL;
44 }
45
46 HRESULT VLCInterfaceBase::loadTypeInfo(REFIID riid)
47 {
48     // if( _ti ) return NOERROR; // unnecessairy
49
50     ITypeLib *p_typelib;
51     HRESULT hr = _plug->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
52     if( SUCCEEDED(hr) )
53     {
54         hr = p_typelib->GetTypeInfoOfGuid(riid, &_ti);
55         if( FAILED(hr) ) _ti = NULL;
56         p_typelib->Release();
57     }
58     return hr;
59 }
60
61 #define BIND_INTERFACE( class ) \
62     template<> REFIID VLCInterface<class, I##class>::_riid = IID_I##class;
63
64 BIND_INTERFACE( VLCAudio )
65 BIND_INTERFACE( VLCInput )
66 BIND_INTERFACE( VLCMessage )
67 BIND_INTERFACE( VLCMessages )
68 BIND_INTERFACE( VLCMessageIterator )
69 BIND_INTERFACE( VLCLog )
70 BIND_INTERFACE( VLCMarquee )
71 BIND_INTERFACE( VLCLogo )
72 BIND_INTERFACE( VLCPlaylistItems )
73 BIND_INTERFACE( VLCPlaylist )
74 BIND_INTERFACE( VLCVideo )
75 BIND_INTERFACE( VLCSubtitle )
76
77 #undef  BIND_INTERFACE
78
79 template<class I> static inline
80 HRESULT object_get(I **dst, I *src)
81 {
82     if( NULL == dst )
83         return E_POINTER;
84
85     *dst = src;
86     if( NULL != src )
87     {
88         src->AddRef();
89         return NOERROR;
90     }
91     return E_OUTOFMEMORY;
92 }
93
94 // ---------
95
96
97 STDMETHODIMP VLCAudio::get_mute(VARIANT_BOOL* mute)
98 {
99     if( NULL == mute )
100         return E_POINTER;
101
102     libvlc_instance_t* p_libvlc;
103     HRESULT hr = getVLC(&p_libvlc);
104     if( SUCCEEDED(hr) )
105         *mute = libvlc_audio_get_mute(p_libvlc) ?
106                         VARIANT_TRUE : VARIANT_FALSE;
107     return hr;
108 };
109
110 STDMETHODIMP VLCAudio::put_mute(VARIANT_BOOL mute)
111 {
112     libvlc_instance_t* p_libvlc;
113     HRESULT hr = getVLC(&p_libvlc);
114     if( SUCCEEDED(hr) )
115         libvlc_audio_set_mute(p_libvlc, VARIANT_FALSE != mute);
116     return hr;
117 };
118
119 STDMETHODIMP VLCAudio::get_volume(long* volume)
120 {
121     if( NULL == volume )
122         return E_POINTER;
123
124     libvlc_instance_t* p_libvlc;
125     HRESULT hr = getVLC(&p_libvlc);
126     if( SUCCEEDED(hr) )
127         *volume = libvlc_audio_get_volume(p_libvlc);
128     return hr;
129 };
130
131 STDMETHODIMP VLCAudio::put_volume(long volume)
132 {
133     libvlc_instance_t* p_libvlc;
134     HRESULT hr = getVLC(&p_libvlc);
135     if( SUCCEEDED(hr) )
136     {
137         libvlc_exception_t ex;
138         libvlc_exception_init(&ex);
139
140         libvlc_audio_set_volume(p_libvlc, volume, &ex);
141         hr = exception_bridge(&ex);
142     }
143     return hr;
144 };
145
146 STDMETHODIMP VLCAudio::get_track(long* track)
147 {
148     if( NULL == track )
149         return E_POINTER;
150
151     libvlc_media_player_t* p_md;
152     HRESULT hr = getMD(&p_md);
153     if( SUCCEEDED(hr) )
154     {
155         libvlc_exception_t ex;
156         libvlc_exception_init(&ex);
157
158         *track = libvlc_audio_get_track(p_md, &ex);
159         hr = exception_bridge(&ex);
160     }
161     return hr;
162 };
163
164 STDMETHODIMP VLCAudio::put_track(long track)
165 {
166     libvlc_media_player_t *p_md;
167     HRESULT hr = getMD(&p_md);
168     if( SUCCEEDED(hr) )
169     {
170         libvlc_exception_t ex;
171         libvlc_exception_init(&ex);
172
173         libvlc_audio_set_track(p_md, track, &ex);
174         hr = exception_bridge(&ex);
175     }
176     return hr;
177 };
178
179 STDMETHODIMP VLCAudio::get_count(long* trackNumber)
180 {
181     if( NULL == trackNumber )
182         return E_POINTER;
183
184     libvlc_media_player_t* p_md;
185     HRESULT hr = getMD(&p_md);
186     if( SUCCEEDED(hr) )
187     {
188         libvlc_exception_t ex;
189         libvlc_exception_init(&ex);
190         // get the number of audio track available and return it
191         *trackNumber = libvlc_audio_get_track_count(p_md, &ex);
192         hr = exception_bridge(&ex);
193     }
194     return hr;
195 };
196
197
198 STDMETHODIMP VLCAudio::description(long trackID, BSTR* name)
199 {
200     if( NULL == name )
201         return E_POINTER;
202
203     libvlc_media_player_t* p_md;
204     libvlc_exception_t ex;
205     libvlc_exception_init(&ex);
206
207     HRESULT hr = getMD(&p_md);
208     if( SUCCEEDED(hr) )
209     {
210         int i, i_limit;
211         const char *psz_name;
212         libvlc_track_description_t *p_trackDesc;
213
214         // get tracks description
215         p_trackDesc = libvlc_audio_get_track_description(p_md, &ex);
216         hr = exception_bridge(&ex);
217         if( FAILED(hr) )
218             return hr;
219
220         //get the number of available track
221         i_limit = libvlc_audio_get_track_count(p_md, &ex);
222         hr = exception_bridge(&ex);
223         if( FAILED(hr) )
224             return hr;
225
226         // check if the number given is a good one
227         if ( ( trackID > ( i_limit -1 ) ) || ( trackID < 0 ) )
228                 return E_FAIL;
229
230         // get the good trackDesc
231         for( i = 0 ; i < trackID ; i++ )
232         {
233             p_trackDesc = p_trackDesc->p_next;
234         }
235         // get the track name
236         psz_name = p_trackDesc->psz_name;
237
238         // return it
239         if( psz_name != NULL )
240         {
241             *name = BSTRFromCStr(CP_UTF8, psz_name);
242             return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
243         }
244         *name = NULL;
245         return E_FAIL;
246     }
247     return hr;
248 };
249
250 STDMETHODIMP VLCAudio::get_channel(long *channel)
251 {
252     if( NULL == channel )
253         return E_POINTER;
254
255     libvlc_instance_t* p_libvlc;
256     HRESULT hr = getVLC(&p_libvlc);
257     if( SUCCEEDED(hr) )
258     {
259         libvlc_exception_t ex;
260         libvlc_exception_init(&ex);
261
262         *channel = libvlc_audio_get_channel(p_libvlc, &ex);
263         hr = exception_bridge(&ex);
264     }
265     return hr;
266 };
267
268 STDMETHODIMP VLCAudio::put_channel(long channel)
269 {
270     libvlc_instance_t* p_libvlc;
271     HRESULT hr = getVLC(&p_libvlc);
272     if( SUCCEEDED(hr) )
273     {
274         libvlc_exception_t ex;
275         libvlc_exception_init(&ex);
276
277         libvlc_audio_set_channel(p_libvlc, channel, &ex);
278         hr = exception_bridge(&ex);
279     }
280     return hr;
281 };
282
283 STDMETHODIMP VLCAudio::toggleMute()
284 {
285     libvlc_instance_t* p_libvlc;
286     HRESULT hr = getVLC(&p_libvlc);
287     if( SUCCEEDED(hr) )
288         libvlc_audio_toggle_mute(p_libvlc);
289     return hr;
290 };
291
292 /****************************************************************************/
293
294 STDMETHODIMP VLCInput::get_length(double* length)
295 {
296     if( NULL == length )
297         return E_POINTER;
298     *length = 0;
299
300     libvlc_media_player_t *p_md;
301     HRESULT hr = getMD(&p_md);
302     if( SUCCEEDED(hr) )
303     {
304         libvlc_exception_t ex;
305         libvlc_exception_init(&ex);
306
307         *length = (double)libvlc_media_player_get_length(p_md, &ex);
308         hr = exception_bridge(&ex);
309     }
310     return hr;
311 };
312
313 STDMETHODIMP VLCInput::get_position(double* position)
314 {
315     if( NULL == position )
316         return E_POINTER;
317
318     *position = 0.0f;
319     libvlc_media_player_t *p_md;
320     HRESULT hr = getMD(&p_md);
321     if( SUCCEEDED(hr) )
322     {
323         libvlc_exception_t ex;
324         libvlc_exception_init(&ex);
325
326         *position = libvlc_media_player_get_position(p_md, &ex);
327         hr = exception_bridge(&ex);
328     }
329     return hr;
330 };
331
332 STDMETHODIMP VLCInput::put_position(double position)
333 {
334     libvlc_media_player_t *p_md;
335     HRESULT hr = getMD(&p_md);
336     if( SUCCEEDED(hr) )
337     {
338         libvlc_exception_t ex;
339         libvlc_exception_init(&ex);
340
341         libvlc_media_player_set_position(p_md, position, &ex);
342         hr = exception_bridge(&ex);
343     }
344     return hr;
345 };
346
347 STDMETHODIMP VLCInput::get_time(double* time)
348 {
349     if( NULL == time )
350         return E_POINTER;
351
352     libvlc_media_player_t *p_md;
353     HRESULT hr = getMD(&p_md);
354     if( SUCCEEDED(hr) )
355     {
356         libvlc_exception_t ex;
357         libvlc_exception_init(&ex);
358
359         *time = (double)libvlc_media_player_get_time(p_md, &ex);
360         hr = exception_bridge(&ex);
361     }
362     return hr;
363 };
364
365 STDMETHODIMP VLCInput::put_time(double time)
366 {
367     libvlc_media_player_t *p_md;
368     HRESULT hr = getMD(&p_md);
369     if( SUCCEEDED(hr) )
370     {
371         libvlc_exception_t ex;
372         libvlc_exception_init(&ex);
373
374         libvlc_media_player_set_time(p_md, (int64_t)time, &ex);
375         hr = exception_bridge(&ex);
376     }
377     return hr;
378 };
379
380 STDMETHODIMP VLCInput::get_state(long* state)
381 {
382     if( NULL == state )
383         return E_POINTER;
384
385     libvlc_media_player_t *p_md;
386     HRESULT hr = getMD(&p_md);
387     if( SUCCEEDED(hr) )
388     {
389         libvlc_exception_t ex;
390         libvlc_exception_init(&ex);
391
392         *state = libvlc_media_player_get_state(p_md, &ex);
393         if( libvlc_exception_raised(&ex) )
394         {
395             // don't fail, just return the idle state
396             *state = 0;
397             libvlc_exception_clear(&ex);
398         }
399     }
400     return hr;
401 };
402
403 STDMETHODIMP VLCInput::get_rate(double* rate)
404 {
405     if( NULL == rate )
406         return E_POINTER;
407
408     libvlc_media_player_t *p_md;
409     HRESULT hr = getMD(&p_md);
410     if( SUCCEEDED(hr) )
411     {
412         libvlc_exception_t ex;
413         libvlc_exception_init(&ex);
414
415         *rate = libvlc_media_player_get_rate(p_md, &ex);
416         hr = exception_bridge(&ex);
417     }
418     return hr;
419 };
420
421 STDMETHODIMP VLCInput::put_rate(double rate)
422 {
423     libvlc_media_player_t *p_md;
424     HRESULT hr = getMD(&p_md);
425     if( SUCCEEDED(hr) )
426     {
427         libvlc_exception_t ex;
428         libvlc_exception_init(&ex);
429
430         libvlc_media_player_set_rate(p_md, rate, &ex);
431         hr = exception_bridge(&ex);
432     }
433     return hr;
434 };
435
436 STDMETHODIMP VLCInput::get_fps(double* fps)
437 {
438     if( NULL == fps )
439         return E_POINTER;
440
441     *fps = 0.0;
442     libvlc_media_player_t *p_md;
443     HRESULT hr = getMD(&p_md);
444     if( SUCCEEDED(hr) )
445     {
446         libvlc_exception_t ex;
447         libvlc_exception_init(&ex);
448
449         *fps = libvlc_media_player_get_fps(p_md, &ex);
450         hr = exception_bridge(&ex);
451     }
452     return hr;
453 };
454
455 STDMETHODIMP VLCInput::get_hasVout(VARIANT_BOOL* hasVout)
456 {
457     if( NULL == hasVout )
458         return E_POINTER;
459
460     libvlc_media_player_t *p_md;
461     HRESULT hr = getMD(&p_md);
462     if( SUCCEEDED(hr) )
463     {
464         libvlc_exception_t ex;
465         libvlc_exception_init(&ex);
466
467         *hasVout = libvlc_media_player_has_vout(p_md, &ex) ?
468                                 VARIANT_TRUE : VARIANT_FALSE;
469         hr = exception_bridge(&ex);
470     }
471     return hr;
472 };
473
474 /****************************************************************************/
475
476 VLCLog::~VLCLog()
477 {
478     delete _p_vlcmessages;
479     if( _p_log )
480         libvlc_log_close(_p_log);
481 }
482
483 STDMETHODIMP VLCLog::get_messages(IVLCMessages** obj)
484 {
485     if( NULL == obj )
486         return E_POINTER;
487
488     *obj = _p_vlcmessages;
489     if( NULL != _p_vlcmessages )
490     {
491         _p_vlcmessages->AddRef();
492         return NOERROR;
493     }
494     return E_OUTOFMEMORY;
495 };
496
497 STDMETHODIMP VLCLog::get_verbosity(long* level)
498 {
499     if( NULL == level )
500         return E_POINTER;
501
502     if( _p_log )
503     {
504         libvlc_instance_t* p_libvlc;
505         HRESULT hr = getVLC(&p_libvlc);
506         if( SUCCEEDED(hr) )
507             *level = libvlc_get_log_verbosity(p_libvlc);
508         return hr;
509     }
510     else
511     {
512         /* log is not enabled, return -1 */
513         *level = -1;
514         return NOERROR;
515     }
516 };
517
518 STDMETHODIMP VLCLog::put_verbosity(long verbosity)
519 {
520     libvlc_instance_t* p_libvlc;
521     HRESULT hr = getVLC(&p_libvlc);
522     if( SUCCEEDED(hr) )
523     {
524         libvlc_exception_t ex;
525         libvlc_exception_init(&ex);
526
527         if( verbosity >= 0 )
528         {
529             if( ! _p_log )
530             {
531                 _p_log = libvlc_log_open(p_libvlc, &ex);
532                 hr = exception_bridge(&ex);
533             }
534             if( SUCCEEDED(hr) )
535                 libvlc_set_log_verbosity(p_libvlc, (unsigned)verbosity);
536         }
537         else if( _p_log )
538         {
539             /* close log  when verbosity is set to -1 */
540             libvlc_log_close(_p_log);
541             _p_log = NULL;
542         }
543         hr = exception_bridge(&ex);
544     }
545     return hr;
546 };
547
548 /****************************************************************************/
549
550 HRESULT VLCMarquee::do_put_int(unsigned idx, LONG val)
551 {
552     libvlc_media_player_t *p_md;
553     HRESULT hr = getMD(&p_md);
554     if( SUCCEEDED(hr) )
555     {
556         libvlc_exception_t ex;
557         libvlc_exception_init(&ex);
558         libvlc_video_set_marquee_int(p_md, idx, val, &ex);
559         hr = exception_bridge(&ex);
560     }
561     return hr;
562 }
563
564 HRESULT VLCMarquee::do_get_int(unsigned idx, LONG *val)
565 {
566     if( NULL == val )
567         return E_POINTER;
568
569     libvlc_media_player_t *p_md;
570     HRESULT hr = getMD(&p_md);
571     if( SUCCEEDED(hr) )
572     {
573         libvlc_exception_t ex;
574         libvlc_exception_init(&ex);
575         *val = libvlc_video_get_marquee_int(p_md, idx, &ex);
576         hr = exception_bridge(&ex);
577     }
578     return hr;
579 }
580
581 STDMETHODIMP VLCMarquee::get_position(BSTR* val)
582 {
583     if( NULL == val )
584         return E_POINTER;
585
586     LONG i;
587     HRESULT hr = do_get_int(libvlc_marquee_Position, &i);
588
589     if(SUCCEEDED(hr))
590         *val = BSTRFromCStr(CP_UTF8, position_bynumber(i));
591
592     return hr;
593 }
594
595 STDMETHODIMP VLCMarquee::put_position(BSTR val)
596 {
597     char *n = CStrFromBSTR(CP_UTF8, val);
598     if( !n ) return E_OUTOFMEMORY;
599
600     size_t i;
601     HRESULT hr;
602     if( position_byname( n, i ) )
603         hr = do_put_int(libvlc_marquee_Position,i);
604     else
605         hr = E_INVALIDARG;
606
607     CoTaskMemFree(n);
608     return hr;
609 }
610
611 STDMETHODIMP VLCMarquee::get_text(BSTR *val)
612 {
613     char *psz;
614     if( NULL == val )
615         return E_POINTER;
616
617     libvlc_media_player_t *p_md;
618     HRESULT hr = getMD(&p_md);
619     if( SUCCEEDED(hr) )
620     {
621         libvlc_exception_t ex;
622         libvlc_exception_init(&ex);
623
624         psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text, &ex);
625
626         hr = exception_bridge(&ex);
627         if(SUCCEEDED(hr))
628             *val = BSTRFromCStr(CP_UTF8, psz);
629     }
630     return hr;
631 }
632
633 STDMETHODIMP VLCMarquee::put_text(BSTR val)
634 {
635     libvlc_media_player_t *p_md;
636     HRESULT hr = getMD(&p_md);
637     if( SUCCEEDED(hr) )
638     {
639         libvlc_exception_t ex;
640         libvlc_exception_init(&ex);
641
642         char *psz_text = CStrFromBSTR(CP_UTF8, val);
643         libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text,
644                                         psz_text, &ex);
645         hr = exception_bridge(&ex);
646         CoTaskMemFree(psz_text);
647     }
648     return hr;
649 }
650
651 /****************************************************************************/
652
653 /* STL forward iterator used by VLCEnumIterator class to implement IEnumVARIANT */
654
655 class VLCMessageSTLIterator
656 {
657
658 public:
659
660     VLCMessageSTLIterator(IVLCMessageIterator* iter) : iter(iter), msg(NULL)
661     {
662         // get first message
663         operator++();
664     };
665
666     VLCMessageSTLIterator(const VLCMessageSTLIterator& other)
667     {
668         iter = other.iter;
669         if( iter )
670             iter->AddRef();
671         msg = other.msg;
672         if( msg )
673             msg->AddRef();
674     };
675
676     virtual ~VLCMessageSTLIterator()
677     {
678         if( msg )
679             msg->Release();
680
681         if( iter )
682             iter->Release();
683     };
684
685     // we only need prefix ++ operator
686     VLCMessageSTLIterator& operator++()
687     {
688         VARIANT_BOOL hasNext = VARIANT_FALSE;
689         if( iter )
690         {
691             iter->get_hasNext(&hasNext);
692
693             if( msg )
694             {
695                 msg->Release();
696                 msg = NULL;
697             }
698             if( VARIANT_TRUE == hasNext ) {
699                 iter->next(&msg);
700             }
701         }
702         return *this;
703     };
704
705     VARIANT operator*() const
706     {
707         VARIANT v;
708         VariantInit(&v);
709         if( msg )
710         {
711             if( SUCCEEDED(msg->QueryInterface(IID_IDispatch,
712                           (LPVOID*)&V_DISPATCH(&v))) )
713             {
714                 V_VT(&v) = VT_DISPATCH;
715             }
716         }
717         return v;
718     };
719
720     bool operator==(const VLCMessageSTLIterator& other) const
721     {
722         return msg == other.msg;
723     };
724
725     bool operator!=(const VLCMessageSTLIterator& other) const
726     {
727         return msg != other.msg;
728     };
729
730 private:
731     IVLCMessageIterator* iter;
732     IVLCMessage*         msg;
733 };
734
735 //////////////////////////////////////////////////////////////////////////////
736
737 STDMETHODIMP VLCMessages::get__NewEnum(LPUNKNOWN* _NewEnum)
738 {
739     if( NULL == _NewEnum )
740         return E_POINTER;
741
742     IVLCMessageIterator* iter = NULL;
743     iterator(&iter);
744
745     *_NewEnum= new VLCEnumIterator<IID_IEnumVARIANT,
746                        IEnumVARIANT,
747                        VARIANT,
748                        VLCMessageSTLIterator>
749                        (VLCMessageSTLIterator(iter), VLCMessageSTLIterator(NULL));
750
751     return *_NewEnum ? S_OK : E_OUTOFMEMORY;
752 };
753
754 STDMETHODIMP VLCMessages::clear()
755 {
756     libvlc_log_t *p_log = _p_vlclog->_p_log;
757     if( p_log )
758         libvlc_log_clear(p_log);
759     return NOERROR;
760 };
761
762 STDMETHODIMP VLCMessages::get_count(long* count)
763 {
764     if( NULL == count )
765         return E_POINTER;
766
767     libvlc_log_t *p_log = _p_vlclog->_p_log;
768     *count = libvlc_log_count(p_log);
769     return S_OK;
770 };
771
772 STDMETHODIMP VLCMessages::iterator(IVLCMessageIterator** iter)
773 {
774     if( NULL == iter )
775         return E_POINTER;
776
777     *iter = new VLCMessageIterator(Instance(), _p_vlclog);
778
779     return *iter ? S_OK : E_OUTOFMEMORY;
780 };
781
782 /****************************************************************************/
783
784 VLCMessageIterator::VLCMessageIterator(VLCPlugin *p, VLCLog* p_vlclog ):
785         VLCInterface<VLCMessageIterator,IVLCMessageIterator>(p),
786         _refcount(1),
787         _p_vlclog(p_vlclog),
788         _p_iter(_p_vlclog && _p_vlclog->_p_log ?
789                 libvlc_log_get_iterator(_p_vlclog->_p_log, NULL) : NULL)
790 {
791 }
792
793 STDMETHODIMP VLCMessageIterator::get_hasNext(VARIANT_BOOL* hasNext)
794 {
795     if( NULL == hasNext )
796         return E_POINTER;
797
798     *hasNext = (_p_iter && _p_vlclog->_p_log &&
799                 libvlc_log_iterator_has_next(_p_iter)) ?
800                 VARIANT_TRUE : VARIANT_FALSE;
801     return S_OK;
802 };
803
804 STDMETHODIMP VLCMessageIterator::next(IVLCMessage** message)
805 {
806     HRESULT hr = S_OK;
807
808     if( NULL == message )
809         return E_POINTER;
810
811     if( _p_iter &&  _p_vlclog->_p_log )
812     {
813         struct libvlc_log_message_t buffer;
814
815         buffer.sizeof_msg = sizeof(buffer);
816
817         libvlc_exception_t ex;
818         libvlc_exception_init(&ex);
819
820         libvlc_log_iterator_next(_p_iter, &buffer, &ex);
821         *message = new VLCMessage(Instance(), buffer);
822         if( !message )
823             hr = E_OUTOFMEMORY;
824     }
825     return hr;
826 };
827
828 /****************************************************************************/
829
830 inline const char *msgSeverity(int sev)
831 {
832     switch( sev )
833     {
834         case 0:
835             return "info";
836         case 1:
837             return "error";
838         case 2:
839             return "warning";
840         default:
841             return "debug";
842     }
843 };
844
845 STDMETHODIMP VLCMessage::get__Value(VARIANT* _Value)
846 {
847     if( NULL == _Value )
848         return E_POINTER;
849
850     char buffer[256];
851
852     snprintf(buffer, sizeof(buffer), "%s %s %s: %s",
853         _msg.psz_type, _msg.psz_name, msgSeverity(_msg.i_severity), _msg.psz_message);
854
855     V_VT(_Value) = VT_BSTR;
856     V_BSTR(_Value) = BSTRFromCStr(CP_UTF8, buffer);
857
858     return S_OK;
859 };
860
861 STDMETHODIMP VLCMessage::get_severity(long* level)
862 {
863     if( NULL == level )
864         return E_POINTER;
865
866     *level = _msg.i_severity;
867
868     return S_OK;
869 };
870
871 STDMETHODIMP VLCMessage::get_type(BSTR* type)
872 {
873     if( NULL == type )
874         return E_POINTER;
875
876     *type = BSTRFromCStr(CP_UTF8, _msg.psz_type);
877
878     return NOERROR;
879 };
880
881 STDMETHODIMP VLCMessage::get_name(BSTR* name)
882 {
883     if( NULL == name )
884         return E_POINTER;
885
886     *name = BSTRFromCStr(CP_UTF8, _msg.psz_name);
887
888     return NOERROR;
889 };
890
891 STDMETHODIMP VLCMessage::get_header(BSTR* header)
892 {
893     if( NULL == header )
894         return E_POINTER;
895
896     *header = BSTRFromCStr(CP_UTF8, _msg.psz_header);
897
898     return NOERROR;
899 };
900
901 STDMETHODIMP VLCMessage::get_message(BSTR* message)
902 {
903     if( NULL == message )
904         return E_POINTER;
905
906     *message = BSTRFromCStr(CP_UTF8, _msg.psz_message);
907
908     return NOERROR;
909 };
910
911 /****************************************************************************/
912
913 STDMETHODIMP VLCPlaylistItems::get_count(long* count)
914 {
915     if( NULL == count )
916         return E_POINTER;
917
918     libvlc_exception_t ex;
919     libvlc_exception_init(&ex);
920
921     *count = Instance()->playlist_count(&ex);
922     return exception_bridge(&ex);
923 };
924
925 STDMETHODIMP VLCPlaylistItems::clear()
926 {
927     libvlc_exception_t ex;
928     libvlc_exception_init(&ex);
929
930     Instance()->playlist_clear(&ex);
931     return exception_bridge(&ex);
932 };
933
934 STDMETHODIMP VLCPlaylistItems::remove(long item)
935 {
936     libvlc_instance_t* p_libvlc;
937     HRESULT hr = getVLC(&p_libvlc);
938     if( SUCCEEDED(hr) )
939     {
940         libvlc_exception_t ex;
941         libvlc_exception_init(&ex);
942
943         Instance()->playlist_delete_item(item, &ex);
944         hr = exception_bridge(&ex);
945     }
946     return hr;
947 };
948
949 /****************************************************************************/
950
951 STDMETHODIMP VLCPlaylist::get_itemCount(long* count)
952 {
953     if( NULL == count )
954         return E_POINTER;
955
956     *count = 0;
957     libvlc_exception_t ex;
958     libvlc_exception_init(&ex);
959
960     *count = Instance()->playlist_count(&ex);
961     return exception_bridge(&ex);
962 };
963
964 STDMETHODIMP VLCPlaylist::get_isPlaying(VARIANT_BOOL* isPlaying)
965 {
966     if( NULL == isPlaying )
967         return E_POINTER;
968
969     libvlc_media_player_t *p_md;
970     HRESULT hr = getMD(&p_md);
971     if( SUCCEEDED(hr) )
972     {
973         libvlc_exception_t ex;
974         libvlc_exception_init(&ex);
975
976         *isPlaying = libvlc_media_player_is_playing(p_md, &ex) ?
977                      VARIANT_TRUE: VARIANT_FALSE;
978         libvlc_exception_clear(&ex);
979     }
980     return hr;
981 };
982
983 STDMETHODIMP VLCPlaylist::add(BSTR uri, VARIANT name, VARIANT options, long* item)
984 {
985     if( NULL == item )
986         return E_POINTER;
987
988     if( 0 == SysStringLen(uri) )
989         return E_INVALIDARG;
990
991     libvlc_instance_t* p_libvlc;
992     HRESULT hr = getVLC(&p_libvlc);
993     if( SUCCEEDED(hr) )
994     {
995         libvlc_exception_t ex;
996         libvlc_exception_init(&ex);
997
998         char *psz_uri = NULL;
999         if( SysStringLen(Instance()->getBaseURL()) > 0 )
1000         {
1001             /*
1002             ** if the MRL a relative URL, we should end up with an absolute URL
1003             */
1004             LPWSTR abs_url = CombineURL(Instance()->getBaseURL(), uri);
1005             if( NULL != abs_url )
1006             {
1007                 psz_uri = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
1008                 CoTaskMemFree(abs_url);
1009             }
1010             else
1011             {
1012                 psz_uri = CStrFromBSTR(CP_UTF8, uri);
1013             }
1014         }
1015         else
1016         {
1017             /*
1018             ** baseURL is empty, assume MRL is absolute
1019             */
1020             psz_uri = CStrFromBSTR(CP_UTF8, uri);
1021         }
1022
1023         if( NULL == psz_uri )
1024         {
1025             return E_OUTOFMEMORY;
1026         }
1027
1028         int i_options;
1029         char **ppsz_options;
1030
1031         hr = VLCControl::CreateTargetOptions(CP_UTF8, &options, &ppsz_options, &i_options);
1032         if( FAILED(hr) )
1033         {
1034             CoTaskMemFree(psz_uri);
1035             return hr;
1036         }
1037
1038         char *psz_name = NULL;
1039         VARIANT v_name;
1040         VariantInit(&v_name);
1041         if( SUCCEEDED(VariantChangeType(&v_name, &name, 0, VT_BSTR)) )
1042         {
1043             if( SysStringLen(V_BSTR(&v_name)) > 0 )
1044                 psz_name = CStrFromBSTR(CP_UTF8, V_BSTR(&v_name));
1045
1046             VariantClear(&v_name);
1047         }
1048
1049         *item = Instance()->playlist_add_extended_untrusted(psz_uri,
1050                     i_options, const_cast<const char **>(ppsz_options), &ex);
1051
1052         VLCControl::FreeTargetOptions(ppsz_options, i_options);
1053         CoTaskMemFree(psz_uri);
1054         if( psz_name ) /* XXX Do we even need to check? */
1055             CoTaskMemFree(psz_name);
1056         hr = exception_bridge(&ex);
1057     }
1058     return hr;
1059 };
1060
1061 STDMETHODIMP VLCPlaylist::play()
1062 {
1063     libvlc_exception_t ex;
1064     libvlc_exception_init(&ex);
1065
1066     Instance()->playlist_play(&ex);
1067     return exception_bridge(&ex);
1068 };
1069
1070 STDMETHODIMP VLCPlaylist::playItem(long item)
1071 {
1072     libvlc_exception_t ex;
1073     libvlc_exception_init(&ex);
1074
1075     Instance()->playlist_play_item(item,&ex);
1076     return exception_bridge(&ex);;
1077 };
1078
1079 STDMETHODIMP VLCPlaylist::togglePause()
1080 {
1081     libvlc_media_player_t* p_md;
1082     HRESULT hr = getMD(&p_md);
1083     if( SUCCEEDED(hr) )
1084     {
1085         libvlc_exception_t ex;
1086         libvlc_exception_init(&ex);
1087
1088         libvlc_media_player_pause(p_md, &ex);
1089         hr = exception_bridge(&ex);;
1090     }
1091     return hr;
1092 };
1093
1094 STDMETHODIMP VLCPlaylist::stop()
1095 {
1096     libvlc_media_player_t *p_md;
1097     HRESULT hr = getMD(&p_md);
1098     if( SUCCEEDED(hr) )
1099     {
1100         libvlc_exception_t ex;
1101         libvlc_exception_init(&ex);
1102
1103         libvlc_media_player_stop(p_md, &ex);
1104         hr = exception_bridge(&ex);;
1105     }
1106     return hr;
1107 };
1108
1109 STDMETHODIMP VLCPlaylist::next()
1110 {
1111     libvlc_exception_t ex;
1112     libvlc_exception_init(&ex);
1113
1114     Instance()->playlist_next(&ex);
1115     return exception_bridge(&ex);;
1116 };
1117
1118 STDMETHODIMP VLCPlaylist::prev()
1119 {
1120     libvlc_exception_t ex;
1121     libvlc_exception_init(&ex);
1122
1123     Instance()->playlist_prev(&ex);
1124     return exception_bridge(&ex);;
1125 };
1126
1127 STDMETHODIMP VLCPlaylist::clear()
1128 {
1129     libvlc_exception_t ex;
1130     libvlc_exception_init(&ex);
1131
1132     Instance()->playlist_clear(&ex);
1133     return exception_bridge(&ex);;
1134 };
1135
1136 STDMETHODIMP VLCPlaylist::removeItem(long item)
1137 {
1138     libvlc_instance_t* p_libvlc;
1139     HRESULT hr = getVLC(&p_libvlc);
1140     if( SUCCEEDED(hr) )
1141     {
1142         libvlc_exception_t ex;
1143         libvlc_exception_init(&ex);
1144
1145         Instance()->playlist_delete_item(item, &ex);
1146         hr = exception_bridge(&ex);;
1147     }
1148     return hr;
1149 };
1150
1151 STDMETHODIMP VLCPlaylist::get_items(IVLCPlaylistItems** obj)
1152 {
1153     if( NULL == obj )
1154         return E_POINTER;
1155
1156     *obj = _p_vlcplaylistitems;
1157     if( NULL != _p_vlcplaylistitems )
1158     {
1159         _p_vlcplaylistitems->AddRef();
1160         return NOERROR;
1161     }
1162     return E_OUTOFMEMORY;
1163 };
1164
1165 /****************************************************************************/
1166
1167 STDMETHODIMP VLCSubtitle::get_track(long* spu)
1168 {
1169     if( NULL == spu )
1170         return E_POINTER;
1171
1172     libvlc_media_player_t *p_md;
1173     HRESULT hr = getMD(&p_md);
1174     if( SUCCEEDED(hr) )
1175     {
1176         libvlc_exception_t ex;
1177         libvlc_exception_init(&ex);
1178
1179         *spu = libvlc_video_get_spu(p_md, &ex);
1180         hr = exception_bridge(&ex);
1181     }
1182     return hr;
1183 };
1184
1185 STDMETHODIMP VLCSubtitle::put_track(long spu)
1186 {
1187     libvlc_media_player_t *p_md;
1188     HRESULT hr = getMD(&p_md);
1189     if( SUCCEEDED(hr) )
1190     {
1191         libvlc_exception_t ex;
1192         libvlc_exception_init(&ex);
1193
1194         libvlc_video_set_spu(p_md, spu, &ex);
1195         hr = exception_bridge(&ex);
1196     }
1197     return hr;
1198 };
1199
1200 STDMETHODIMP VLCSubtitle::get_count(long* spuNumber)
1201 {
1202     if( NULL == spuNumber )
1203         return E_POINTER;
1204
1205     libvlc_media_player_t *p_md;
1206     HRESULT hr = getMD(&p_md);
1207     if( SUCCEEDED(hr) )
1208     {
1209         libvlc_exception_t ex;
1210         libvlc_exception_init(&ex);
1211         // get the number of video subtitle available and return it
1212         *spuNumber = libvlc_video_get_spu_count(p_md, &ex);
1213         hr = exception_bridge(&ex);
1214     }
1215     return hr;
1216 };
1217
1218
1219 STDMETHODIMP VLCSubtitle::description(long nameID, BSTR* name)
1220 {
1221     if( NULL == name )
1222        return E_POINTER;
1223
1224     libvlc_media_player_t* p_md;
1225     libvlc_exception_t ex;
1226     libvlc_exception_init(&ex);
1227
1228     HRESULT hr = getMD(&p_md);
1229     if( SUCCEEDED(hr) )
1230     {
1231         int i, i_limit;
1232         const char *psz_name;
1233         libvlc_track_description_t *p_spuDesc;
1234
1235         // get subtitles description
1236         p_spuDesc = libvlc_video_get_spu_description(p_md, &ex);
1237         hr = exception_bridge(&ex);
1238         if( FAILED(hr) )
1239             return hr;
1240
1241         // get the number of available subtitle
1242         i_limit = libvlc_video_get_spu_count(p_md, &ex);
1243         hr = exception_bridge(&ex);
1244         if( FAILED(hr) )
1245             return hr;
1246
1247         // check if the number given is a good one
1248         if ( ( nameID > ( i_limit -1 ) ) || ( nameID < 0 ) )
1249             return E_FAIL;
1250
1251         // get the good spuDesc
1252         for( i = 0 ; i < nameID ; i++ )
1253         {
1254             p_spuDesc = p_spuDesc->p_next;
1255         }
1256         // get the subtitle name
1257         psz_name = p_spuDesc->psz_name;
1258
1259         // return it
1260         if( psz_name != NULL )
1261         {
1262             *name = BSTRFromCStr(CP_UTF8, psz_name);
1263             return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
1264         }
1265         *name = NULL;
1266         return E_FAIL;
1267     }
1268     return hr;
1269 };
1270
1271 /****************************************************************************/
1272
1273 STDMETHODIMP VLCVideo::get_fullscreen(VARIANT_BOOL* fullscreen)
1274 {
1275     if( NULL == fullscreen )
1276         return E_POINTER;
1277
1278     libvlc_media_player_t *p_md;
1279     HRESULT hr = getMD(&p_md);
1280     if( SUCCEEDED(hr) )
1281     {
1282         libvlc_exception_t ex;
1283         libvlc_exception_init(&ex);
1284
1285         *fullscreen = libvlc_get_fullscreen(p_md, &ex) ?
1286                       VARIANT_TRUE : VARIANT_FALSE;
1287         hr = exception_bridge(&ex);
1288     }
1289     return hr;
1290 };
1291
1292 STDMETHODIMP VLCVideo::put_fullscreen(VARIANT_BOOL fullscreen)
1293 {
1294     libvlc_media_player_t *p_md;
1295     HRESULT hr = getMD(&p_md);
1296     if( SUCCEEDED(hr) )
1297     {
1298         libvlc_exception_t ex;
1299         libvlc_exception_init(&ex);
1300
1301         libvlc_set_fullscreen(p_md, VARIANT_FALSE != fullscreen, &ex);
1302         hr = exception_bridge(&ex);
1303     }
1304     return hr;
1305 };
1306
1307 STDMETHODIMP VLCVideo::get_width(long* width)
1308 {
1309     if( NULL == width )
1310         return E_POINTER;
1311
1312     libvlc_media_player_t *p_md;
1313     HRESULT hr = getMD(&p_md);
1314     if( SUCCEEDED(hr) )
1315     {
1316         libvlc_exception_t ex;
1317         libvlc_exception_init(&ex);
1318
1319         *width = libvlc_video_get_width(p_md, &ex);
1320         hr = exception_bridge(&ex);
1321     }
1322     return hr;
1323 };
1324
1325 STDMETHODIMP VLCVideo::get_height(long* height)
1326 {
1327     if( NULL == height )
1328         return E_POINTER;
1329
1330     libvlc_media_player_t *p_md;
1331     HRESULT hr = getMD(&p_md);
1332     if( SUCCEEDED(hr) )
1333     {
1334         libvlc_exception_t ex;
1335         libvlc_exception_init(&ex);
1336
1337         *height = libvlc_video_get_height(p_md, &ex);
1338         hr = exception_bridge(&ex);
1339     }
1340     return hr;
1341 };
1342
1343 STDMETHODIMP VLCVideo::get_aspectRatio(BSTR* aspect)
1344 {
1345     if( NULL == aspect )
1346         return E_POINTER;
1347
1348     libvlc_media_player_t *p_md;
1349     HRESULT hr = getMD(&p_md);
1350     if( SUCCEEDED(hr) )
1351     {
1352         libvlc_exception_t ex;
1353         libvlc_exception_init(&ex);
1354
1355         char *psz_aspect = libvlc_video_get_aspect_ratio(p_md, &ex);
1356
1357         hr = exception_bridge(&ex);
1358         if( SUCCEEDED(hr) && NULL != psz_aspect )
1359         {
1360             *aspect = BSTRFromCStr(CP_UTF8, psz_aspect);
1361             if( NULL == *aspect )
1362                 hr = E_OUTOFMEMORY;
1363         } else if( NULL == psz_aspect) hr = E_OUTOFMEMORY; // strdup("") failed
1364         free( psz_aspect );
1365     }
1366     return hr;
1367 };
1368
1369 STDMETHODIMP VLCVideo::put_aspectRatio(BSTR aspect)
1370 {
1371     if( NULL == aspect )
1372         return E_POINTER;
1373
1374     libvlc_media_player_t *p_md;
1375     HRESULT hr = getMD(&p_md);
1376     if( SUCCEEDED(hr) )
1377     {
1378         libvlc_exception_t ex;
1379         libvlc_exception_init(&ex);
1380
1381         char *psz_aspect = CStrFromBSTR(CP_UTF8, aspect);
1382         if( NULL == psz_aspect )
1383         {
1384             return E_OUTOFMEMORY;
1385         }
1386
1387         libvlc_video_set_aspect_ratio(p_md, psz_aspect, &ex);
1388
1389         CoTaskMemFree(psz_aspect);
1390         hr = exception_bridge(&ex);
1391     }
1392     return hr;
1393 };
1394
1395 STDMETHODIMP VLCVideo::get_subtitle(long* spu)
1396 {
1397     if( NULL == spu )
1398         return E_POINTER;
1399
1400     libvlc_media_player_t *p_md;
1401     HRESULT hr = getMD(&p_md);
1402     if( SUCCEEDED(hr) )
1403     {
1404         libvlc_exception_t ex;
1405         libvlc_exception_init(&ex);
1406
1407         *spu = libvlc_video_get_spu(p_md, &ex);
1408         hr = exception_bridge(&ex);
1409     }
1410     return hr;
1411 };
1412
1413 STDMETHODIMP VLCVideo::put_subtitle(long spu)
1414 {
1415     libvlc_media_player_t *p_md;
1416     HRESULT hr = getMD(&p_md);
1417     if( SUCCEEDED(hr) )
1418     {
1419         libvlc_exception_t ex;
1420         libvlc_exception_init(&ex);
1421
1422         libvlc_video_set_spu(p_md, spu, &ex);
1423         hr = exception_bridge(&ex);
1424     }
1425     return hr;
1426 };
1427
1428 STDMETHODIMP VLCVideo::get_crop(BSTR* geometry)
1429 {
1430     if( NULL == geometry )
1431         return E_POINTER;
1432
1433     libvlc_media_player_t *p_md;
1434     HRESULT hr = getMD(&p_md);
1435     if( SUCCEEDED(hr) )
1436     {
1437         libvlc_exception_t ex;
1438         libvlc_exception_init(&ex);
1439
1440         char *psz_geometry = libvlc_video_get_crop_geometry(p_md, &ex);
1441
1442         hr = exception_bridge(&ex);
1443         if( SUCCEEDED(&ex) && NULL != psz_geometry )
1444         {
1445             *geometry = BSTRFromCStr(CP_UTF8, psz_geometry);
1446             if( NULL == geometry ) hr = E_OUTOFMEMORY;
1447         } else if( NULL == psz_geometry ) hr = E_OUTOFMEMORY;
1448         free( psz_geometry );
1449     }
1450     return hr;
1451 };
1452
1453 STDMETHODIMP VLCVideo::put_crop(BSTR geometry)
1454 {
1455     if( NULL == geometry )
1456         return E_POINTER;
1457
1458     if( 0 == SysStringLen(geometry) )
1459         return E_INVALIDARG;
1460
1461     libvlc_media_player_t *p_md;
1462     HRESULT hr = getMD(&p_md);
1463     if( SUCCEEDED(hr) )
1464     {
1465         libvlc_exception_t ex;
1466         libvlc_exception_init(&ex);
1467
1468         char *psz_geometry = CStrFromBSTR(CP_UTF8, geometry);
1469         if( NULL == psz_geometry )
1470         {
1471             return E_OUTOFMEMORY;
1472         }
1473
1474         libvlc_video_set_crop_geometry(p_md, psz_geometry, &ex);
1475
1476         CoTaskMemFree(psz_geometry);
1477         hr = exception_bridge(&ex);
1478     }
1479     return hr;
1480 };
1481
1482 STDMETHODIMP VLCVideo::get_teletext(long* page)
1483 {
1484     if( NULL == page )
1485         return E_POINTER;
1486
1487     libvlc_media_player_t *p_md;
1488     HRESULT hr = getMD(&p_md);
1489     if( SUCCEEDED(hr) )
1490     {
1491         libvlc_exception_t ex;
1492         libvlc_exception_init(&ex);
1493
1494         *page = libvlc_video_get_teletext(p_md, &ex);
1495         hr = exception_bridge(&ex);
1496     }
1497     return hr;
1498 };
1499
1500 STDMETHODIMP VLCVideo::put_teletext(long page)
1501 {
1502     libvlc_media_player_t *p_md;
1503     HRESULT hr = getMD(&p_md);
1504     if( SUCCEEDED(hr) )
1505     {
1506         libvlc_exception_t ex;
1507         libvlc_exception_init(&ex);
1508
1509         libvlc_video_set_teletext(p_md, page, &ex);
1510         hr = exception_bridge(&ex);
1511     }
1512     return hr;
1513 };
1514
1515 STDMETHODIMP VLCVideo::deinterlaceDisable()
1516 {
1517     libvlc_media_player_t *p_md;
1518     HRESULT hr = getMD(&p_md);
1519     if( SUCCEEDED(hr) )
1520     {
1521         libvlc_exception_t ex;
1522         libvlc_exception_init(&ex);
1523
1524         libvlc_video_set_deinterlace(p_md, 0, "", &ex);
1525         hr = exception_bridge(&ex);
1526     }
1527     return hr;
1528 };
1529
1530 STDMETHODIMP VLCVideo::deinterlaceEnable(BSTR mode)
1531 {
1532     libvlc_media_player_t *p_md;
1533     HRESULT hr = getMD(&p_md);
1534     if( SUCCEEDED(hr) )
1535     {
1536         libvlc_exception_t ex;
1537         libvlc_exception_init(&ex);
1538         /* get deinterlace mode from the user */
1539         char *psz_mode = CStrFromBSTR(CP_UTF8, mode);
1540         /* enable deinterlace filter if possible */
1541         libvlc_video_set_deinterlace(p_md, 1, psz_mode, &ex);
1542         hr = exception_bridge(&ex);
1543         CoTaskMemFree(psz_mode);
1544     }
1545     return hr;
1546 };
1547
1548 STDMETHODIMP VLCVideo::takeSnapshot(LPPICTUREDISP* picture)
1549 {
1550     if( NULL == picture )
1551         return E_POINTER;
1552
1553     libvlc_media_player_t *p_md;
1554     HRESULT hr = getMD(&p_md);
1555     if( SUCCEEDED(hr) )
1556     {
1557         libvlc_exception_t ex;
1558         libvlc_exception_init(&ex);
1559
1560         static int uniqueId = 0;
1561         TCHAR path[MAX_PATH+1];
1562
1563         int pathlen = GetTempPath(MAX_PATH-24, path);
1564         if( (0 == pathlen) || (pathlen > (MAX_PATH-24)) )
1565             return E_FAIL;
1566
1567         /* check temp directory path by openning it */
1568         {
1569             HANDLE dirHandle = CreateFile(path, GENERIC_READ,
1570                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
1571                        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1572             if( INVALID_HANDLE_VALUE == dirHandle )
1573             {
1574                 Instance()->setErrorInfo(IID_IVLCVideo,
1575                         "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
1576                 return E_FAIL;
1577             }
1578             else
1579             {
1580                 BY_HANDLE_FILE_INFORMATION bhfi;
1581                 BOOL res = GetFileInformationByHandle(dirHandle, &bhfi);
1582                 CloseHandle(dirHandle);
1583                 if( !res || !(bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
1584                 {
1585                     Instance()->setErrorInfo(IID_IVLCVideo,
1586                             "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
1587                     return E_FAIL;
1588                 }
1589             }
1590         }
1591
1592         TCHAR filepath[MAX_PATH+1];
1593
1594         _stprintf(filepath, TEXT("%sAXVLC%lXS%lX.bmp"),
1595                  path, GetCurrentProcessId(), ++uniqueId);
1596
1597 #ifdef _UNICODE
1598         /* reuse path storage for UTF8 string */
1599         char *psz_filepath = (char *)path;
1600         WCHAR* wpath = filepath;
1601 #else
1602         char *psz_filepath = path;
1603         /* first convert to unicode using current code page */
1604         WCHAR wpath[MAX_PATH+1];
1605         if( 0 == MultiByteToWideChar(CP_ACP, 0, filepath, -1,
1606                                      wpath, sizeof(wpath)/sizeof(WCHAR)) )
1607             return E_FAIL;
1608 #endif
1609         /* convert to UTF8 */
1610         pathlen = WideCharToMultiByte(CP_UTF8, 0, wpath, -1,
1611                                       psz_filepath, sizeof(path), NULL, NULL);
1612         // fail if path is 0 or too short (i.e pathlen is the same as
1613         // storage size)
1614
1615         if( (0 == pathlen) || (sizeof(path) == pathlen) )
1616             return E_FAIL;
1617
1618         /* take snapshot into file */
1619         libvlc_video_take_snapshot(p_md, psz_filepath, 0, 0, &ex);
1620         hr = exception_bridge(&ex);
1621         if( SUCCEEDED(hr) )
1622         {
1623             /* open snapshot file */
1624             HANDLE snapPic = LoadImage(NULL, filepath, IMAGE_BITMAP, 0, 0,
1625                                        LR_CREATEDIBSECTION|LR_LOADFROMFILE);
1626             if( snapPic )
1627             {
1628                 PICTDESC snapDesc;
1629
1630                 snapDesc.cbSizeofstruct = sizeof(PICTDESC);
1631                 snapDesc.picType        = PICTYPE_BITMAP;
1632                 snapDesc.bmp.hbitmap    = (HBITMAP)snapPic;
1633                 snapDesc.bmp.hpal       = NULL;
1634
1635                 hr = OleCreatePictureIndirect(&snapDesc, IID_IPictureDisp,
1636                                               TRUE, (LPVOID*)picture);
1637                 if( FAILED(hr) )
1638                 {
1639                     *picture = NULL;
1640                     DeleteObject(snapPic);
1641                 }
1642             }
1643             DeleteFile(filepath);
1644         }
1645     }
1646     return hr;
1647 };
1648
1649 STDMETHODIMP VLCVideo::toggleFullscreen()
1650 {
1651     libvlc_media_player_t *p_md;
1652     HRESULT hr = getMD(&p_md);
1653     if( SUCCEEDED(hr) )
1654     {
1655         libvlc_exception_t ex;
1656         libvlc_exception_init(&ex);
1657
1658         libvlc_toggle_fullscreen(p_md, &ex);
1659         hr = exception_bridge(&ex);
1660     }
1661     return hr;
1662 };
1663
1664 STDMETHODIMP VLCVideo::toggleTeletext()
1665 {
1666     libvlc_media_player_t *p_md;
1667     HRESULT hr = getMD(&p_md);
1668     if( SUCCEEDED(hr) )
1669     {
1670         libvlc_exception_t ex;
1671         libvlc_exception_init(&ex);
1672
1673         libvlc_toggle_teletext(p_md, &ex);
1674         hr = exception_bridge(&ex);
1675     }
1676     return hr;
1677 };
1678
1679 STDMETHODIMP VLCVideo::get_marquee(IVLCMarquee** obj)
1680 {
1681     return object_get(obj,_p_vlcmarquee);
1682 }
1683
1684 STDMETHODIMP VLCVideo::get_logo(IVLCLogo** obj)
1685 {
1686     return object_get(obj,_p_vlclogo);
1687 }
1688
1689
1690 /****************************************************************************/
1691
1692 HRESULT VLCLogo::do_put_int(unsigned idx, LONG val)
1693 {
1694     libvlc_media_player_t *p_md;
1695     HRESULT hr = getMD(&p_md);
1696     if( SUCCEEDED(hr) )
1697     {
1698         libvlc_exception_t ex;
1699         libvlc_exception_init(&ex);
1700         libvlc_video_set_logo_int(p_md, idx, val, &ex);
1701         hr = exception_bridge(&ex);
1702     }
1703     return hr;
1704 }
1705
1706 HRESULT VLCLogo::do_get_int(unsigned idx, LONG *val)
1707 {
1708     if( NULL == val )
1709         return E_POINTER;
1710
1711     libvlc_media_player_t *p_md;
1712     HRESULT hr = getMD(&p_md);
1713     if( SUCCEEDED(hr) )
1714     {
1715         libvlc_exception_t ex;
1716         libvlc_exception_init(&ex);
1717         *val = libvlc_video_get_logo_int(p_md, idx, &ex);
1718         hr = exception_bridge(&ex);
1719     }
1720     return hr;
1721 }
1722
1723 STDMETHODIMP VLCLogo::file(BSTR fname)
1724 {
1725     libvlc_media_player_t *p_md;
1726     HRESULT hr = getMD(&p_md);
1727
1728     char *n = CStrFromBSTR(CP_UTF8, fname);
1729     if( !n ) hr = E_OUTOFMEMORY;
1730
1731     if( SUCCEEDED(hr) )
1732     {
1733         libvlc_exception_t ex;
1734         libvlc_exception_init(&ex);
1735         libvlc_video_set_logo_string(p_md, libvlc_logo_file, n, &ex);
1736         hr = exception_bridge(&ex);
1737     }
1738
1739     CoTaskMemFree(n);
1740     return hr;
1741 }
1742
1743 STDMETHODIMP VLCLogo::get_position(BSTR* val)
1744 {
1745     if( NULL == val )
1746         return E_POINTER;
1747
1748     LONG i;
1749     HRESULT hr = do_get_int(libvlc_logo_position, &i);
1750
1751     if(SUCCEEDED(hr))
1752         *val = BSTRFromCStr(CP_UTF8, position_bynumber(i));
1753
1754     return hr;
1755 }
1756
1757 STDMETHODIMP VLCLogo::put_position(BSTR val)
1758 {
1759     char *n = CStrFromBSTR(CP_UTF8, val);
1760     if( !n ) return E_OUTOFMEMORY;
1761
1762     size_t i;
1763     HRESULT hr;
1764     if( position_byname( n, i ) )
1765         hr = do_put_int(libvlc_logo_position,i);
1766     else
1767         hr = E_INVALIDARG;
1768
1769     CoTaskMemFree(n);
1770     return hr;
1771 }
1772
1773 /****************************************************************************/
1774
1775 VLCControl2::VLCControl2(VLCPlugin *p_instance) :
1776     _p_instance(p_instance),
1777     _p_typeinfo(NULL),
1778     _p_vlcaudio(new VLCAudio(p_instance)),
1779     _p_vlcinput(new VLCInput(p_instance)),
1780     _p_vlclog(new VLCLog(p_instance)),
1781     _p_vlcplaylist(new VLCPlaylist(p_instance)),
1782     _p_vlcsubtitle(new VLCSubtitle(p_instance)),
1783     _p_vlcvideo(new VLCVideo(p_instance))
1784 {
1785 }
1786
1787 VLCControl2::~VLCControl2()
1788 {
1789     delete _p_vlcvideo;
1790     delete _p_vlcsubtitle;
1791     delete _p_vlcplaylist;
1792     delete _p_vlclog;
1793     delete _p_vlcinput;
1794     delete _p_vlcaudio;
1795     if( _p_typeinfo )
1796         _p_typeinfo->Release();
1797 };
1798
1799 HRESULT VLCControl2::loadTypeInfo(void)
1800 {
1801     HRESULT hr = NOERROR;
1802     if( NULL == _p_typeinfo )
1803     {
1804         ITypeLib *p_typelib;
1805
1806         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1807         if( SUCCEEDED(hr) )
1808         {
1809             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl2, &_p_typeinfo);
1810             if( FAILED(hr) )
1811             {
1812                 _p_typeinfo = NULL;
1813             }
1814             p_typelib->Release();
1815         }
1816     }
1817     return hr;
1818 };
1819
1820 STDMETHODIMP VLCControl2::GetTypeInfoCount(UINT* pctInfo)
1821 {
1822     if( NULL == pctInfo )
1823         return E_INVALIDARG;
1824
1825     if( SUCCEEDED(loadTypeInfo()) )
1826         *pctInfo = 1;
1827     else
1828         *pctInfo = 0;
1829
1830     return NOERROR;
1831 };
1832
1833 STDMETHODIMP VLCControl2::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1834 {
1835     if( NULL == ppTInfo )
1836         return E_INVALIDARG;
1837
1838     if( SUCCEEDED(loadTypeInfo()) )
1839     {
1840         _p_typeinfo->AddRef();
1841         *ppTInfo = _p_typeinfo;
1842         return NOERROR;
1843     }
1844     *ppTInfo = NULL;
1845     return E_NOTIMPL;
1846 };
1847
1848 STDMETHODIMP VLCControl2::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1849         UINT cNames, LCID lcid, DISPID* rgDispID)
1850 {
1851     if( SUCCEEDED(loadTypeInfo()) )
1852     {
1853         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1854     }
1855     return E_NOTIMPL;
1856 };
1857
1858 STDMETHODIMP VLCControl2::Invoke(DISPID dispIdMember, REFIID riid,
1859         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1860         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1861 {
1862     if( SUCCEEDED(loadTypeInfo()) )
1863     {
1864         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1865                 pVarResult, pExcepInfo, puArgErr);
1866     }
1867     return E_NOTIMPL;
1868 };
1869
1870 STDMETHODIMP VLCControl2::get_AutoLoop(VARIANT_BOOL *autoloop)
1871 {
1872     if( NULL == autoloop )
1873         return E_POINTER;
1874
1875     *autoloop = _p_instance->getAutoLoop() ? VARIANT_TRUE: VARIANT_FALSE;
1876     return S_OK;
1877 };
1878
1879 STDMETHODIMP VLCControl2::put_AutoLoop(VARIANT_BOOL autoloop)
1880 {
1881     _p_instance->setAutoLoop((VARIANT_FALSE != autoloop) ? TRUE: FALSE);
1882     return S_OK;
1883 };
1884
1885 STDMETHODIMP VLCControl2::get_AutoPlay(VARIANT_BOOL *autoplay)
1886 {
1887     if( NULL == autoplay )
1888         return E_POINTER;
1889
1890     *autoplay = _p_instance->getAutoPlay() ? VARIANT_TRUE: VARIANT_FALSE;
1891     return S_OK;
1892 };
1893
1894 STDMETHODIMP VLCControl2::put_AutoPlay(VARIANT_BOOL autoplay)
1895 {
1896     _p_instance->setAutoPlay((VARIANT_FALSE != autoplay) ? TRUE: FALSE);
1897     return S_OK;
1898 };
1899
1900 STDMETHODIMP VLCControl2::get_BaseURL(BSTR *url)
1901 {
1902     if( NULL == url )
1903         return E_POINTER;
1904
1905     *url = SysAllocStringLen(_p_instance->getBaseURL(),
1906                 SysStringLen(_p_instance->getBaseURL()));
1907     return NOERROR;
1908 };
1909
1910 STDMETHODIMP VLCControl2::put_BaseURL(BSTR mrl)
1911 {
1912     _p_instance->setBaseURL(mrl);
1913
1914     return S_OK;
1915 };
1916
1917 STDMETHODIMP VLCControl2::get_MRL(BSTR *mrl)
1918 {
1919     if( NULL == mrl )
1920         return E_POINTER;
1921
1922     *mrl = SysAllocStringLen(_p_instance->getMRL(),
1923                 SysStringLen(_p_instance->getMRL()));
1924     return NOERROR;
1925 };
1926
1927 STDMETHODIMP VLCControl2::put_MRL(BSTR mrl)
1928 {
1929     _p_instance->setMRL(mrl);
1930
1931     return S_OK;
1932 };
1933
1934
1935 STDMETHODIMP VLCControl2::get_Toolbar(VARIANT_BOOL *visible)
1936 {
1937     if( NULL == visible )
1938         return E_POINTER;
1939
1940     /*
1941      * Note to developers
1942      *
1943      * Returning the _b_toolbar is closer to the method specification.
1944      * But returning True when toolbar is not implemented so not displayed
1945      * could be bad for ActiveX users which rely on this value to show their
1946      * own toolbar if not provided by the ActiveX.
1947      *
1948      * This is the reason why FALSE is returned, until toolbar get implemented.
1949      */
1950
1951     /* DISABLED for now */
1952     //  *visible = _p_instance->getShowToolbar() ? VARIANT_TRUE: VARIANT_FALSE;
1953
1954     *visible = VARIANT_FALSE;
1955
1956     return S_OK;
1957 };
1958
1959 STDMETHODIMP VLCControl2::put_Toolbar(VARIANT_BOOL visible)
1960 {
1961     _p_instance->setShowToolbar((VARIANT_FALSE != visible) ? TRUE: FALSE);
1962     return S_OK;
1963 };
1964
1965
1966 STDMETHODIMP VLCControl2::get_StartTime(long *seconds)
1967 {
1968     if( NULL == seconds )
1969         return E_POINTER;
1970
1971     *seconds = _p_instance->getStartTime();
1972
1973     return S_OK;
1974 };
1975
1976 STDMETHODIMP VLCControl2::put_StartTime(long seconds)
1977 {
1978     _p_instance->setStartTime(seconds);
1979
1980     return NOERROR;
1981 };
1982
1983 STDMETHODIMP VLCControl2::get_VersionInfo(BSTR *version)
1984 {
1985     if( NULL == version )
1986         return E_POINTER;
1987
1988     const char *versionStr = libvlc_get_version();
1989     if( NULL != versionStr )
1990     {
1991         *version = BSTRFromCStr(CP_UTF8, versionStr);
1992
1993         return (NULL == *version) ? E_OUTOFMEMORY : NOERROR;
1994     }
1995     *version = NULL;
1996     return E_FAIL;
1997 };
1998
1999 STDMETHODIMP VLCControl2::get_Visible(VARIANT_BOOL *isVisible)
2000 {
2001     if( NULL == isVisible )
2002         return E_POINTER;
2003
2004     *isVisible = _p_instance->getVisible() ? VARIANT_TRUE : VARIANT_FALSE;
2005
2006     return NOERROR;
2007 };
2008
2009 STDMETHODIMP VLCControl2::put_Visible(VARIANT_BOOL isVisible)
2010 {
2011     _p_instance->setVisible(isVisible != VARIANT_FALSE);
2012
2013     return NOERROR;
2014 };
2015
2016 STDMETHODIMP VLCControl2::get_Volume(long *volume)
2017 {
2018     if( NULL == volume )
2019         return E_POINTER;
2020
2021     *volume  = _p_instance->getVolume();
2022     return NOERROR;
2023 };
2024
2025 STDMETHODIMP VLCControl2::put_Volume(long volume)
2026 {
2027     _p_instance->setVolume(volume);
2028     return NOERROR;
2029 };
2030
2031 STDMETHODIMP VLCControl2::get_BackColor(OLE_COLOR *backcolor)
2032 {
2033     if( NULL == backcolor )
2034         return E_POINTER;
2035
2036     *backcolor  = _p_instance->getBackColor();
2037     return NOERROR;
2038 };
2039
2040 STDMETHODIMP VLCControl2::put_BackColor(OLE_COLOR backcolor)
2041 {
2042     _p_instance->setBackColor(backcolor);
2043     return NOERROR;
2044 };
2045
2046 STDMETHODIMP VLCControl2::get_audio(IVLCAudio** obj)
2047 {
2048     return object_get(obj,_p_vlcaudio);
2049 }
2050
2051 STDMETHODIMP VLCControl2::get_input(IVLCInput** obj)
2052 {
2053     return object_get(obj,_p_vlcinput);
2054 }
2055
2056 STDMETHODIMP VLCControl2::get_log(IVLCLog** obj)
2057 {
2058     return object_get(obj,_p_vlclog);
2059 }
2060
2061 STDMETHODIMP VLCControl2::get_playlist(IVLCPlaylist** obj)
2062 {
2063     return object_get(obj,_p_vlcplaylist);
2064 }
2065
2066 STDMETHODIMP VLCControl2::get_subtitle(IVLCSubtitle** obj)
2067 {
2068     return object_get(obj,_p_vlcsubtitle);
2069 }
2070
2071 STDMETHODIMP VLCControl2::get_video(IVLCVideo** obj)
2072 {
2073     return object_get(obj,_p_vlcvideo);
2074 }