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