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