]> git.sesse.net Git - vlc/blob - projects/activex/vlccontrol.cpp
Merge branch 'master' of git://git.videolan.org/vlc
[vlc] / projects / activex / vlccontrol.cpp
1 /*****************************************************************************
2  * vlccontrol.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005-2010 the VideoLAN team
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *          Jean-Paul Saman <jpsaman@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "plugin.h"
25 #include "vlccontrol.h"
26
27 #include "utils.h"
28
29 using namespace std;
30
31 VLCControl::~VLCControl()
32 {
33     if( _p_typeinfo )
34         _p_typeinfo->Release();
35 };
36
37 HRESULT VLCControl::getTypeInfo(void)
38 {
39     HRESULT hr = NOERROR;
40     if( NULL == _p_typeinfo )
41     {
42         ITypeLib *p_typelib;
43
44         hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
45         if( SUCCEEDED(hr) )
46         {
47             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl, &_p_typeinfo);
48             if( FAILED(hr) )
49             {
50                 _p_typeinfo = NULL;
51             }
52             p_typelib->Release();
53         }
54     }
55     return hr;
56 };
57
58 STDMETHODIMP VLCControl::GetTypeInfoCount(UINT* pctInfo)
59 {
60     if( NULL == pctInfo )
61         return E_INVALIDARG;
62
63     if( SUCCEEDED(getTypeInfo()) )
64         *pctInfo = 1;
65     else
66         *pctInfo = 0;
67
68     return NOERROR;
69 };
70
71 STDMETHODIMP VLCControl::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
72 {
73     if( NULL == ppTInfo )
74         return E_INVALIDARG;
75
76     if( SUCCEEDED(getTypeInfo()) )
77     {
78         _p_typeinfo->AddRef();
79         *ppTInfo = _p_typeinfo;
80         return NOERROR;
81     }
82     *ppTInfo = NULL;
83     return E_NOTIMPL;
84 };
85
86 STDMETHODIMP VLCControl::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
87         UINT cNames, LCID lcid, DISPID* rgDispID)
88 {
89     if( SUCCEEDED(getTypeInfo()) )
90     {
91         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
92     }
93     return E_NOTIMPL;
94 };
95
96 STDMETHODIMP VLCControl::Invoke(DISPID dispIdMember, REFIID riid,
97         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
98         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
99 {
100     if( SUCCEEDED(getTypeInfo()) )
101     {
102         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
103                 pVarResult, pExcepInfo, puArgErr);
104     }
105     return E_NOTIMPL;
106 };
107
108 STDMETHODIMP VLCControl::get_Visible(VARIANT_BOOL *isVisible)
109 {
110     if( NULL == isVisible )
111         return E_POINTER;
112
113     *isVisible = _p_instance->getVisible() ? VARIANT_TRUE : VARIANT_FALSE;
114
115     return S_OK;
116 };
117
118 STDMETHODIMP VLCControl::put_Visible(VARIANT_BOOL isVisible)
119 {
120     _p_instance->setVisible(isVisible != VARIANT_FALSE);
121
122     return S_OK;
123 };
124
125 STDMETHODIMP VLCControl::play(void)
126 {
127     _p_instance->playlist_play();
128     _p_instance->fireOnPlayEvent();
129     return S_OK;
130 };
131
132 STDMETHODIMP VLCControl::pause(void)
133 {
134     libvlc_media_player_t* p_md;
135     HRESULT result = _p_instance->getMD(&p_md);
136     if( SUCCEEDED(result) )
137     {
138         libvlc_media_player_pause(p_md);
139         _p_instance->fireOnPauseEvent();
140     }
141     return result;
142 };
143
144 STDMETHODIMP VLCControl::stop(void)
145 {
146     libvlc_media_player_t *p_md;
147     HRESULT result = _p_instance->getMD(&p_md);
148     if( SUCCEEDED(result) )
149     {
150         libvlc_media_player_stop(p_md);
151         _p_instance->fireOnStopEvent();
152     }
153     return result;
154 };
155
156 STDMETHODIMP VLCControl::get_Playing(VARIANT_BOOL *isPlaying)
157 {
158     if( NULL == isPlaying )
159         return E_POINTER;
160
161     libvlc_media_player_t *p_md;
162     HRESULT result = _p_instance->getMD(&p_md);
163     if( SUCCEEDED(result) )
164     {
165         *isPlaying = libvlc_media_player_is_playing(p_md) ?
166                      VARIANT_TRUE : VARIANT_FALSE;
167     } else *isPlaying = VARIANT_FALSE;
168     return result;
169 };
170
171 STDMETHODIMP VLCControl::get_Position(float *position)
172 {
173     if( NULL == position )
174         return E_POINTER;
175     *position = 0.0f;
176
177     libvlc_media_player_t *p_md;
178     HRESULT result = _p_instance->getMD(&p_md);
179     if( SUCCEEDED(result) )
180     {
181         *position = libvlc_media_player_get_position(p_md);
182     }
183     return result;
184 };
185
186 STDMETHODIMP VLCControl::put_Position(float position)
187 {
188     libvlc_media_player_t *p_md;
189     HRESULT result = _p_instance->getMD(&p_md);
190     if( SUCCEEDED(result) )
191     {
192         libvlc_media_player_set_position(p_md, position);
193     }
194     return result;
195 };
196
197 STDMETHODIMP VLCControl::get_Time(int *seconds)
198 {
199     if( NULL == seconds )
200         return E_POINTER;
201
202     *seconds = 0;
203     libvlc_media_player_t *p_md;
204     HRESULT result = _p_instance->getMD(&p_md);
205     if( SUCCEEDED(result) )
206     {
207         *seconds = libvlc_media_player_get_time(p_md);
208     }
209     return result;
210 };
211
212 STDMETHODIMP VLCControl::put_Time(int seconds)
213 {
214     /* setTime function of the plugin sets the time. */
215     _p_instance->setTime(seconds);
216     return S_OK;
217 };
218
219 STDMETHODIMP VLCControl::shuttle(int seconds)
220 {
221     libvlc_media_player_t *p_md;
222     HRESULT result = _p_instance->getMD(&p_md);
223     if( SUCCEEDED(result) )
224     {
225         if( seconds < 0 ) seconds = 0;
226         libvlc_media_player_set_time(p_md, (int64_t)seconds);
227     }
228     return result;
229
230 };
231
232 STDMETHODIMP VLCControl::fullscreen(void)
233 {
234     libvlc_media_player_t *p_md;
235     HRESULT result = _p_instance->getMD(&p_md);
236     if( SUCCEEDED(result) )
237     {
238         if( libvlc_media_player_is_playing(p_md) )
239         {
240             libvlc_toggle_fullscreen(p_md);
241         }
242     }
243     return result;
244 };
245
246 STDMETHODIMP VLCControl::get_Length(int *seconds)
247 {
248     if( NULL == seconds )
249         return E_POINTER;
250     *seconds = 0;
251
252     libvlc_media_player_t *p_md;
253     HRESULT result = _p_instance->getMD(&p_md);
254     if( SUCCEEDED(result) )
255     {
256         *seconds = (double)libvlc_media_player_get_length(p_md);
257     }
258     return result;
259
260 };
261
262 STDMETHODIMP VLCControl::playFaster(void)
263 {
264     int32_t rate = 2;
265
266     libvlc_media_player_t *p_md;
267     HRESULT result = _p_instance->getMD(&p_md);
268
269     if( SUCCEEDED(result) )
270     {
271         libvlc_media_player_set_rate(p_md, rate);
272     }
273     return result;
274 };
275
276 STDMETHODIMP VLCControl::playSlower(void)
277 {
278     float rate = 0.5;
279
280     libvlc_media_player_t *p_md;
281     HRESULT result = _p_instance->getMD(&p_md);
282     if( SUCCEEDED(result) )
283     {
284         libvlc_media_player_set_rate(p_md, rate);
285     }
286     return result;
287 };
288
289 STDMETHODIMP VLCControl::get_Volume(int *volume)
290 {
291     if( NULL == volume )
292         return E_POINTER;
293
294     *volume  = _p_instance->getVolume();
295     return S_OK;
296 };
297
298 STDMETHODIMP VLCControl::put_Volume(int volume)
299 {
300     _p_instance->setVolume(volume);
301     return S_OK;
302 };
303
304 STDMETHODIMP VLCControl::toggleMute(void)
305 {
306     libvlc_media_player_t *p_md;
307     HRESULT result = _p_instance->getMD(&p_md);
308     if( SUCCEEDED(result) )
309         libvlc_audio_toggle_mute(p_md);
310     return result;
311 };
312
313 STDMETHODIMP VLCControl::setVariable(BSTR name, VARIANT value)
314 {
315     libvlc_instance_t* p_libvlc;
316     HRESULT result = _p_instance->getVLC(&p_libvlc);
317     if( SUCCEEDED(result) )
318     {
319         _p_instance->setErrorInfo(IID_IVLCControl,
320             "setVariable() is an unsafe interface to use. "
321             "It has been removed because of security implications." );
322     }
323     return E_FAIL;
324 };
325
326 STDMETHODIMP VLCControl::getVariable(BSTR name, VARIANT *value)
327 {
328     libvlc_instance_t* p_libvlc;
329     HRESULT result = _p_instance->getVLC(&p_libvlc);
330     if( SUCCEEDED(result) )
331     {
332         _p_instance->setErrorInfo(IID_IVLCControl,
333             "getVariable() is an unsafe interface to use. "
334             "It has been removed because of security implications." );
335     }
336     return E_FAIL;
337 };
338
339 void VLCControl::FreeTargetOptions(char **cOptions, int cOptionCount)
340 {
341     // clean up
342     if( NULL != cOptions )
343     {
344         for( int pos=0; pos<cOptionCount; ++pos )
345         {
346             char *cOption = cOptions[pos];
347             if( NULL != cOption )
348                 CoTaskMemFree(cOption);
349             else
350                 break;
351         }
352         CoTaskMemFree(cOptions);
353     }
354 };
355
356 static HRESULT parseStringOptions(int codePage, BSTR bstr, char*** cOptions, int *cOptionCount)
357 {
358     HRESULT hr = E_INVALIDARG;
359     if( SysStringLen(bstr) > 0 )
360     {
361         hr = E_OUTOFMEMORY;
362         char *s = CStrFromBSTR(codePage, bstr);
363         char *val = s;
364         if( val )
365         {
366             long capacity = 16;
367             char **options = (char **)CoTaskMemAlloc(capacity*sizeof(char *));
368             if( options )
369             {
370                 int nOptions = 0;
371
372                 char *end = val + strlen(val);
373                 while( val < end )
374                 {
375                     // skip leading blanks
376                     while( (val < end)
377                         && ((*val == ' ' ) || (*val == '\t')) )
378                         ++val;
379
380                     char *start = val;
381                     // skip till we get a blank character
382                     while( (val < end)
383                         && (*val != ' ' )
384                         && (*val != '\t') )
385                     {
386                         char c = *(val++);
387                         if( ('\'' == c) || ('"' == c) )
388                         {
389                             // skip till end of string
390                             while( (val < end) && (*(val++) != c ) );
391                         }
392                     }
393
394                     if( val > start )
395                     {
396                         if( nOptions == capacity )
397                         {
398                             capacity += 16;
399                             char **moreOptions = (char **)CoTaskMemRealloc(options, capacity*sizeof(char*));
400                             if( ! moreOptions )
401                             {
402                                 /* failed to allocate more memory */
403                                 CoTaskMemFree(s);
404                                 /* return what we got so far */
405                                 *cOptionCount = nOptions;
406                                 *cOptions = options;
407                                 return NOERROR;
408                             }
409                             options = moreOptions;
410                         }
411                         *(val++) = '\0';
412                         options[nOptions] = (char *)CoTaskMemAlloc(val-start);
413                         if( options[nOptions] )
414                         {
415                             memcpy(options[nOptions], start, val-start);
416                             ++nOptions;
417                         }
418                         else
419                         {
420                             /* failed to allocate memory */
421                             CoTaskMemFree(s);
422                             /* return what we got so far */
423                             *cOptionCount = nOptions;
424                             *cOptions = options;
425                             return NOERROR;
426                         }
427                     }
428                     else
429                         // must be end of string
430                         break;
431                 }
432                 *cOptionCount = nOptions;
433                 *cOptions = options;
434                 hr = NOERROR;
435             }
436             CoTaskMemFree(s);
437         }
438     }
439     return hr;
440 }
441
442 HRESULT VLCControl::CreateTargetOptions(int codePage, VARIANT *options, char ***cOptions, int *cOptionCount)
443 {
444     HRESULT hr = E_INVALIDARG;
445     if( VT_ERROR == V_VT(options) )
446     {
447         if( DISP_E_PARAMNOTFOUND == V_ERROR(options) )
448         {
449             // optional parameter not set
450             *cOptions = NULL;
451             *cOptionCount = 0;
452             return NOERROR;
453         }
454     }
455     else if( (VT_EMPTY == V_VT(options)) || (VT_NULL == V_VT(options)) )
456     {
457         // null parameter
458         *cOptions = NULL;
459         *cOptionCount = 0;
460         return NOERROR;
461     }
462     else if( VT_DISPATCH == V_VT(options) )
463     {
464         // if object is a collection, retrieve enumerator
465         VARIANT colEnum;
466         V_VT(&colEnum) = VT_UNKNOWN;
467         hr = GetObjectProperty(V_DISPATCH(options), DISPID_NEWENUM, colEnum);
468         if( SUCCEEDED(hr) )
469         {
470             IEnumVARIANT *enumVar;
471             hr = V_UNKNOWN(&colEnum)->QueryInterface(IID_IEnumVARIANT, (LPVOID *)&enumVar);
472             if( SUCCEEDED(hr) )
473             {
474                 long pos = 0;
475                 long capacity = 16;
476                 VARIANT option;
477
478                 *cOptions = (char **)CoTaskMemAlloc(capacity*sizeof(char *));
479                 if( NULL != *cOptions )
480                 {
481                     ZeroMemory(*cOptions, sizeof(char *)*capacity);
482                     while( SUCCEEDED(hr) && (S_OK == enumVar->Next(1, &option, NULL)) )
483                     {
484                         if( VT_BSTR == V_VT(&option) )
485                         {
486                             char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));
487                             (*cOptions)[pos] = cOption;
488                             if( NULL != cOption )
489                             {
490                                 ++pos;
491                                 if( pos == capacity )
492                                 {
493                                     char **moreOptions = (char **)CoTaskMemRealloc(*cOptions, (capacity+16)*sizeof(char *));
494                                     if( NULL != moreOptions )
495                                     {
496                                         ZeroMemory(moreOptions+capacity, sizeof(char *)*16);
497                                         capacity += 16;
498                                         *cOptions = moreOptions;
499                                     }
500                                     else
501                                         hr = E_OUTOFMEMORY;
502                                 }
503                             }
504                             else
505                                 hr = ( SysStringLen(V_BSTR(&option)) > 0 ) ?
506                                     E_OUTOFMEMORY : E_INVALIDARG;
507                         }
508                         else
509                             hr = E_INVALIDARG;
510
511                         VariantClear(&option);
512                     }
513                     *cOptionCount = pos;
514                     if( FAILED(hr) )
515                     {
516                         // free already processed elements
517                         FreeTargetOptions(*cOptions, *cOptionCount);
518                     }
519                 }
520                 else
521                     hr = E_OUTOFMEMORY;
522
523                 enumVar->Release();
524             }
525         }
526         else
527         {
528             // coerce object into a string and parse it
529             VARIANT v_name;
530             VariantInit(&v_name);
531             hr = VariantChangeType(&v_name, options, 0, VT_BSTR);
532             if( SUCCEEDED(hr) )
533             {
534                 hr = parseStringOptions(codePage, V_BSTR(&v_name), cOptions, cOptionCount);
535                 VariantClear(&v_name);
536             }
537         }
538     }
539     else if( V_ISARRAY(options) )
540     {
541         // array parameter
542         SAFEARRAY *array = V_ISBYREF(options) ? *V_ARRAYREF(options) : V_ARRAY(options);
543
544         if( SafeArrayGetDim(array) != 1 )
545             return E_INVALIDARG;
546
547         long lBound = 0;
548         long uBound = 0;
549         SafeArrayGetLBound(array, 1, &lBound);
550         SafeArrayGetUBound(array, 1, &uBound);
551
552         // have we got any options
553         if( uBound >= lBound )
554         {
555             VARTYPE vType;
556             hr = SafeArrayGetVartype(array, &vType);
557             if( FAILED(hr) )
558                 return hr;
559
560             long pos;
561
562             // marshall options into an array of C strings
563             if( VT_VARIANT == vType )
564             {
565                 *cOptions = (char **)CoTaskMemAlloc(sizeof(char *)*(uBound-lBound+1));
566                 if( NULL == *cOptions )
567                     return E_OUTOFMEMORY;
568
569                 ZeroMemory(*cOptions, sizeof(char *)*(uBound-lBound+1));
570                 for(pos=lBound; (pos<=uBound) && SUCCEEDED(hr); ++pos )
571                 {
572                     VARIANT option;
573                     hr = SafeArrayGetElement(array, &pos, &option);
574                     if( SUCCEEDED(hr) )
575                     {
576                         if( VT_BSTR == V_VT(&option) )
577                         {
578                             char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));
579                             (*cOptions)[pos-lBound] = cOption;
580                             if( NULL == cOption )
581                                 hr = ( SysStringLen(V_BSTR(&option)) > 0 ) ?
582                                     E_OUTOFMEMORY : E_INVALIDARG;
583                         }
584                         else
585                             hr = E_INVALIDARG;
586                         VariantClear(&option);
587                     }
588                 }
589             }
590             else if( VT_BSTR == vType )
591             {
592                 *cOptions = (char **)CoTaskMemAlloc(sizeof(char *)*(uBound-lBound+1));
593                 if( NULL == *cOptions )
594                     return E_OUTOFMEMORY;
595
596                 ZeroMemory(*cOptions, sizeof(char *)*(uBound-lBound+1));
597                 for(pos=lBound; (pos<=uBound) && SUCCEEDED(hr); ++pos )
598                 {
599                     BSTR option;
600                     hr = SafeArrayGetElement(array, &pos, &option);
601                     if( SUCCEEDED(hr) )
602                     {
603                         char *cOption = CStrFromBSTR(codePage, option);
604
605                         (*cOptions)[pos-lBound] = cOption;
606                         if( NULL == cOption )
607                             hr = ( SysStringLen(option) > 0 ) ?
608                                 E_OUTOFMEMORY : E_INVALIDARG;
609                         SysFreeString(option);
610                     }
611                 }
612             }
613             else
614             {
615                 // unsupported type
616                 return E_INVALIDARG;
617             }
618
619             *cOptionCount = pos-lBound;
620             if( FAILED(hr) )
621             {
622                 // free already processed elements
623                 FreeTargetOptions(*cOptions, *cOptionCount);
624             }
625         }
626         else
627         {
628             // empty array
629             *cOptions = NULL;
630             *cOptionCount = 0;
631             return NOERROR;
632         }
633     }
634     else if( VT_UNKNOWN == V_VT(options) )
635     {
636         // coerce object into a string and parse it
637         VARIANT v_name;
638         VariantInit(&v_name);
639         hr = VariantChangeType(&v_name, options, 0, VT_BSTR);
640         if( SUCCEEDED(hr) )
641         {
642             hr = parseStringOptions(codePage, V_BSTR(&v_name), cOptions, cOptionCount);
643             VariantClear(&v_name);
644         }
645     }
646     else if( VT_BSTR == V_VT(options) )
647     {
648         hr = parseStringOptions(codePage, V_BSTR(options), cOptions, cOptionCount);
649     }
650     return hr;
651 };
652
653 /*
654 ** use VARIANT rather than a SAFEARRAY as argument type
655 ** for compatibility with some scripting language (JScript)
656 */
657
658 STDMETHODIMP VLCControl::addTarget(BSTR uri, VARIANT options, enum VLCPlaylistMode mode, int position)
659 {
660     if( 0 == SysStringLen(uri) )
661         return E_INVALIDARG;
662
663     libvlc_instance_t *p_libvlc;
664     HRESULT hr = _p_instance->getVLC(&p_libvlc);
665     if( SUCCEEDED(hr) )
666     {
667         char *cUri = CStrFromBSTR(CP_UTF8, uri);
668         if( NULL == cUri )
669             return E_OUTOFMEMORY;
670
671         int cOptionsCount;
672         char **cOptions;
673
674         if( FAILED(CreateTargetOptions(CP_UTF8, &options, &cOptions, &cOptionsCount)) )
675             return E_INVALIDARG;
676
677         position = _p_instance->playlist_add_extended_untrusted(cUri,
678                        cOptionsCount, const_cast<const char**>(cOptions));
679
680         FreeTargetOptions(cOptions, cOptionsCount);
681         CoTaskMemFree(cUri);
682
683         if( position >= 0 )
684         {
685             if( mode & VLCPlayListAppendAndGo )
686                 _p_instance->fireOnPlayEvent();
687         }
688         else
689         {
690             if( mode & VLCPlayListAppendAndGo )
691                 _p_instance->fireOnStopEvent();
692         }
693     }
694     return hr;
695 };
696
697 STDMETHODIMP VLCControl::get_PlaylistIndex(int *index)
698 {
699     if( NULL == index )
700         return E_POINTER;
701
702     *index = 0;
703     libvlc_instance_t *p_libvlc;
704     HRESULT result = _p_instance->getVLC(&p_libvlc);
705     if( SUCCEEDED(result) )
706     {
707         *index = _p_instance->playlist_get_current_index();
708     }
709     return result;
710 };
711
712 STDMETHODIMP VLCControl::get_PlaylistCount(int *count)
713 {
714     if( NULL == count )
715         return E_POINTER;
716
717     *count = _p_instance->playlist_count();
718     return S_OK;
719 };
720
721 STDMETHODIMP VLCControl::playlistNext(void)
722 {
723     libvlc_instance_t* p_libvlc;
724     HRESULT result = _p_instance->getVLC(&p_libvlc);
725     if( SUCCEEDED(result) )
726     {
727         _p_instance->playlist_next();
728     }
729     return result;
730 };
731
732 STDMETHODIMP VLCControl::playlistPrev(void)
733 {
734     libvlc_instance_t* p_libvlc;
735     HRESULT result = _p_instance->getVLC(&p_libvlc);
736     if( SUCCEEDED(result) )
737     {
738         _p_instance->playlist_prev();
739     }
740     return result;
741 };
742
743 STDMETHODIMP VLCControl::playlistClear(void)
744 {
745     libvlc_instance_t* p_libvlc;
746     HRESULT result = _p_instance->getVLC(&p_libvlc);
747     if( SUCCEEDED(result) )
748     {
749         _p_instance->playlist_clear();
750     }
751     return result;
752 };
753
754 STDMETHODIMP VLCControl::get_VersionInfo(BSTR *version)
755 {
756     if( NULL == version )
757         return E_POINTER;
758
759     const char *versionStr = libvlc_get_version();
760     if( NULL != versionStr )
761     {
762         *version = BSTRFromCStr(CP_UTF8, versionStr);
763         return (NULL == *version) ? E_OUTOFMEMORY : NOERROR;
764     }
765     *version = NULL;
766     return E_FAIL;
767 };
768
769 STDMETHODIMP VLCControl::get_MRL(BSTR *mrl)
770 {
771     if( NULL == mrl )
772         return E_POINTER;
773
774     *mrl = SysAllocStringLen(_p_instance->getMRL(),
775                 SysStringLen(_p_instance->getMRL()));
776     return S_OK;
777 };
778
779 STDMETHODIMP VLCControl::put_MRL(BSTR mrl)
780 {
781     _p_instance->setMRL(mrl);
782
783     return S_OK;
784 };
785
786 STDMETHODIMP VLCControl::get_AutoPlay(VARIANT_BOOL *autoplay)
787 {
788     if( NULL == autoplay )
789         return E_POINTER;
790
791     *autoplay = _p_instance->getAutoPlay() ? VARIANT_TRUE: VARIANT_FALSE;
792     return S_OK;
793 };
794
795 STDMETHODIMP VLCControl::put_AutoPlay(VARIANT_BOOL autoplay)
796 {
797     _p_instance->setAutoPlay((VARIANT_FALSE != autoplay) ? TRUE: FALSE);
798     return S_OK;
799 };
800
801 STDMETHODIMP VLCControl::get_AutoLoop(VARIANT_BOOL *autoloop)
802 {
803     if( NULL == autoloop )
804         return E_POINTER;
805
806     *autoloop = _p_instance->getAutoLoop() ? VARIANT_TRUE: VARIANT_FALSE;
807     return S_OK;
808 };
809
810 STDMETHODIMP VLCControl::put_AutoLoop(VARIANT_BOOL autoloop)
811 {
812     _p_instance->setAutoLoop((VARIANT_FALSE != autoloop) ? TRUE: FALSE);
813     return S_OK;
814 };