]> git.sesse.net Git - vlc/blob - activex/vlccontrol.cpp
Avoid \r\n problems between platforms
[vlc] / activex / vlccontrol.cpp
1 /*****************************************************************************
2  * vlccontrol.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 VideoLAN
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 #include "plugin.h"
24 #include "vlccontrol.h"
25
26 #include "utils.h"
27
28 VLCControl::~VLCControl()
29 {
30     if( _p_typeinfo )
31         _p_typeinfo->Release();
32 };
33
34 HRESULT VLCControl::getTypeInfo(void)
35 {
36     HRESULT hr = NOERROR;
37     if( NULL == _p_typeinfo )
38     {
39         ITypeLib *p_typelib;
40
41         HRESULT hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
42         if( SUCCEEDED(hr) )
43         {
44             hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl, &_p_typeinfo);
45             if( FAILED(hr) )
46             {
47                 _p_typeinfo = NULL;
48             }
49             p_typelib->Release();
50         }
51     }
52     return hr;
53 };
54
55 STDMETHODIMP VLCControl::GetTypeInfoCount(UINT* pctInfo)
56 {
57     if( SUCCEEDED(getTypeInfo()) )
58         *pctInfo = 1;
59     else
60         *pctInfo = 0;
61
62     return NOERROR;
63 };
64
65 STDMETHODIMP VLCControl::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
66 {
67     if( NULL == ppTInfo )
68         return E_INVALIDARG;
69
70     if( SUCCEEDED(getTypeInfo()) )
71     {
72         _p_typeinfo->AddRef();
73         *ppTInfo = _p_typeinfo;
74         return NO_ERROR;
75     }
76     *ppTInfo = NULL;
77     return E_NOTIMPL;
78 };
79
80 STDMETHODIMP VLCControl::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, 
81         UINT cNames, LCID lcid, DISPID* rgDispID)
82 {
83     if( SUCCEEDED(getTypeInfo()) )
84     {
85         return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
86     }
87     return E_NOTIMPL;
88 };
89
90 STDMETHODIMP VLCControl::Invoke(DISPID dispIdMember, REFIID riid,
91         LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
92         VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
93 {
94     if( SUCCEEDED(getTypeInfo()) )
95     {
96         return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
97                 pVarResult, pExcepInfo, puArgErr);
98     }
99     return E_NOTIMPL;
100 };
101
102 STDMETHODIMP VLCControl::get_Value(VARIANT *pvarValue)
103 {
104     if( NULL == pvarValue )
105         return E_INVALIDARG;
106
107     V_VT(pvarValue) = VT_BOOL;
108     return get_Playing(&V_BOOL(pvarValue));
109 };
110         
111 STDMETHODIMP VLCControl::put_Value(VARIANT pvarValue)
112 {
113     if( VT_BOOL != V_VT(&pvarValue) )
114     {
115         VARIANT boolValue;
116         HRESULT hr = VariantChangeType(&boolValue, &pvarValue, 0, VT_BOOL);
117         if( SUCCEEDED(hr) )
118         {
119             hr = get_Playing(&V_BOOL(&pvarValue));
120             //VariantClear(&boolValue);
121         }
122         return hr;
123     }
124     return get_Playing(&V_BOOL(&pvarValue));
125 };
126         
127 STDMETHODIMP VLCControl::get_Visible(VARIANT_BOOL *isVisible)
128 {
129     if( NULL == isVisible )
130         return E_INVALIDARG;
131
132     *isVisible = _p_instance->getVisible();
133
134     return NOERROR;
135 };
136         
137 STDMETHODIMP VLCControl::put_Visible(VARIANT_BOOL isVisible)
138 {
139     _p_instance->setVisible(isVisible != VARIANT_FALSE);
140
141     return NOERROR;
142 };
143
144 STDMETHODIMP VLCControl::play(void)
145 {
146     int i_vlc = _p_instance->getVLCObject();
147     if( i_vlc )
148     {
149         VLC_Play(i_vlc);
150         _p_instance->fireOnPlayEvent();
151         return NOERROR;
152     }
153     return E_UNEXPECTED;
154 };
155  
156 STDMETHODIMP VLCControl::pause(void)
157 {
158     int i_vlc = _p_instance->getVLCObject();
159     if( i_vlc )
160     {
161         VLC_Pause(i_vlc);
162         _p_instance->fireOnPauseEvent();
163         return NOERROR;
164     }
165     return E_UNEXPECTED;
166 };
167         
168 STDMETHODIMP VLCControl::stop(void)
169 {
170     int i_vlc = _p_instance->getVLCObject();
171     if( i_vlc )
172     {
173         VLC_Stop(i_vlc);
174         _p_instance->fireOnStopEvent();
175         return NOERROR;
176     }
177     return E_UNEXPECTED;
178 }
179         
180 STDMETHODIMP VLCControl::get_Playing(VARIANT_BOOL *isPlaying)
181 {
182     if( NULL == isPlaying )
183         return E_INVALIDARG;
184
185     int i_vlc = _p_instance->getVLCObject();
186     if( i_vlc )
187     {
188         *isPlaying = VLC_IsPlaying(i_vlc) ? VARIANT_TRUE : VARIANT_FALSE;
189         return NOERROR;
190     }
191     *isPlaying = VARIANT_FALSE;
192     return E_UNEXPECTED;
193 };
194         
195 STDMETHODIMP VLCControl::put_Playing(VARIANT_BOOL isPlaying)
196 {
197     int i_vlc = _p_instance->getVLCObject();
198     if( i_vlc )
199     {
200         if( VARIANT_FALSE == isPlaying )
201         {
202             if( VLC_IsPlaying(i_vlc) )
203                 VLC_Stop(i_vlc);
204         }
205         else
206         {
207             if( ! VLC_IsPlaying(i_vlc) )
208                 VLC_Play(i_vlc);
209         }
210         return NOERROR;
211     }
212     return E_UNEXPECTED;
213 };
214         
215 STDMETHODIMP VLCControl::get_Position(float *position)
216 {
217     if( NULL == position )
218         return E_INVALIDARG;
219
220     int i_vlc = _p_instance->getVLCObject();
221     if( i_vlc )
222     {
223         *position = VLC_PositionGet(i_vlc);
224         return NOERROR;
225     }
226     *position = 0.0f;
227     return E_UNEXPECTED;
228 };
229         
230 STDMETHODIMP VLCControl::put_Position(float position)
231 {
232     int i_vlc = _p_instance->getVLCObject();
233     if( i_vlc )
234     {
235         VLC_PositionSet(i_vlc, position);
236         return NOERROR;
237     }
238     return E_UNEXPECTED;
239 };
240         
241 STDMETHODIMP VLCControl::get_Time(int *seconds)
242 {
243     if( NULL == seconds )
244         return E_INVALIDARG;
245
246     int i_vlc = _p_instance->getVLCObject();
247     if( i_vlc )
248     {
249         *seconds = VLC_TimeGet(i_vlc);
250         return NOERROR;
251     }
252     *seconds = 0;
253     return E_UNEXPECTED;
254 };
255         
256 STDMETHODIMP VLCControl::put_Time(int seconds)
257 {
258     int i_vlc = _p_instance->getVLCObject();
259     if( i_vlc )
260     {
261         VLC_TimeSet(i_vlc, seconds, VLC_FALSE);
262         return NOERROR;
263     }
264     return E_UNEXPECTED;
265 };
266         
267 STDMETHODIMP VLCControl::shuttle(int seconds)
268 {
269     int i_vlc = _p_instance->getVLCObject();
270     if( i_vlc )
271     {
272         VLC_TimeSet(i_vlc, seconds, VLC_TRUE);
273         return NOERROR;
274     }
275     return E_UNEXPECTED;
276 };
277         
278 STDMETHODIMP VLCControl::fullscreen(void)
279 {
280     int i_vlc = _p_instance->getVLCObject();
281     if( i_vlc )
282     {
283         VLC_FullScreen(i_vlc);
284         return NOERROR;
285     }
286     return E_UNEXPECTED;
287 };
288         
289 STDMETHODIMP VLCControl::get_Length(int *seconds)
290 {
291     if( NULL == seconds )
292         return E_INVALIDARG;
293
294     int i_vlc = _p_instance->getVLCObject();
295     if( i_vlc )
296     {
297         *seconds = VLC_LengthGet(i_vlc);
298         return NOERROR;
299     }
300     *seconds = 0;
301     return E_UNEXPECTED;
302 };
303         
304 STDMETHODIMP VLCControl::playFaster(void)
305 {
306     int i_vlc = _p_instance->getVLCObject();
307     if( i_vlc )
308     {
309         VLC_SpeedFaster(i_vlc);
310         return NOERROR;
311     }
312     return E_UNEXPECTED;
313 };
314         
315 STDMETHODIMP VLCControl::playSlower(void)
316 {
317     int i_vlc = _p_instance->getVLCObject();
318     if( i_vlc )
319     {
320         VLC_SpeedSlower(i_vlc);
321         return NOERROR;
322     }
323     return E_UNEXPECTED;
324 };
325         
326 STDMETHODIMP VLCControl::get_Volume(int *volume)
327 {
328     if( NULL == volume )
329         return E_INVALIDARG;
330
331     int i_vlc = _p_instance->getVLCObject();
332     if( i_vlc )
333     {
334         *volume  = VLC_VolumeGet(i_vlc);
335         return NOERROR;
336     }
337     *volume = 0;
338     return E_UNEXPECTED;
339 };
340         
341 STDMETHODIMP VLCControl::put_Volume(int volume)
342 {
343     int i_vlc = _p_instance->getVLCObject();
344     if( i_vlc )
345     {
346         VLC_VolumeSet(i_vlc, volume);
347         return NOERROR;
348     }
349     return E_UNEXPECTED;
350 };
351         
352 STDMETHODIMP VLCControl::toggleMute(void)
353 {
354     int i_vlc = _p_instance->getVLCObject();
355     if( i_vlc )
356     {
357         VLC_VolumeMute(i_vlc);
358         return NOERROR;
359     }
360     return E_UNEXPECTED;
361 };
362
363 static void freeTargetOptions(char **cOptions, int cOptionCount)
364 {
365     // clean up 
366     for( long pos=0; pos<cOptionCount; ++pos )
367     {
368         char *cOption = cOptions[pos];
369         if( NULL != cOption )
370             free(cOption);
371         else
372             break;
373     }
374     if( NULL != cOptions )
375         free(cOptions);
376 };
377
378 static HRESULT createTargetOptions(int codePage, VARIANT *options, char ***cOptions, int *cOptionCount)
379 {
380     HRESULT hr = E_INVALIDARG;
381     if( VT_ERROR == V_VT(options) )
382     {
383         if( DISP_E_PARAMNOTFOUND == V_ERROR(options) )
384         {
385             // optional parameter not set
386             *cOptions = NULL;
387             *cOptionCount = 0;
388             return NOERROR;
389         }
390     }
391     else if( (VT_EMPTY == V_VT(options)) || (VT_NULL == V_VT(options)) )
392     {
393         // null parameter
394         *cOptions = NULL;
395         *cOptionCount = 0;
396         return NOERROR;
397     }
398     else if( VT_DISPATCH == V_VT(options) )
399     {
400         // collection parameter
401         VARIANT colEnum;
402         V_VT(&colEnum) = VT_UNKNOWN;
403         hr = GetObjectProperty(V_DISPATCH(options), DISPID_NEWENUM, colEnum);
404         if( SUCCEEDED(hr) )
405         {
406             IEnumVARIANT *enumVar;
407             hr = V_UNKNOWN(&colEnum)->QueryInterface(IID_IEnumVARIANT, (LPVOID *)&enumVar);
408             if( SUCCEEDED(hr) )
409             {
410                 long pos = 0;
411                 long capacity = 16;
412                 VARIANT option;
413
414                 *cOptions = (char **)malloc(capacity*sizeof(char *));
415                 if( NULL != *cOptions )
416                 {
417                     ZeroMemory(*cOptions, sizeof(char *)*capacity);
418                     while( SUCCEEDED(hr) && (S_OK == enumVar->Next(1, &option, NULL)) )
419                     {
420                         if( VT_BSTR == V_VT(&option) )
421                         {
422                             char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));
423                             (*cOptions)[pos] = cOption;
424                             if( NULL != cOption )
425                             {
426                                 ++pos;
427                                 if( pos == capacity )
428                                 {
429                                     char **moreOptions = (char **)realloc(*cOptions, (capacity+16)*sizeof(char *));
430                                     if( NULL != moreOptions )
431                                     {
432                                         ZeroMemory(moreOptions+capacity, sizeof(char *)*16);
433                                         capacity += 16;
434                                         *cOptions = moreOptions;
435                                     }
436                                     else
437                                         hr = E_OUTOFMEMORY;
438                                 }
439                             }
440                             else
441                                 hr = E_OUTOFMEMORY;
442                         }
443                         else
444                             hr = E_INVALIDARG;
445
446                         VariantClear(&option);
447                     }
448                     *cOptionCount = pos;
449                     if( FAILED(hr) )
450                     {
451                         // free already processed elements
452                         freeTargetOptions(*cOptions, *cOptionCount);
453                     }
454                 }
455                 else
456                     hr = E_OUTOFMEMORY;
457                 enumVar->Release();
458             }
459         }
460     }
461     else if( V_ISARRAY(options) )
462     {
463         // array parameter
464         SAFEARRAY *array = V_ISBYREF(options) ? *V_ARRAYREF(options) : V_ARRAY(options);
465
466         if( SafeArrayGetDim(array) != 1 )
467             return E_INVALIDARG;
468
469         long lBound = 0;
470         long uBound = 0;
471         SafeArrayGetLBound(array, 1, &lBound);
472         SafeArrayGetUBound(array, 1, &uBound);
473
474         // have we got any options
475         if( uBound > lBound )
476         {
477             VARTYPE vType;
478             HRESULT hr = SafeArrayGetVartype(array, &vType);
479             if( FAILED(hr) )
480                 return hr;
481
482             long pos;
483
484             // marshall options into an array of C strings
485             if( VT_VARIANT == vType )
486             {
487                 *cOptions = (char **)malloc(sizeof(char *)*(uBound-lBound));
488                 if( NULL != options )
489                     return E_OUTOFMEMORY;
490
491                 for(pos=lBound; SUCCEEDED(hr) && (pos<uBound); ++pos )
492                 {
493                     VARIANT option;
494                     hr = SafeArrayGetElement(array, &pos, &option);
495                     if( SUCCEEDED(hr) )
496                     {
497                         if( VT_BSTR == V_VT(&option) ) 
498                         {
499                             char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));
500                             (*cOptions)[pos-lBound] = cOption;
501                             if( NULL == cOption )
502                                 hr = E_OUTOFMEMORY;
503                         }
504                         else
505                             hr = E_INVALIDARG;
506                         VariantClear(&option);
507                     }
508                 }
509             }
510             else if( VT_BSTR == vType )
511             {
512                 *cOptions = (char **)malloc(sizeof(char *)*(uBound-lBound));
513                 if( NULL != options )
514                     return E_OUTOFMEMORY;
515
516                 ZeroMemory(cOptions, sizeof(char *)*(uBound-lBound));
517                 for(pos=lBound; SUCCEEDED(hr) && (pos<uBound); ++pos )
518                 {
519                     BSTR option;
520                     hr = SafeArrayGetElement(array, &pos, &option);
521                     if( SUCCEEDED(hr) )
522                     {
523                         char *cOption = CStrFromBSTR(codePage, option);
524                         (*cOptions)[pos-lBound] = cOption;
525                         if( NULL == cOption )
526                             hr = E_OUTOFMEMORY;
527                         SysFreeString(option);
528                     }
529                 }
530             }
531             else
532                 // unsupported type
533                 return E_INVALIDARG;
534
535             *cOptionCount = pos-lBound;
536             if( FAILED(hr) )
537             {
538                 // free already processed elements
539                 freeTargetOptions(*cOptions, *cOptionCount);
540             }
541         }
542         else
543         {
544             // empty array
545             *cOptions = NULL;
546             *cOptionCount = 0;
547             return NOERROR;
548         }
549     }
550     return hr;
551 };
552
553 /*
554 ** use VARIANT rather than a SAFEARRAY as argument type
555 ** for compatibility with some scripting language (JScript)
556 */
557
558 STDMETHODIMP VLCControl::addTarget( BSTR uri, VARIANT options, enum VLCPlaylistMode mode, int position)
559 {
560     if( NULL == uri )
561         return E_INVALIDARG;
562
563     HRESULT hr = E_UNEXPECTED;
564
565     int i_vlc = _p_instance->getVLCObject();
566     if( i_vlc )
567     {
568         int codePage = _p_instance->getCodePage();
569         char *cUri = CStrFromBSTR(codePage, uri);
570         if( NULL == cUri )
571             return E_OUTOFMEMORY;
572
573         int cOptionsCount;
574         char **cOptions;
575
576         if( FAILED(createTargetOptions(codePage, &options, &cOptions, &cOptionsCount)) )
577             return E_INVALIDARG;
578
579         VLC_AddTarget(i_vlc, cUri, (const char **)cOptions, cOptionsCount, mode, position);
580         hr = NOERROR;
581
582         freeTargetOptions(cOptions, cOptionsCount);
583         free(cUri);
584     }
585     return hr;
586 };
587         
588 STDMETHODIMP VLCControl::get_PlaylistIndex(int *index)
589 {
590     if( NULL == index )
591         return E_INVALIDARG;
592
593     int i_vlc = _p_instance->getVLCObject();
594     if( i_vlc )
595     {
596         *index = VLC_PlaylistIndex(i_vlc);
597         return NOERROR;
598     }
599     *index = 0;
600     return E_UNEXPECTED;
601 };
602         
603 STDMETHODIMP VLCControl::get_PlaylistCount(int *count)
604 {
605     int i_vlc = _p_instance->getVLCObject();
606     if( i_vlc )
607     {
608         *count = VLC_PlaylistNumberOfItems(i_vlc);
609         return NOERROR;
610     }
611     return E_UNEXPECTED;
612 };
613         
614 STDMETHODIMP VLCControl::playlistNext(void)
615 {
616     int i_vlc = _p_instance->getVLCObject();
617     if( i_vlc )
618     {
619         VLC_PlaylistNext(i_vlc);
620         return NOERROR;
621     }
622     return E_UNEXPECTED;
623 };
624         
625 STDMETHODIMP VLCControl::playlistPrev(void)
626 {
627     int i_vlc = _p_instance->getVLCObject();
628     if( i_vlc )
629     {
630         VLC_PlaylistPrev(i_vlc);
631         return NOERROR;
632     }
633     return E_UNEXPECTED;
634 };
635         
636 STDMETHODIMP VLCControl::playlistClear(void)
637 {
638     int i_vlc = _p_instance->getVLCObject();
639     if( i_vlc )
640     {
641         VLC_PlaylistClear(i_vlc);
642         return NOERROR;
643     }
644     return E_UNEXPECTED;
645 };
646         
647 STDMETHODIMP VLCControl::get_VersionInfo(BSTR *version)
648 {
649     if( NULL == version )
650         return E_INVALIDARG;
651
652     const char *versionStr = VLC_Version();
653     if( NULL != versionStr )
654     {
655         *version = BSTRFromCStr(_p_instance->getCodePage(), versionStr);
656         
657         return NULL == *version ? E_OUTOFMEMORY : NOERROR;
658     }
659     *version = NULL;
660     return E_FAIL;
661 };
662