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