]> git.sesse.net Git - vlc/blob - projects/activex/vlccontrol2.cpp
ActiveX: fix compilation
[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);
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) ?
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);
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 0
1490     if( SUCCEEDED(hr) )
1491     {
1492         libvlc_exception_t ex;
1493         libvlc_exception_init(&ex);
1494
1495         *page = libvlc_video_get_teletext(p_md);
1496         hr = exception_bridge(&ex);
1497     }
1498 #endif
1499     return hr;
1500 };
1501
1502 STDMETHODIMP VLCVideo::put_teletext(long page)
1503 {
1504 #warning Broken
1505     libvlc_media_player_t *p_md;
1506     HRESULT hr = getMD(&p_md);
1507 #if 0
1508     if( SUCCEEDED(hr) )
1509     {
1510         libvlc_exception_t ex;
1511         libvlc_exception_init(&ex);
1512
1513         libvlc_video_set_teletext(p_md, page);
1514         hr = exception_bridge(&ex);
1515     }
1516 #endif
1517     return hr;
1518 };
1519
1520 STDMETHODIMP VLCVideo::deinterlaceDisable()
1521 {
1522     libvlc_media_player_t *p_md;
1523     HRESULT hr = getMD(&p_md);
1524     if( SUCCEEDED(hr) )
1525     {
1526         libvlc_exception_t ex;
1527         libvlc_exception_init(&ex);
1528
1529         libvlc_video_set_deinterlace(p_md, 0, "", &ex);
1530         hr = exception_bridge(&ex);
1531     }
1532     return hr;
1533 };
1534
1535 STDMETHODIMP VLCVideo::deinterlaceEnable(BSTR mode)
1536 {
1537     libvlc_media_player_t *p_md;
1538     HRESULT hr = getMD(&p_md);
1539     if( SUCCEEDED(hr) )
1540     {
1541         libvlc_exception_t ex;
1542         libvlc_exception_init(&ex);
1543         /* get deinterlace mode from the user */
1544         char *psz_mode = CStrFromBSTR(CP_UTF8, mode);
1545         /* enable deinterlace filter if possible */
1546         libvlc_video_set_deinterlace(p_md, 1, psz_mode, &ex);
1547         hr = exception_bridge(&ex);
1548         CoTaskMemFree(psz_mode);
1549     }
1550     return hr;
1551 };
1552
1553 STDMETHODIMP VLCVideo::takeSnapshot(LPPICTUREDISP* picture)
1554 {
1555     if( NULL == picture )
1556         return E_POINTER;
1557
1558     libvlc_media_player_t *p_md;
1559     HRESULT hr = getMD(&p_md);
1560     if( SUCCEEDED(hr) )
1561     {
1562         libvlc_exception_t ex;
1563         libvlc_exception_init(&ex);
1564
1565         static int uniqueId = 0;
1566         TCHAR path[MAX_PATH+1];
1567
1568         int pathlen = GetTempPath(MAX_PATH-24, path);
1569         if( (0 == pathlen) || (pathlen > (MAX_PATH-24)) )
1570             return E_FAIL;
1571
1572         /* check temp directory path by openning it */
1573         {
1574             HANDLE dirHandle = CreateFile(path, GENERIC_READ,
1575                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
1576                        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1577             if( INVALID_HANDLE_VALUE == dirHandle )
1578             {
1579                 Instance()->setErrorInfo(IID_IVLCVideo,
1580                         "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
1581                 return E_FAIL;
1582             }
1583             else
1584             {
1585                 BY_HANDLE_FILE_INFORMATION bhfi;
1586                 BOOL res = GetFileInformationByHandle(dirHandle, &bhfi);
1587                 CloseHandle(dirHandle);
1588                 if( !res || !(bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
1589                 {
1590                     Instance()->setErrorInfo(IID_IVLCVideo,
1591                             "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
1592                     return E_FAIL;
1593                 }
1594             }
1595         }
1596
1597         TCHAR filepath[MAX_PATH+1];
1598
1599         _stprintf(filepath, TEXT("%sAXVLC%lXS%lX.bmp"),
1600                  path, GetCurrentProcessId(), ++uniqueId);
1601
1602 #ifdef _UNICODE
1603         /* reuse path storage for UTF8 string */
1604         char *psz_filepath = (char *)path;
1605         WCHAR* wpath = filepath;
1606 #else
1607         char *psz_filepath = path;
1608         /* first convert to unicode using current code page */
1609         WCHAR wpath[MAX_PATH+1];
1610         if( 0 == MultiByteToWideChar(CP_ACP, 0, filepath, -1,
1611                                      wpath, sizeof(wpath)/sizeof(WCHAR)) )
1612             return E_FAIL;
1613 #endif
1614         /* convert to UTF8 */
1615         pathlen = WideCharToMultiByte(CP_UTF8, 0, wpath, -1,
1616                                       psz_filepath, sizeof(path), NULL, NULL);
1617         // fail if path is 0 or too short (i.e pathlen is the same as
1618         // storage size)
1619
1620         if( (0 == pathlen) || (sizeof(path) == pathlen) )
1621             return E_FAIL;
1622
1623         /* take snapshot into file */
1624         libvlc_video_take_snapshot(p_md, psz_filepath, 0, 0, &ex);
1625         hr = exception_bridge(&ex);
1626         if( SUCCEEDED(hr) )
1627         {
1628             /* open snapshot file */
1629             HANDLE snapPic = LoadImage(NULL, filepath, IMAGE_BITMAP, 0, 0,
1630                                        LR_CREATEDIBSECTION|LR_LOADFROMFILE);
1631             if( snapPic )
1632             {
1633                 PICTDESC snapDesc;
1634
1635                 snapDesc.cbSizeofstruct = sizeof(PICTDESC);
1636                 snapDesc.picType        = PICTYPE_BITMAP;
1637                 snapDesc.bmp.hbitmap    = (HBITMAP)snapPic;
1638                 snapDesc.bmp.hpal       = NULL;
1639
1640                 hr = OleCreatePictureIndirect(&snapDesc, IID_IPictureDisp,
1641                                               TRUE, (LPVOID*)picture);
1642                 if( FAILED(hr) )
1643                 {
1644                     *picture = NULL;
1645                     DeleteObject(snapPic);
1646                 }
1647             }
1648             DeleteFile(filepath);
1649         }
1650     }
1651     return hr;
1652 };
1653
1654 STDMETHODIMP VLCVideo::toggleFullscreen()
1655 {
1656     libvlc_media_player_t *p_md;
1657     HRESULT hr = getMD(&p_md);
1658     if( SUCCEEDED(hr) )
1659     {
1660         libvlc_exception_t ex;
1661         libvlc_exception_init(&ex);
1662
1663         libvlc_toggle_fullscreen(p_md, &ex);
1664         hr = exception_bridge(&ex);
1665     }
1666     return hr;
1667 };
1668
1669 STDMETHODIMP VLCVideo::toggleTeletext()
1670 {
1671     libvlc_media_player_t *p_md;
1672     HRESULT hr = getMD(&p_md);
1673     if( SUCCEEDED(hr) )
1674     {
1675         libvlc_exception_t ex;
1676         libvlc_exception_init(&ex);
1677
1678         libvlc_toggle_teletext(p_md, &ex);
1679         hr = exception_bridge(&ex);
1680     }
1681     return hr;
1682 };
1683
1684 STDMETHODIMP VLCVideo::get_marquee(IVLCMarquee** obj)
1685 {
1686     return object_get(obj,_p_vlcmarquee);
1687 }
1688
1689 STDMETHODIMP VLCVideo::get_logo(IVLCLogo** obj)
1690 {
1691     return object_get(obj,_p_vlclogo);
1692 }
1693
1694
1695 /****************************************************************************/
1696
1697 HRESULT VLCLogo::do_put_int(unsigned idx, LONG val)
1698 {
1699     libvlc_media_player_t *p_md;
1700     HRESULT hr = getMD(&p_md);
1701     if( SUCCEEDED(hr) )
1702     {
1703         libvlc_exception_t ex;
1704         libvlc_exception_init(&ex);
1705         libvlc_video_set_logo_int(p_md, idx, val, &ex);
1706         hr = exception_bridge(&ex);
1707     }
1708     return hr;
1709 }
1710
1711 HRESULT VLCLogo::do_get_int(unsigned idx, LONG *val)
1712 {
1713     if( NULL == val )
1714         return E_POINTER;
1715
1716     libvlc_media_player_t *p_md;
1717     HRESULT hr = getMD(&p_md);
1718     if( SUCCEEDED(hr) )
1719     {
1720         libvlc_exception_t ex;
1721         libvlc_exception_init(&ex);
1722         *val = libvlc_video_get_logo_int(p_md, idx, &ex);
1723         hr = exception_bridge(&ex);
1724     }
1725     return hr;
1726 }
1727
1728 STDMETHODIMP VLCLogo::file(BSTR fname)
1729 {
1730     libvlc_media_player_t *p_md;
1731     HRESULT hr = getMD(&p_md);
1732
1733     char *n = CStrFromBSTR(CP_UTF8, fname);
1734     if( !n ) hr = E_OUTOFMEMORY;
1735
1736     if( SUCCEEDED(hr) )
1737     {
1738         libvlc_exception_t ex;
1739         libvlc_exception_init(&ex);
1740         libvlc_video_set_logo_string(p_md, libvlc_logo_file, n, &ex);
1741         hr = exception_bridge(&ex);
1742     }
1743
1744     CoTaskMemFree(n);
1745     return hr;
1746 }
1747
1748 STDMETHODIMP VLCLogo::get_position(BSTR* val)
1749 {
1750     if( NULL == val )
1751         return E_POINTER;
1752
1753     LONG i;
1754     HRESULT hr = do_get_int(libvlc_logo_position, &i);
1755
1756     if(SUCCEEDED(hr))
1757         *val = BSTRFromCStr(CP_UTF8, position_bynumber(i));
1758
1759     return hr;
1760 }
1761
1762 STDMETHODIMP VLCLogo::put_position(BSTR val)
1763 {
1764     char *n = CStrFromBSTR(CP_UTF8, val);
1765     if( !n ) return E_OUTOFMEMORY;
1766
1767     size_t i;
1768     HRESULT hr;
1769     if( position_byname( n, i ) )
1770         hr = do_put_int(libvlc_logo_position,i);
1771     else
1772         hr = E_INVALIDARG;
1773
1774     CoTaskMemFree(n);
1775     return hr;
1776 }
1777
1778 /****************************************************************************/
1779
1780 VLCControl2::VLCControl2(VLCPlugin *p_instance) :
1781     _p_instance(p_instance),
1782     _p_typeinfo(NULL),
1783     _p_vlcaudio(new VLCAudio(p_instance)),
1784     _p_vlcinput(new VLCInput(p_instance)),
1785     _p_vlclog(new VLCLog(p_instance)),
1786     _p_vlcplaylist(new VLCPlaylist(p_instance)),
1787     _p_vlcsubtitle(new VLCSubtitle(p_instance)),
1788     _p_vlcvideo(new VLCVideo(p_instance))
1789 {
1790 }
1791
1792 VLCControl2::~VLCControl2()
1793 {
1794     delete _p_vlcvideo;
1795     delete _p_vlcsubtitle;
1796     delete _p_vlcplaylist;
1797     delete _p_vlclog;
1798     delete _p_vlcinput;
1799     delete _p_vlcaudio;
1800     if( _p_typeinfo )
1801         _p_typeinfo->Release();
1802 };
1803
1804 HRESULT VLCControl2::loadTypeInfo(void)
1805 {
1806     HRESULT hr = NOERROR;
1807     if( NULL == _p_typeinfo )
1808     {
1809         ITypeLib *p_typelib;
1810
1811         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1812         if( SUCCEEDED(hr) )
1813         {
1814             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl2, &_p_typeinfo);
1815             if( FAILED(hr) )
1816             {
1817                 _p_typeinfo = NULL;
1818             }
1819             p_typelib->Release();
1820         }
1821     }
1822     return hr;
1823 };
1824
1825 STDMETHODIMP VLCControl2::GetTypeInfoCount(UINT* pctInfo)
1826 {
1827     if( NULL == pctInfo )
1828         return E_INVALIDARG;
1829
1830     if( SUCCEEDED(loadTypeInfo()) )
1831         *pctInfo = 1;
1832     else
1833         *pctInfo = 0;
1834
1835     return NOERROR;
1836 };
1837
1838 STDMETHODIMP VLCControl2::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1839 {
1840     if( NULL == ppTInfo )
1841         return E_INVALIDARG;
1842
1843     if( SUCCEEDED(loadTypeInfo()) )
1844     {
1845         _p_typeinfo->AddRef();
1846         *ppTInfo = _p_typeinfo;
1847         return NOERROR;
1848     }
1849     *ppTInfo = NULL;
1850     return E_NOTIMPL;
1851 };
1852
1853 STDMETHODIMP VLCControl2::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1854         UINT cNames, LCID lcid, DISPID* rgDispID)
1855 {
1856     if( SUCCEEDED(loadTypeInfo()) )
1857     {
1858         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1859     }
1860     return E_NOTIMPL;
1861 };
1862
1863 STDMETHODIMP VLCControl2::Invoke(DISPID dispIdMember, REFIID riid,
1864         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1865         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1866 {
1867     if( SUCCEEDED(loadTypeInfo()) )
1868     {
1869         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1870                 pVarResult, pExcepInfo, puArgErr);
1871     }
1872     return E_NOTIMPL;
1873 };
1874
1875 STDMETHODIMP VLCControl2::get_AutoLoop(VARIANT_BOOL *autoloop)
1876 {
1877     if( NULL == autoloop )
1878         return E_POINTER;
1879
1880     *autoloop = _p_instance->getAutoLoop() ? VARIANT_TRUE: VARIANT_FALSE;
1881     return S_OK;
1882 };
1883
1884 STDMETHODIMP VLCControl2::put_AutoLoop(VARIANT_BOOL autoloop)
1885 {
1886     _p_instance->setAutoLoop((VARIANT_FALSE != autoloop) ? TRUE: FALSE);
1887     return S_OK;
1888 };
1889
1890 STDMETHODIMP VLCControl2::get_AutoPlay(VARIANT_BOOL *autoplay)
1891 {
1892     if( NULL == autoplay )
1893         return E_POINTER;
1894
1895     *autoplay = _p_instance->getAutoPlay() ? VARIANT_TRUE: VARIANT_FALSE;
1896     return S_OK;
1897 };
1898
1899 STDMETHODIMP VLCControl2::put_AutoPlay(VARIANT_BOOL autoplay)
1900 {
1901     _p_instance->setAutoPlay((VARIANT_FALSE != autoplay) ? TRUE: FALSE);
1902     return S_OK;
1903 };
1904
1905 STDMETHODIMP VLCControl2::get_BaseURL(BSTR *url)
1906 {
1907     if( NULL == url )
1908         return E_POINTER;
1909
1910     *url = SysAllocStringLen(_p_instance->getBaseURL(),
1911                 SysStringLen(_p_instance->getBaseURL()));
1912     return NOERROR;
1913 };
1914
1915 STDMETHODIMP VLCControl2::put_BaseURL(BSTR mrl)
1916 {
1917     _p_instance->setBaseURL(mrl);
1918
1919     return S_OK;
1920 };
1921
1922 STDMETHODIMP VLCControl2::get_MRL(BSTR *mrl)
1923 {
1924     if( NULL == mrl )
1925         return E_POINTER;
1926
1927     *mrl = SysAllocStringLen(_p_instance->getMRL(),
1928                 SysStringLen(_p_instance->getMRL()));
1929     return NOERROR;
1930 };
1931
1932 STDMETHODIMP VLCControl2::put_MRL(BSTR mrl)
1933 {
1934     _p_instance->setMRL(mrl);
1935
1936     return S_OK;
1937 };
1938
1939
1940 STDMETHODIMP VLCControl2::get_Toolbar(VARIANT_BOOL *visible)
1941 {
1942     if( NULL == visible )
1943         return E_POINTER;
1944
1945     /*
1946      * Note to developers
1947      *
1948      * Returning the _b_toolbar is closer to the method specification.
1949      * But returning True when toolbar is not implemented so not displayed
1950      * could be bad for ActiveX users which rely on this value to show their
1951      * own toolbar if not provided by the ActiveX.
1952      *
1953      * This is the reason why FALSE is returned, until toolbar get implemented.
1954      */
1955
1956     /* DISABLED for now */
1957     //  *visible = _p_instance->getShowToolbar() ? VARIANT_TRUE: VARIANT_FALSE;
1958
1959     *visible = VARIANT_FALSE;
1960
1961     return S_OK;
1962 };
1963
1964 STDMETHODIMP VLCControl2::put_Toolbar(VARIANT_BOOL visible)
1965 {
1966     _p_instance->setShowToolbar((VARIANT_FALSE != visible) ? TRUE: FALSE);
1967     return S_OK;
1968 };
1969
1970
1971 STDMETHODIMP VLCControl2::get_StartTime(long *seconds)
1972 {
1973     if( NULL == seconds )
1974         return E_POINTER;
1975
1976     *seconds = _p_instance->getStartTime();
1977
1978     return S_OK;
1979 };
1980
1981 STDMETHODIMP VLCControl2::put_StartTime(long seconds)
1982 {
1983     _p_instance->setStartTime(seconds);
1984
1985     return NOERROR;
1986 };
1987
1988 STDMETHODIMP VLCControl2::get_VersionInfo(BSTR *version)
1989 {
1990     if( NULL == version )
1991         return E_POINTER;
1992
1993     const char *versionStr = libvlc_get_version();
1994     if( NULL != versionStr )
1995     {
1996         *version = BSTRFromCStr(CP_UTF8, versionStr);
1997
1998         return (NULL == *version) ? E_OUTOFMEMORY : NOERROR;
1999     }
2000     *version = NULL;
2001     return E_FAIL;
2002 };
2003
2004 STDMETHODIMP VLCControl2::get_Visible(VARIANT_BOOL *isVisible)
2005 {
2006     if( NULL == isVisible )
2007         return E_POINTER;
2008
2009     *isVisible = _p_instance->getVisible() ? VARIANT_TRUE : VARIANT_FALSE;
2010
2011     return NOERROR;
2012 };
2013
2014 STDMETHODIMP VLCControl2::put_Visible(VARIANT_BOOL isVisible)
2015 {
2016     _p_instance->setVisible(isVisible != VARIANT_FALSE);
2017
2018     return NOERROR;
2019 };
2020
2021 STDMETHODIMP VLCControl2::get_Volume(long *volume)
2022 {
2023     if( NULL == volume )
2024         return E_POINTER;
2025
2026     *volume  = _p_instance->getVolume();
2027     return NOERROR;
2028 };
2029
2030 STDMETHODIMP VLCControl2::put_Volume(long volume)
2031 {
2032     _p_instance->setVolume(volume);
2033     return NOERROR;
2034 };
2035
2036 STDMETHODIMP VLCControl2::get_BackColor(OLE_COLOR *backcolor)
2037 {
2038     if( NULL == backcolor )
2039         return E_POINTER;
2040
2041     *backcolor  = _p_instance->getBackColor();
2042     return NOERROR;
2043 };
2044
2045 STDMETHODIMP VLCControl2::put_BackColor(OLE_COLOR backcolor)
2046 {
2047     _p_instance->setBackColor(backcolor);
2048     return NOERROR;
2049 };
2050
2051 STDMETHODIMP VLCControl2::get_audio(IVLCAudio** obj)
2052 {
2053     return object_get(obj,_p_vlcaudio);
2054 }
2055
2056 STDMETHODIMP VLCControl2::get_input(IVLCInput** obj)
2057 {
2058     return object_get(obj,_p_vlcinput);
2059 }
2060
2061 STDMETHODIMP VLCControl2::get_log(IVLCLog** obj)
2062 {
2063     return object_get(obj,_p_vlclog);
2064 }
2065
2066 STDMETHODIMP VLCControl2::get_playlist(IVLCPlaylist** obj)
2067 {
2068     return object_get(obj,_p_vlcplaylist);
2069 }
2070
2071 STDMETHODIMP VLCControl2::get_subtitle(IVLCSubtitle** obj)
2072 {
2073     return object_get(obj,_p_vlcsubtitle);
2074 }
2075
2076 STDMETHODIMP VLCControl2::get_video(IVLCVideo** obj)
2077 {
2078     return object_get(obj,_p_vlcvideo);
2079 }