]> git.sesse.net Git - vlc/blob - projects/activex/vlccontrol2.cpp
0bf7952c0bf4d5d031933dfb47ba2c3fb3ea5609
[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::loadTypeInfo(REFIID riid)
40 {
41     // if( _ti ) return NOERROR; // unnecessairy
42
43     ITypeLib *p_typelib;
44     HRESULT hr = _plug->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
45     if( SUCCEEDED(hr) )
46     {
47         hr = p_typelib->GetTypeInfoOfGuid(riid, &_ti);
48         if( FAILED(hr) ) _ti = NULL;
49         p_typelib->Release();
50     }
51     return hr;
52 }
53
54 #define BIND_INTERFACE( class ) \
55     template<> REFIID VLCInterface<class, I##class>::_riid = IID_I##class;
56
57 BIND_INTERFACE( VLCAudio )
58 BIND_INTERFACE( VLCInput )
59 BIND_INTERFACE( VLCMarquee )
60 BIND_INTERFACE( VLCLogo )
61 BIND_INTERFACE( VLCDeinterlace )
62 BIND_INTERFACE( VLCPlaylistItems )
63 BIND_INTERFACE( VLCPlaylist )
64 BIND_INTERFACE( VLCVideo )
65 BIND_INTERFACE( VLCSubtitle )
66
67 #undef  BIND_INTERFACE
68
69 template<class I> static inline
70 HRESULT object_get(I **dst, I *src)
71 {
72     if( NULL == dst )
73         return E_POINTER;
74
75     *dst = src;
76     if( NULL != src )
77     {
78         src->AddRef();
79         return NOERROR;
80     }
81     return E_OUTOFMEMORY;
82 }
83
84 static inline
85 VARIANT_BOOL varbool(bool b) { return b ? VARIANT_TRUE : VARIANT_FALSE; }
86
87 // ---------
88
89 STDMETHODIMP VLCAudio::get_mute(VARIANT_BOOL* mute)
90 {
91     if( NULL == mute )
92         return E_POINTER;
93
94     libvlc_media_player_t *p_md;
95     HRESULT hr = getMD(&p_md);
96     if( SUCCEEDED(hr) )
97         *mute = varbool( libvlc_audio_get_mute(p_md) );
98     return hr;
99 };
100
101 STDMETHODIMP VLCAudio::put_mute(VARIANT_BOOL mute)
102 {
103     libvlc_media_player_t *p_md;
104     HRESULT hr = getMD(&p_md);
105     if( SUCCEEDED(hr) )
106         libvlc_audio_set_mute(p_md, VARIANT_FALSE != mute);
107     return hr;
108 };
109
110 STDMETHODIMP VLCAudio::get_volume(long* volume)
111 {
112     if( NULL == volume )
113         return E_POINTER;
114
115     libvlc_media_player_t *p_md;
116     HRESULT hr = getMD(&p_md);
117     if( SUCCEEDED(hr) )
118         *volume = libvlc_audio_get_volume(p_md);
119     return hr;
120 };
121
122 STDMETHODIMP VLCAudio::put_volume(long volume)
123 {
124     libvlc_media_player_t *p_md;
125     HRESULT hr = getMD(&p_md);
126     if( SUCCEEDED(hr) )
127     {
128         libvlc_audio_set_volume(p_md, volume);
129     }
130     return hr;
131 };
132
133 STDMETHODIMP VLCAudio::get_track(long* track)
134 {
135     if( NULL == track )
136         return E_POINTER;
137
138     libvlc_media_player_t* p_md;
139     HRESULT hr = getMD(&p_md);
140     if( SUCCEEDED(hr) )
141     {
142         *track = libvlc_audio_get_track(p_md);
143     }
144     return hr;
145 };
146
147 STDMETHODIMP VLCAudio::put_track(long track)
148 {
149     libvlc_media_player_t *p_md;
150     HRESULT hr = getMD(&p_md);
151     if( SUCCEEDED(hr) )
152     {
153         libvlc_audio_set_track(p_md, track);
154     }
155     return hr;
156 };
157
158 STDMETHODIMP VLCAudio::get_count(long* trackNumber)
159 {
160     if( NULL == trackNumber )
161         return E_POINTER;
162
163     libvlc_media_player_t* p_md;
164     HRESULT hr = getMD(&p_md);
165     if( SUCCEEDED(hr) )
166     {
167         // get the number of audio track available and return it
168         *trackNumber = libvlc_audio_get_track_count(p_md);
169     }
170     return hr;
171 };
172
173
174 STDMETHODIMP VLCAudio::description(long trackID, BSTR* name)
175 {
176     if( NULL == name )
177         return E_POINTER;
178
179     libvlc_media_player_t* p_md;
180
181     HRESULT hr = getMD(&p_md);
182     if( SUCCEEDED(hr) )
183     {
184         int i, i_limit;
185         const char *psz_name;
186         libvlc_track_description_t *p_trackDesc;
187
188         // get tracks description
189         p_trackDesc = libvlc_audio_get_track_description(p_md);
190         if( !p_trackDesc )
191             return E_FAIL;
192
193         //get the number of available track
194         i_limit = libvlc_audio_get_track_count(p_md);
195         if( i_limit < 0 )
196             return E_FAIL;
197
198         // check if the number given is a good one
199         if ( ( trackID > ( i_limit -1 ) ) || ( trackID < 0 ) )
200                 return E_FAIL;
201
202         // get the good trackDesc
203         for( i = 0 ; i < trackID ; i++ )
204         {
205             p_trackDesc = p_trackDesc->p_next;
206         }
207         // get the track name
208         psz_name = p_trackDesc->psz_name;
209
210         // return it
211         if( psz_name != NULL )
212         {
213             *name = BSTRFromCStr(CP_UTF8, psz_name);
214             return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
215         }
216         *name = NULL;
217         return E_FAIL;
218     }
219     return hr;
220 };
221
222 STDMETHODIMP VLCAudio::get_channel(long *channel)
223 {
224     if( NULL == channel )
225         return E_POINTER;
226
227     libvlc_media_player_t *p_md;
228     HRESULT hr = getMD(&p_md);
229     if( SUCCEEDED(hr) )
230     {
231         *channel = libvlc_audio_get_channel(p_md);
232     }
233     return hr;
234 };
235
236 STDMETHODIMP VLCAudio::put_channel(long channel)
237 {
238     libvlc_media_player_t *p_md;
239     HRESULT hr = getMD(&p_md);
240     if( SUCCEEDED(hr) )
241     {
242         libvlc_audio_set_channel(p_md, channel);
243     }
244     return hr;
245 };
246
247 STDMETHODIMP VLCAudio::toggleMute()
248 {
249     libvlc_media_player_t *p_md;
250     HRESULT hr = getMD(&p_md);
251     if( SUCCEEDED(hr) )
252         libvlc_audio_toggle_mute(p_md);
253     return hr;
254 };
255
256 /****************************************************************************/
257
258 STDMETHODIMP VLCDeinterlace::disable()
259 {
260     libvlc_media_player_t *p_md;
261     HRESULT hr = getMD(&p_md);
262     if( SUCCEEDED(hr) )
263     {
264         libvlc_video_set_deinterlace(p_md, "");
265     }
266     return hr;
267 }
268
269 STDMETHODIMP VLCDeinterlace::enable(BSTR mode)
270 {
271     libvlc_media_player_t *p_md;
272     HRESULT hr = getMD(&p_md);
273     if( SUCCEEDED(hr) )
274     {
275         char *psz_mode = CStrFromBSTR(CP_UTF8, mode);
276         libvlc_video_set_deinterlace(p_md, psz_mode);
277         CoTaskMemFree(psz_mode);
278     }
279     return hr;
280 }
281
282 /****************************************************************************/
283
284 STDMETHODIMP VLCInput::get_length(double* length)
285 {
286     if( NULL == length )
287         return E_POINTER;
288     *length = 0;
289
290     libvlc_media_player_t *p_md;
291     HRESULT hr = getMD(&p_md);
292     if( SUCCEEDED(hr) )
293     {
294         *length = (double)libvlc_media_player_get_length(p_md);
295     }
296     return hr;
297 };
298
299 STDMETHODIMP VLCInput::get_position(double* position)
300 {
301     if( NULL == position )
302         return E_POINTER;
303
304     *position = 0.0f;
305     libvlc_media_player_t *p_md;
306     HRESULT hr = getMD(&p_md);
307     if( SUCCEEDED(hr) )
308     {
309         *position = libvlc_media_player_get_position(p_md);
310     }
311     return hr;
312 };
313
314 STDMETHODIMP VLCInput::put_position(double position)
315 {
316     libvlc_media_player_t *p_md;
317     HRESULT hr = getMD(&p_md);
318     if( SUCCEEDED(hr) )
319     {
320         libvlc_media_player_set_position(p_md, position);
321     }
322     return hr;
323 };
324
325 STDMETHODIMP VLCInput::get_time(double* time)
326 {
327     if( NULL == time )
328         return E_POINTER;
329
330     libvlc_media_player_t *p_md;
331     HRESULT hr = getMD(&p_md);
332     if( SUCCEEDED(hr) )
333     {
334         *time = (double)libvlc_media_player_get_time(p_md);
335     }
336     return hr;
337 };
338
339 STDMETHODIMP VLCInput::put_time(double time)
340 {
341     libvlc_media_player_t *p_md;
342     HRESULT hr = getMD(&p_md);
343     if( SUCCEEDED(hr) )
344     {
345         libvlc_media_player_set_time(p_md, (int64_t)time);
346     }
347     return hr;
348 };
349
350 STDMETHODIMP VLCInput::get_state(long* state)
351 {
352     if( NULL == state )
353         return E_POINTER;
354
355     libvlc_media_player_t *p_md;
356     HRESULT hr = getMD(&p_md);
357     if( SUCCEEDED(hr) )
358     {
359         *state = libvlc_media_player_get_state(p_md);
360     }
361     return hr;
362 };
363
364 STDMETHODIMP VLCInput::get_rate(double* rate)
365 {
366     if( NULL == rate )
367         return E_POINTER;
368
369     libvlc_media_player_t *p_md;
370     HRESULT hr = getMD(&p_md);
371     if( SUCCEEDED(hr) )
372     {
373         *rate = libvlc_media_player_get_rate(p_md);
374     }
375     return hr;
376 };
377
378 STDMETHODIMP VLCInput::put_rate(double rate)
379 {
380     libvlc_media_player_t *p_md;
381     HRESULT hr = getMD(&p_md);
382     if( SUCCEEDED(hr) )
383     {
384         libvlc_media_player_set_rate(p_md, rate);
385     }
386     return hr;
387 };
388
389 STDMETHODIMP VLCInput::get_fps(double* fps)
390 {
391     if( NULL == fps )
392         return E_POINTER;
393
394     *fps = 0.0;
395     libvlc_media_player_t *p_md;
396     HRESULT hr = getMD(&p_md);
397     if( SUCCEEDED(hr) )
398     {
399         *fps = libvlc_media_player_get_fps(p_md);
400     }
401     return hr;
402 };
403
404 STDMETHODIMP VLCInput::get_hasVout(VARIANT_BOOL* hasVout)
405 {
406     if( NULL == hasVout )
407         return E_POINTER;
408
409     libvlc_media_player_t *p_md;
410     HRESULT hr = getMD(&p_md);
411     if( SUCCEEDED(hr) )
412     {
413         *hasVout = varbool( libvlc_media_player_has_vout(p_md) );
414     }
415     return hr;
416 };
417
418 /****************************************************************************/
419
420 HRESULT VLCMarquee::do_put_int(unsigned idx, LONG val)
421 {
422     libvlc_media_player_t *p_md;
423     HRESULT hr = getMD(&p_md);
424     if( SUCCEEDED(hr) )
425     {
426         libvlc_video_set_marquee_int(p_md, idx, val);
427     }
428     return hr;
429 }
430
431 HRESULT VLCMarquee::do_get_int(unsigned idx, LONG *val)
432 {
433     if( NULL == val )
434         return E_POINTER;
435
436     libvlc_media_player_t *p_md;
437     HRESULT hr = getMD(&p_md);
438     if( SUCCEEDED(hr) )
439     {
440         *val = libvlc_video_get_marquee_int(p_md, idx);
441     }
442     return hr;
443 }
444
445 STDMETHODIMP VLCMarquee::get_position(BSTR* val)
446 {
447     if( NULL == val )
448         return E_POINTER;
449
450     LONG i;
451     HRESULT hr = do_get_int(libvlc_marquee_Position, &i);
452     if(SUCCEEDED(hr))
453         *val = BSTRFromCStr(CP_UTF8, position_bynumber(i));
454
455     return hr;
456 }
457
458 STDMETHODIMP VLCMarquee::put_position(BSTR val)
459 {
460     char *n = CStrFromBSTR(CP_UTF8, val);
461     if( !n ) return E_OUTOFMEMORY;
462
463     size_t i;
464     HRESULT hr;
465     if( position_byname( n, i ) )
466         hr = do_put_int(libvlc_marquee_Position,i);
467     else
468         hr = E_INVALIDARG;
469
470     CoTaskMemFree(n);
471     return hr;
472 }
473
474 STDMETHODIMP VLCMarquee::get_text(BSTR *val)
475 {
476     char *psz;
477     if( NULL == val )
478         return E_POINTER;
479
480     libvlc_media_player_t *p_md;
481     HRESULT hr = getMD(&p_md);
482     if( SUCCEEDED(hr) )
483     {
484         psz = libvlc_video_get_marquee_string(p_md, libvlc_marquee_Text);
485         if( psz )
486             *val = BSTRFromCStr(CP_UTF8, psz);
487     }
488     return hr;
489 }
490
491 STDMETHODIMP VLCMarquee::put_text(BSTR val)
492 {
493     libvlc_media_player_t *p_md;
494     HRESULT hr = getMD(&p_md);
495     if( SUCCEEDED(hr) )
496     {
497         char *psz_text = CStrFromBSTR(CP_UTF8, val);
498         libvlc_video_set_marquee_string(p_md, libvlc_marquee_Text, psz_text);
499         CoTaskMemFree(psz_text);
500     }
501     return hr;
502 }
503
504 /****************************************************************************/
505
506 STDMETHODIMP VLCPlaylistItems::get_count(long* count)
507 {
508     if( NULL == count )
509         return E_POINTER;
510
511     *count = Instance()->playlist_count();
512     return S_OK;
513 };
514
515 STDMETHODIMP VLCPlaylistItems::clear()
516 {
517     Instance()->playlist_clear();
518     return S_OK;
519 };
520
521 STDMETHODIMP VLCPlaylistItems::remove(long item)
522 {
523     libvlc_instance_t* p_libvlc;
524     HRESULT hr = getVLC(&p_libvlc);
525     if( SUCCEEDED(hr) )
526     {
527         Instance()->playlist_delete_item(item);
528     }
529     return hr;
530 };
531
532 /****************************************************************************/
533
534 STDMETHODIMP VLCPlaylist::get_itemCount(long* count)
535 {
536     if( NULL == count )
537         return E_POINTER;
538
539     *count = 0;
540     *count = Instance()->playlist_count();
541     return S_OK;
542 };
543
544 STDMETHODIMP VLCPlaylist::get_isPlaying(VARIANT_BOOL* isPlaying)
545 {
546     if( NULL == isPlaying )
547         return E_POINTER;
548
549     libvlc_media_player_t *p_md;
550     HRESULT hr = getMD(&p_md);
551     if( SUCCEEDED(hr) )
552     {
553         *isPlaying = varbool( libvlc_media_player_is_playing(p_md) );
554     }
555     return hr;
556 };
557
558 STDMETHODIMP VLCPlaylist::add(BSTR uri, VARIANT name, VARIANT options, long* item)
559 {
560     if( NULL == item )
561         return E_POINTER;
562
563     if( 0 == SysStringLen(uri) )
564         return E_INVALIDARG;
565
566     libvlc_instance_t* p_libvlc;
567     HRESULT hr = getVLC(&p_libvlc);
568     if( SUCCEEDED(hr) )
569     {
570         char *psz_uri = NULL;
571         if( SysStringLen(Instance()->getBaseURL()) > 0 )
572         {
573             /*
574             ** if the MRL a relative URL, we should end up with an absolute URL
575             */
576             LPWSTR abs_url = CombineURL(Instance()->getBaseURL(), uri);
577             if( NULL != abs_url )
578             {
579                 psz_uri = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
580                 CoTaskMemFree(abs_url);
581             }
582             else
583             {
584                 psz_uri = CStrFromBSTR(CP_UTF8, uri);
585             }
586         }
587         else
588         {
589             /*
590             ** baseURL is empty, assume MRL is absolute
591             */
592             psz_uri = CStrFromBSTR(CP_UTF8, uri);
593         }
594
595         if( NULL == psz_uri )
596         {
597             return E_OUTOFMEMORY;
598         }
599
600         int i_options;
601         char **ppsz_options;
602
603         hr = VLCControl::CreateTargetOptions(CP_UTF8, &options, &ppsz_options, &i_options);
604         if( FAILED(hr) )
605         {
606             CoTaskMemFree(psz_uri);
607             return hr;
608         }
609
610         char *psz_name = NULL;
611         VARIANT v_name;
612         VariantInit(&v_name);
613         if( SUCCEEDED(VariantChangeType(&v_name, &name, 0, VT_BSTR)) )
614         {
615             if( SysStringLen(V_BSTR(&v_name)) > 0 )
616                 psz_name = CStrFromBSTR(CP_UTF8, V_BSTR(&v_name));
617
618             VariantClear(&v_name);
619         }
620
621         *item = Instance()->playlist_add_extended_untrusted(psz_uri,
622                     i_options, const_cast<const char **>(ppsz_options));
623
624         VLCControl::FreeTargetOptions(ppsz_options, i_options);
625         CoTaskMemFree(psz_uri);
626         if( psz_name ) /* XXX Do we even need to check? */
627             CoTaskMemFree(psz_name);
628     }
629     return hr;
630 };
631
632 STDMETHODIMP VLCPlaylist::play()
633 {
634     Instance()->playlist_play();
635     return S_OK;
636 };
637
638 STDMETHODIMP VLCPlaylist::playItem(long item)
639 {
640     Instance()->playlist_play_item(item);
641     return S_OK;
642 };
643
644 STDMETHODIMP VLCPlaylist::togglePause()
645 {
646     libvlc_media_player_t* p_md;
647     HRESULT hr = getMD(&p_md);
648     if( SUCCEEDED(hr) )
649     {
650         libvlc_media_player_pause(p_md);
651     }
652     return hr;
653 };
654
655 STDMETHODIMP VLCPlaylist::stop()
656 {
657     libvlc_media_player_t *p_md;
658     HRESULT hr = getMD(&p_md);
659     if( SUCCEEDED(hr) )
660     {
661         libvlc_media_player_stop(p_md);
662     }
663     return hr;
664 };
665
666 STDMETHODIMP VLCPlaylist::next()
667 {
668     Instance()->playlist_next();
669     return S_OK;
670 };
671
672 STDMETHODIMP VLCPlaylist::prev()
673 {
674     Instance()->playlist_prev();
675     return S_OK;
676 };
677
678 STDMETHODIMP VLCPlaylist::clear()
679 {
680     Instance()->playlist_clear();
681     return S_OK;
682 };
683
684 STDMETHODIMP VLCPlaylist::removeItem(long item)
685 {
686     libvlc_instance_t* p_libvlc;
687     HRESULT hr = getVLC(&p_libvlc);
688     if( SUCCEEDED(hr) )
689     {
690         Instance()->playlist_delete_item(item);
691     }
692     return hr;
693 };
694
695 STDMETHODIMP VLCPlaylist::get_items(IVLCPlaylistItems** obj)
696 {
697     if( NULL == obj )
698         return E_POINTER;
699
700     *obj = _p_vlcplaylistitems;
701     if( NULL != _p_vlcplaylistitems )
702     {
703         _p_vlcplaylistitems->AddRef();
704         return NOERROR;
705     }
706     return E_OUTOFMEMORY;
707 };
708
709 /****************************************************************************/
710
711 STDMETHODIMP VLCSubtitle::get_track(long* spu)
712 {
713     if( NULL == spu )
714         return E_POINTER;
715
716     libvlc_media_player_t *p_md;
717     HRESULT hr = getMD(&p_md);
718     if( SUCCEEDED(hr) )
719     {
720         *spu = libvlc_video_get_spu(p_md);
721     }
722     return hr;
723 };
724
725 STDMETHODIMP VLCSubtitle::put_track(long spu)
726 {
727     libvlc_media_player_t *p_md;
728     HRESULT hr = getMD(&p_md);
729     if( SUCCEEDED(hr) )
730     {
731         libvlc_video_set_spu(p_md, spu);
732     }
733     return hr;
734 };
735
736 STDMETHODIMP VLCSubtitle::get_count(long* spuNumber)
737 {
738     if( NULL == spuNumber )
739         return E_POINTER;
740
741     libvlc_media_player_t *p_md;
742     HRESULT hr = getMD(&p_md);
743     if( SUCCEEDED(hr) )
744     {
745         // get the number of video subtitle available and return it
746         *spuNumber = libvlc_video_get_spu_count(p_md);
747     }
748     return hr;
749 };
750
751
752 STDMETHODIMP VLCSubtitle::description(long nameID, BSTR* name)
753 {
754     if( NULL == name )
755        return E_POINTER;
756
757     libvlc_media_player_t* p_md;
758
759     HRESULT hr = getMD(&p_md);
760     if( SUCCEEDED(hr) )
761     {
762         int i, i_limit;
763         const char *psz_name;
764         libvlc_track_description_t *p_spuDesc;
765
766         // get subtitles description
767         p_spuDesc = libvlc_video_get_spu_description(p_md);
768         if( !p_spuDesc )
769             return E_FAIL;
770
771         // get the number of available subtitle
772         i_limit = libvlc_video_get_spu_count(p_md);
773         if( i_limit < 0 )
774             return E_FAIL;
775
776         // check if the number given is a good one
777         if ( ( nameID > ( i_limit -1 ) ) || ( nameID < 0 ) )
778             return E_FAIL;
779
780         // get the good spuDesc
781         for( i = 0 ; i < nameID ; i++ )
782         {
783             p_spuDesc = p_spuDesc->p_next;
784         }
785         // get the subtitle name
786         psz_name = p_spuDesc->psz_name;
787
788         // return it
789         if( psz_name != NULL )
790         {
791             *name = BSTRFromCStr(CP_UTF8, psz_name);
792             return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
793         }
794         *name = NULL;
795         return E_FAIL;
796     }
797     return hr;
798 };
799
800 /****************************************************************************/
801
802 STDMETHODIMP VLCVideo::get_fullscreen(VARIANT_BOOL* fullscreen)
803 {
804     if( NULL == fullscreen )
805         return E_POINTER;
806
807     libvlc_media_player_t *p_md;
808     HRESULT hr = getMD(&p_md);
809     if( SUCCEEDED(hr) )
810     {
811         *fullscreen = varbool( libvlc_get_fullscreen(p_md) );
812     }
813     return hr;
814 };
815
816 STDMETHODIMP VLCVideo::put_fullscreen(VARIANT_BOOL fullscreen)
817 {
818     libvlc_media_player_t *p_md;
819     HRESULT hr = getMD(&p_md);
820     if( SUCCEEDED(hr) )
821     {
822         libvlc_set_fullscreen(p_md, VARIANT_FALSE != fullscreen);
823     }
824     return hr;
825 };
826
827 STDMETHODIMP VLCVideo::get_width(long* width)
828 {
829     if( NULL == width )
830         return E_POINTER;
831
832     libvlc_media_player_t *p_md;
833     HRESULT hr = getMD(&p_md);
834     if( SUCCEEDED(hr) )
835     {
836         *width = libvlc_video_get_width(p_md);
837     }
838     return hr;
839 };
840
841 STDMETHODIMP VLCVideo::get_height(long* height)
842 {
843     if( NULL == height )
844         return E_POINTER;
845
846     libvlc_media_player_t *p_md;
847     HRESULT hr = getMD(&p_md);
848     if( SUCCEEDED(hr) )
849     {
850         *height = libvlc_video_get_height(p_md);
851     }
852     return hr;
853 };
854
855 STDMETHODIMP VLCVideo::get_aspectRatio(BSTR* aspect)
856 {
857     if( NULL == aspect )
858         return E_POINTER;
859
860     libvlc_media_player_t *p_md;
861     HRESULT hr = getMD(&p_md);
862     if( SUCCEEDED(hr) )
863     {
864         char *psz_aspect = libvlc_video_get_aspect_ratio(p_md);
865
866         if( !psz_aspect )
867         {
868             *aspect = BSTRFromCStr(CP_UTF8, psz_aspect);
869             if( NULL == *aspect )
870                 hr = E_OUTOFMEMORY;
871         } else if( NULL == psz_aspect)
872                 hr = E_OUTOFMEMORY;
873         free( psz_aspect );
874     }
875     return hr;
876 };
877
878 STDMETHODIMP VLCVideo::put_aspectRatio(BSTR aspect)
879 {
880     if( NULL == aspect )
881         return E_POINTER;
882
883     libvlc_media_player_t *p_md;
884     HRESULT hr = getMD(&p_md);
885     if( SUCCEEDED(hr) )
886     {
887         char *psz_aspect = CStrFromBSTR(CP_UTF8, aspect);
888         if( !psz_aspect )
889         {
890             return E_OUTOFMEMORY;
891         }
892
893         libvlc_video_set_aspect_ratio(p_md, psz_aspect);
894
895         CoTaskMemFree(psz_aspect);
896     }
897     return hr;
898 };
899
900 STDMETHODIMP VLCVideo::get_subtitle(long* spu)
901 {
902     if( NULL == spu )
903         return E_POINTER;
904
905     libvlc_media_player_t *p_md;
906     HRESULT hr = getMD(&p_md);
907     if( SUCCEEDED(hr) )
908     {
909         *spu = libvlc_video_get_spu(p_md);
910     }
911     return hr;
912 };
913
914 STDMETHODIMP VLCVideo::put_subtitle(long spu)
915 {
916     libvlc_media_player_t *p_md;
917     HRESULT hr = getMD(&p_md);
918     if( SUCCEEDED(hr) )
919     {
920         libvlc_video_set_spu(p_md, spu);
921     }
922     return hr;
923 };
924
925 STDMETHODIMP VLCVideo::get_crop(BSTR* geometry)
926 {
927     if( NULL == geometry )
928         return E_POINTER;
929
930     libvlc_media_player_t *p_md;
931     HRESULT hr = getMD(&p_md);
932     if( SUCCEEDED(hr) )
933     {
934         char *psz_geometry = libvlc_video_get_crop_geometry(p_md);
935         if( !psz_geometry )
936         {
937             *geometry = BSTRFromCStr(CP_UTF8, psz_geometry);
938             if( !geometry )
939                 hr = E_OUTOFMEMORY;
940         } else if( !psz_geometry )
941                 hr = E_OUTOFMEMORY;
942         free( psz_geometry );
943     }
944     return hr;
945 };
946
947 STDMETHODIMP VLCVideo::put_crop(BSTR geometry)
948 {
949     if( NULL == geometry )
950         return E_POINTER;
951
952     if( 0 == SysStringLen(geometry) )
953         return E_INVALIDARG;
954
955     libvlc_media_player_t *p_md;
956     HRESULT hr = getMD(&p_md);
957     if( SUCCEEDED(hr) )
958     {
959         char *psz_geometry = CStrFromBSTR(CP_UTF8, geometry);
960         if( !psz_geometry )
961         {
962             return E_OUTOFMEMORY;
963         }
964
965         libvlc_video_set_crop_geometry(p_md, psz_geometry);
966
967         CoTaskMemFree(psz_geometry);
968     }
969     return hr;
970 };
971
972 STDMETHODIMP VLCVideo::get_teletext(long* page)
973 {
974     if( NULL == page )
975         return E_POINTER;
976
977     libvlc_media_player_t *p_md;
978     HRESULT hr = getMD(&p_md);
979     if( SUCCEEDED(hr) )
980     {
981         *page = libvlc_video_get_teletext(p_md);
982     }
983
984     return hr;
985 };
986
987 STDMETHODIMP VLCVideo::put_teletext(long page)
988 {
989     libvlc_media_player_t *p_md;
990     HRESULT hr = getMD(&p_md);
991
992     if( SUCCEEDED(hr) )
993     {
994         libvlc_video_set_teletext(p_md, page);
995     }
996     return hr;
997 };
998
999 STDMETHODIMP VLCVideo::takeSnapshot(LPPICTUREDISP* picture)
1000 {
1001     if( NULL == picture )
1002         return E_POINTER;
1003
1004     libvlc_media_player_t *p_md;
1005     HRESULT hr = getMD(&p_md);
1006     if( SUCCEEDED(hr) )
1007     {
1008         static int uniqueId = 0;
1009         TCHAR path[MAX_PATH+1];
1010
1011         int pathlen = GetTempPath(MAX_PATH-24, path);
1012         if( (0 == pathlen) || (pathlen > (MAX_PATH-24)) )
1013             return E_FAIL;
1014
1015         /* check temp directory path by openning it */
1016         {
1017             HANDLE dirHandle = CreateFile(path, GENERIC_READ,
1018                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
1019                        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1020             if( INVALID_HANDLE_VALUE == dirHandle )
1021             {
1022                 Instance()->setErrorInfo(IID_IVLCVideo,
1023                         "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
1024                 return E_FAIL;
1025             }
1026             else
1027             {
1028                 BY_HANDLE_FILE_INFORMATION bhfi;
1029                 BOOL res = GetFileInformationByHandle(dirHandle, &bhfi);
1030                 CloseHandle(dirHandle);
1031                 if( !res || !(bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
1032                 {
1033                     Instance()->setErrorInfo(IID_IVLCVideo,
1034                             "Invalid temporary directory for snapshot images, check values of TMP, TEMP envars.");
1035                     return E_FAIL;
1036                 }
1037             }
1038         }
1039
1040         TCHAR filepath[MAX_PATH+1];
1041
1042         _stprintf(filepath, TEXT("%sAXVLC%lXS%lX.bmp"),
1043                  path, GetCurrentProcessId(), ++uniqueId);
1044
1045 #ifdef _UNICODE
1046         /* reuse path storage for UTF8 string */
1047         char *psz_filepath = (char *)path;
1048         WCHAR* wpath = filepath;
1049 #else
1050         char *psz_filepath = path;
1051         /* first convert to unicode using current code page */
1052         WCHAR wpath[MAX_PATH+1];
1053         if( 0 == MultiByteToWideChar(CP_ACP, 0, filepath, -1,
1054                                      wpath, sizeof(wpath)/sizeof(WCHAR)) )
1055             return E_FAIL;
1056 #endif
1057         /* convert to UTF8 */
1058         pathlen = WideCharToMultiByte(CP_UTF8, 0, wpath, -1,
1059                                       psz_filepath, sizeof(path), NULL, NULL);
1060         // fail if path is 0 or too short (i.e pathlen is the same as
1061         // storage size)
1062
1063         if( (0 == pathlen) || (sizeof(path) == pathlen) )
1064             return E_FAIL;
1065
1066         /* take snapshot into file */
1067         if( libvlc_video_take_snapshot(p_md, 0, psz_filepath, 0, 0) == 0 )
1068         {
1069             /* open snapshot file */
1070             HANDLE snapPic = LoadImage(NULL, filepath, IMAGE_BITMAP, 0, 0,
1071                                        LR_CREATEDIBSECTION|LR_LOADFROMFILE);
1072             if( snapPic )
1073             {
1074                 PICTDESC snapDesc;
1075
1076                 snapDesc.cbSizeofstruct = sizeof(PICTDESC);
1077                 snapDesc.picType        = PICTYPE_BITMAP;
1078                 snapDesc.bmp.hbitmap    = (HBITMAP)snapPic;
1079                 snapDesc.bmp.hpal       = NULL;
1080
1081                 hr = OleCreatePictureIndirect(&snapDesc, IID_IPictureDisp,
1082                                               TRUE, (LPVOID*)picture);
1083                 if( FAILED(hr) )
1084                 {
1085                     *picture = NULL;
1086                     DeleteObject(snapPic);
1087                 }
1088             }
1089             DeleteFile(filepath);
1090         }
1091     }
1092     return hr;
1093 };
1094
1095 STDMETHODIMP VLCVideo::toggleFullscreen()
1096 {
1097     libvlc_media_player_t *p_md;
1098     HRESULT hr = getMD(&p_md);
1099     if( SUCCEEDED(hr) )
1100     {
1101         libvlc_toggle_fullscreen(p_md);
1102     }
1103     return hr;
1104 };
1105
1106 STDMETHODIMP VLCVideo::toggleTeletext()
1107 {
1108     libvlc_media_player_t *p_md;
1109     HRESULT hr = getMD(&p_md);
1110     if( SUCCEEDED(hr) )
1111     {
1112         libvlc_toggle_teletext(p_md);
1113     }
1114     return hr;
1115 };
1116
1117 STDMETHODIMP VLCVideo::get_marquee(IVLCMarquee** obj)
1118 {
1119     return object_get(obj,_p_vlcmarquee);
1120 }
1121
1122 STDMETHODIMP VLCVideo::get_logo(IVLCLogo** obj)
1123 {
1124     return object_get(obj,_p_vlclogo);
1125 }
1126
1127 STDMETHODIMP VLCVideo::get_deinterlace(IVLCDeinterlace** obj)
1128 {
1129     return object_get(obj,_p_vlcdeint);
1130 }
1131
1132 /****************************************************************************/
1133
1134 HRESULT VLCLogo::do_put_int(unsigned idx, LONG val)
1135 {
1136     libvlc_media_player_t *p_md;
1137     HRESULT hr = getMD(&p_md);
1138     if( SUCCEEDED(hr) )
1139     {
1140         libvlc_video_set_logo_int(p_md, idx, val);
1141     }
1142     return hr;
1143 }
1144
1145 HRESULT VLCLogo::do_get_int(unsigned idx, LONG *val)
1146 {
1147     if( NULL == val )
1148         return E_POINTER;
1149
1150     libvlc_media_player_t *p_md;
1151     HRESULT hr = getMD(&p_md);
1152     if( SUCCEEDED(hr) )
1153     {
1154         *val = libvlc_video_get_logo_int(p_md, idx);
1155     }
1156     return hr;
1157 }
1158
1159 STDMETHODIMP VLCLogo::file(BSTR fname)
1160 {
1161     libvlc_media_player_t *p_md;
1162     HRESULT hr = getMD(&p_md);
1163
1164     char *n = CStrFromBSTR(CP_UTF8, fname);
1165     if( !n ) hr = E_OUTOFMEMORY;
1166
1167     if( SUCCEEDED(hr) )
1168     {
1169         libvlc_video_set_logo_string(p_md, libvlc_logo_file, n);
1170     }
1171
1172     CoTaskMemFree(n);
1173     return hr;
1174 }
1175
1176 STDMETHODIMP VLCLogo::get_position(BSTR* val)
1177 {
1178     if( NULL == val )
1179         return E_POINTER;
1180
1181     LONG i;
1182     HRESULT hr = do_get_int(libvlc_logo_position, &i);
1183
1184     if(SUCCEEDED(hr))
1185         *val = BSTRFromCStr(CP_UTF8, position_bynumber(i));
1186
1187     return hr;
1188 }
1189
1190 STDMETHODIMP VLCLogo::put_position(BSTR val)
1191 {
1192     char *n = CStrFromBSTR(CP_UTF8, val);
1193     if( !n ) return E_OUTOFMEMORY;
1194
1195     size_t i;
1196     HRESULT hr;
1197     if( position_byname( n, i ) )
1198         hr = do_put_int(libvlc_logo_position,i);
1199     else
1200         hr = E_INVALIDARG;
1201
1202     CoTaskMemFree(n);
1203     return hr;
1204 }
1205
1206 /****************************************************************************/
1207
1208 VLCControl2::VLCControl2(VLCPlugin *p_instance) :
1209     _p_instance(p_instance),
1210     _p_typeinfo(NULL),
1211     _p_vlcaudio(new VLCAudio(p_instance)),
1212     _p_vlcinput(new VLCInput(p_instance)),
1213     _p_vlcplaylist(new VLCPlaylist(p_instance)),
1214     _p_vlcsubtitle(new VLCSubtitle(p_instance)),
1215     _p_vlcvideo(new VLCVideo(p_instance))
1216 {
1217 }
1218
1219 VLCControl2::~VLCControl2()
1220 {
1221     delete _p_vlcvideo;
1222     delete _p_vlcsubtitle;
1223     delete _p_vlcplaylist;
1224     delete _p_vlcinput;
1225     delete _p_vlcaudio;
1226     if( _p_typeinfo )
1227         _p_typeinfo->Release();
1228 };
1229
1230 HRESULT VLCControl2::loadTypeInfo(void)
1231 {
1232     HRESULT hr = NOERROR;
1233     if( NULL == _p_typeinfo )
1234     {
1235         ITypeLib *p_typelib;
1236
1237         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
1238         if( SUCCEEDED(hr) )
1239         {
1240             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl2, &_p_typeinfo);
1241             if( FAILED(hr) )
1242             {
1243                 _p_typeinfo = NULL;
1244             }
1245             p_typelib->Release();
1246         }
1247     }
1248     return hr;
1249 };
1250
1251 STDMETHODIMP VLCControl2::GetTypeInfoCount(UINT* pctInfo)
1252 {
1253     if( NULL == pctInfo )
1254         return E_INVALIDARG;
1255
1256     if( SUCCEEDED(loadTypeInfo()) )
1257         *pctInfo = 1;
1258     else
1259         *pctInfo = 0;
1260
1261     return NOERROR;
1262 };
1263
1264 STDMETHODIMP VLCControl2::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
1265 {
1266     if( NULL == ppTInfo )
1267         return E_INVALIDARG;
1268
1269     if( SUCCEEDED(loadTypeInfo()) )
1270     {
1271         _p_typeinfo->AddRef();
1272         *ppTInfo = _p_typeinfo;
1273         return NOERROR;
1274     }
1275     *ppTInfo = NULL;
1276     return E_NOTIMPL;
1277 };
1278
1279 STDMETHODIMP VLCControl2::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
1280         UINT cNames, LCID lcid, DISPID* rgDispID)
1281 {
1282     if( SUCCEEDED(loadTypeInfo()) )
1283     {
1284         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
1285     }
1286     return E_NOTIMPL;
1287 };
1288
1289 STDMETHODIMP VLCControl2::Invoke(DISPID dispIdMember, REFIID riid,
1290         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
1291         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1292 {
1293     if( SUCCEEDED(loadTypeInfo()) )
1294     {
1295         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
1296                 pVarResult, pExcepInfo, puArgErr);
1297     }
1298     return E_NOTIMPL;
1299 };
1300
1301 STDMETHODIMP VLCControl2::get_AutoLoop(VARIANT_BOOL *autoloop)
1302 {
1303     if( NULL == autoloop )
1304         return E_POINTER;
1305
1306     *autoloop = varbool( _p_instance->getAutoLoop() );
1307     return S_OK;
1308 };
1309
1310 STDMETHODIMP VLCControl2::put_AutoLoop(VARIANT_BOOL autoloop)
1311 {
1312     _p_instance->setAutoLoop((VARIANT_FALSE != autoloop) ? TRUE: FALSE);
1313     return S_OK;
1314 };
1315
1316 STDMETHODIMP VLCControl2::get_AutoPlay(VARIANT_BOOL *autoplay)
1317 {
1318     if( NULL == autoplay )
1319         return E_POINTER;
1320
1321     *autoplay = varbool( _p_instance->getAutoPlay() );
1322     return S_OK;
1323 };
1324
1325 STDMETHODIMP VLCControl2::put_AutoPlay(VARIANT_BOOL autoplay)
1326 {
1327     _p_instance->setAutoPlay((VARIANT_FALSE != autoplay) ? TRUE: FALSE);
1328     return S_OK;
1329 };
1330
1331 STDMETHODIMP VLCControl2::get_BaseURL(BSTR *url)
1332 {
1333     if( NULL == url )
1334         return E_POINTER;
1335
1336     *url = SysAllocStringLen(_p_instance->getBaseURL(),
1337                 SysStringLen(_p_instance->getBaseURL()));
1338     return NOERROR;
1339 };
1340
1341 STDMETHODIMP VLCControl2::put_BaseURL(BSTR mrl)
1342 {
1343     _p_instance->setBaseURL(mrl);
1344
1345     return S_OK;
1346 };
1347
1348 STDMETHODIMP VLCControl2::get_MRL(BSTR *mrl)
1349 {
1350     if( NULL == mrl )
1351         return E_POINTER;
1352
1353     *mrl = SysAllocStringLen(_p_instance->getMRL(),
1354                 SysStringLen(_p_instance->getMRL()));
1355     return NOERROR;
1356 };
1357
1358 STDMETHODIMP VLCControl2::put_MRL(BSTR mrl)
1359 {
1360     _p_instance->setMRL(mrl);
1361
1362     return S_OK;
1363 };
1364
1365
1366 STDMETHODIMP VLCControl2::get_Toolbar(VARIANT_BOOL *visible)
1367 {
1368     if( NULL == visible )
1369         return E_POINTER;
1370
1371     /*
1372      * Note to developers
1373      *
1374      * Returning the _b_toolbar is closer to the method specification.
1375      * But returning True when toolbar is not implemented so not displayed
1376      * could be bad for ActiveX users which rely on this value to show their
1377      * own toolbar if not provided by the ActiveX.
1378      *
1379      * This is the reason why FALSE is returned, until toolbar get implemented.
1380      */
1381
1382     /* DISABLED for now */
1383     //  *visible = varbool( _p_instance->getShowToolbar() );
1384
1385     *visible = VARIANT_FALSE;
1386
1387     return S_OK;
1388 };
1389
1390 STDMETHODIMP VLCControl2::put_Toolbar(VARIANT_BOOL visible)
1391 {
1392     _p_instance->setShowToolbar((VARIANT_FALSE != visible) ? TRUE: FALSE);
1393     return S_OK;
1394 };
1395
1396
1397 STDMETHODIMP VLCControl2::get_StartTime(long *seconds)
1398 {
1399     if( NULL == seconds )
1400         return E_POINTER;
1401
1402     *seconds = _p_instance->getStartTime();
1403     return S_OK;
1404 };
1405
1406 STDMETHODIMP VLCControl2::put_StartTime(long seconds)
1407 {
1408     _p_instance->setStartTime(seconds);
1409     return S_OK;
1410 };
1411
1412 STDMETHODIMP VLCControl2::get_VersionInfo(BSTR *version)
1413 {
1414     if( NULL == version )
1415         return E_POINTER;
1416
1417     const char *versionStr = libvlc_get_version();
1418     if( NULL != versionStr )
1419     {
1420         *version = BSTRFromCStr(CP_UTF8, versionStr);
1421
1422         return (NULL == *version) ? E_OUTOFMEMORY : NOERROR;
1423     }
1424     *version = NULL;
1425     return E_FAIL;
1426 };
1427
1428 STDMETHODIMP VLCControl2::get_Visible(VARIANT_BOOL *isVisible)
1429 {
1430     if( NULL == isVisible )
1431         return E_POINTER;
1432
1433     *isVisible = varbool( _p_instance->getVisible() );
1434
1435     return S_OK;
1436 };
1437
1438 STDMETHODIMP VLCControl2::put_Visible(VARIANT_BOOL isVisible)
1439 {
1440     _p_instance->setVisible(isVisible != VARIANT_FALSE);
1441     return S_OK;
1442 };
1443
1444 STDMETHODIMP VLCControl2::get_Volume(long *volume)
1445 {
1446     if( NULL == volume )
1447         return E_POINTER;
1448
1449     *volume  = _p_instance->getVolume();
1450     return S_OK;
1451 };
1452
1453 STDMETHODIMP VLCControl2::put_Volume(long volume)
1454 {
1455     _p_instance->setVolume(volume);
1456     return S_OK;
1457 };
1458
1459 STDMETHODIMP VLCControl2::get_BackColor(OLE_COLOR *backcolor)
1460 {
1461     if( NULL == backcolor )
1462         return E_POINTER;
1463
1464     *backcolor  = _p_instance->getBackColor();
1465     return S_OKs;
1466 };
1467
1468 STDMETHODIMP VLCControl2::put_BackColor(OLE_COLOR backcolor)
1469 {
1470     _p_instance->setBackColor(backcolor);
1471     return S_OK;
1472 };
1473
1474 STDMETHODIMP VLCControl2::get_audio(IVLCAudio** obj)
1475 {
1476     return object_get(obj,_p_vlcaudio);
1477 }
1478
1479 STDMETHODIMP VLCControl2::get_input(IVLCInput** obj)
1480 {
1481     return object_get(obj,_p_vlcinput);
1482 }
1483
1484 STDMETHODIMP VLCControl2::get_playlist(IVLCPlaylist** obj)
1485 {
1486     return object_get(obj,_p_vlcplaylist);
1487 }
1488
1489 STDMETHODIMP VLCControl2::get_subtitle(IVLCSubtitle** obj)
1490 {
1491     return object_get(obj,_p_vlcsubtitle);
1492 }
1493
1494 STDMETHODIMP VLCControl2::get_video(IVLCVideo** obj)
1495 {
1496     return object_get(obj,_p_vlcvideo);
1497 }