-/*****************************************************************************\r
- * vlccontrol.cpp: ActiveX control for VLC\r
- *****************************************************************************\r
- * Copyright (C) 2005 VideoLAN\r
- *\r
- * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\r
- *****************************************************************************/\r
-\r
-#include "plugin.h"\r
-#include "vlccontrol.h"\r
-\r
-#include "utils.h"\r
-\r
-VLCControl::~VLCControl()\r
-{\r
- if( _p_typeinfo )\r
- _p_typeinfo->Release();\r
-};\r
-\r
-HRESULT VLCControl::getTypeInfo(void)\r
-{\r
- HRESULT hr = NOERROR;\r
- if( NULL == _p_typeinfo )\r
- {\r
- ITypeLib *p_typelib;\r
-\r
- HRESULT hr = _p_instance->getTypeLib(&p_typelib);\r
- if( SUCCEEDED(hr) )\r
- {\r
- hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl, &_p_typeinfo);\r
- if( FAILED(hr) )\r
- {\r
- _p_typeinfo = NULL;\r
- }\r
- p_typelib->Release();\r
- }\r
- }\r
- return hr;\r
-};\r
-\r
-STDMETHODIMP VLCControl::GetTypeInfoCount(UINT* pctInfo)\r
-{\r
- if( SUCCEEDED(getTypeInfo()) )\r
- *pctInfo = 1;\r
- else\r
- *pctInfo = 0;\r
-\r
- return NOERROR;\r
-};\r
-\r
-STDMETHODIMP VLCControl::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)\r
-{\r
- if( NULL == ppTInfo )\r
- return E_INVALIDARG;\r
-\r
- if( SUCCEEDED(getTypeInfo()) )\r
- {\r
- _p_typeinfo->AddRef();\r
- *ppTInfo = _p_typeinfo;\r
- return NO_ERROR;\r
- }\r
- *ppTInfo = NULL;\r
- return E_NOTIMPL;\r
-};\r
-\r
-STDMETHODIMP VLCControl::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, \r
- UINT cNames, LCID lcid, DISPID* rgDispID)\r
-{\r
- if( SUCCEEDED(getTypeInfo()) )\r
- {\r
- return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);\r
- }\r
- return E_NOTIMPL;\r
-};\r
-\r
-STDMETHODIMP VLCControl::Invoke(DISPID dispIdMember, REFIID riid,\r
- LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,\r
- VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)\r
-{\r
- if( SUCCEEDED(getTypeInfo()) )\r
- {\r
- return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,\r
- pVarResult, pExcepInfo, puArgErr);\r
- }\r
- return E_NOTIMPL;\r
-};\r
-\r
-STDMETHODIMP VLCControl::get_Value(VARIANT *pvarValue)\r
-{\r
- if( NULL == pvarValue )\r
- return E_INVALIDARG;\r
-\r
- V_VT(pvarValue) = VT_BOOL;\r
- return get_Playing(&V_BOOL(pvarValue));\r
-};\r
- \r
-STDMETHODIMP VLCControl::put_Value(VARIANT pvarValue)\r
-{\r
- if( VT_BOOL != V_VT(&pvarValue) )\r
- {\r
- VARIANT boolValue;\r
- HRESULT hr = VariantChangeType(&boolValue, &pvarValue, 0, VT_BOOL);\r
- if( SUCCEEDED(hr) )\r
- {\r
- hr = get_Playing(&V_BOOL(&pvarValue));\r
- //VariantClear(&boolValue);\r
- }\r
- return hr;\r
- }\r
- return get_Playing(&V_BOOL(&pvarValue));\r
-};\r
- \r
-STDMETHODIMP VLCControl::get_Visible(VARIANT_BOOL *isVisible)\r
-{\r
- if( NULL == isVisible )\r
- return E_INVALIDARG;\r
-\r
- if( _p_instance->isInPlaceActive() )\r
- *isVisible = _p_instance->isVisible() ? VARIANT_TRUE : VARIANT_FALSE;\r
- else\r
- *isVisible = VARIANT_FALSE;\r
-\r
- return NOERROR;\r
-};\r
- \r
-STDMETHODIMP VLCControl::put_Visible(VARIANT_BOOL isVisible)\r
-{\r
- if( _p_instance->isInPlaceActive() )\r
- _p_instance->setVisible(isVisible != VARIANT_FALSE);\r
- else\r
- _p_instance->setShowDisplay(isVisible != VARIANT_FALSE);\r
-\r
- return NOERROR;\r
-};\r
-\r
-STDMETHODIMP VLCControl::play(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_Play(i_vlc);\r
- _p_instance->fireOnPlayEvent();\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::pause(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_Pause(i_vlc);\r
- _p_instance->fireOnPauseEvent();\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::stop(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_Stop(i_vlc);\r
- _p_instance->fireOnStopEvent();\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-}\r
- \r
-STDMETHODIMP VLCControl::get_Playing(VARIANT_BOOL *isPlaying)\r
-{\r
- if( NULL == isPlaying )\r
- return E_INVALIDARG;\r
-\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- *isPlaying = VLC_IsPlaying(i_vlc) ? VARIANT_TRUE : VARIANT_FALSE;\r
- return NOERROR;\r
- }\r
- *isPlaying = VARIANT_FALSE;\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::put_Playing(VARIANT_BOOL isPlaying)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- if( VARIANT_FALSE == isPlaying )\r
- {\r
- if( VLC_IsPlaying(i_vlc) )\r
- VLC_Stop(i_vlc);\r
- }\r
- else\r
- {\r
- if( ! VLC_IsPlaying(i_vlc) )\r
- VLC_Play(i_vlc);\r
- }\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::get_Position(float *position)\r
-{\r
- if( NULL == position )\r
- return E_INVALIDARG;\r
-\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- *position = VLC_PositionGet(i_vlc);\r
- return NOERROR;\r
- }\r
- *position = 0.0f;\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::put_Position(float position)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_PositionSet(i_vlc, position);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::get_Time(int *seconds)\r
-{\r
- if( NULL == seconds )\r
- return E_INVALIDARG;\r
-\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- *seconds = VLC_TimeGet(i_vlc);\r
- return NOERROR;\r
- }\r
- *seconds = 0;\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::put_Time(int seconds)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_TimeSet(i_vlc, seconds, VLC_FALSE);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::shuttle(int seconds)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_TimeSet(i_vlc, seconds, VLC_TRUE);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::fullscreen(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_FullScreen(i_vlc);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::get_Length(int *seconds)\r
-{\r
- if( NULL == seconds )\r
- return E_INVALIDARG;\r
-\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- *seconds = VLC_LengthGet(i_vlc);\r
- return NOERROR;\r
- }\r
- *seconds = 0;\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::playFaster(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_SpeedFaster(i_vlc);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::playSlower(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_SpeedSlower(i_vlc);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::get_Volume(int *volume)\r
-{\r
- if( NULL == volume )\r
- return E_INVALIDARG;\r
-\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- *volume = VLC_VolumeGet(i_vlc);\r
- return NOERROR;\r
- }\r
- *volume = 0;\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::put_Volume(int volume)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_VolumeSet(i_vlc, volume);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::toggleMute(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_VolumeMute(i_vlc);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
-\r
-static void freeTargetOptions(char **cOptions, int cOptionCount)\r
-{\r
- // clean up \r
- for( long pos=0; pos<cOptionCount; ++pos )\r
- {\r
- char *cOption = cOptions[pos];\r
- if( NULL != cOption )\r
- free(cOption);\r
- else\r
- break;\r
- }\r
- if( NULL != cOptions )\r
- free(cOptions);\r
-};\r
-\r
-static HRESULT createTargetOptions(int codePage, VARIANT *options, char ***cOptions, int *cOptionCount)\r
-{\r
- HRESULT hr = E_INVALIDARG;\r
- if( VT_ERROR == V_VT(options) )\r
- {\r
- if( DISP_E_PARAMNOTFOUND == V_ERROR(options) )\r
- {\r
- // optional parameter not set\r
- *cOptions = NULL;\r
- *cOptionCount = 0;\r
- return NOERROR;\r
- }\r
- }\r
- else if( (VT_EMPTY == V_VT(options)) || (VT_NULL == V_VT(options)) )\r
- {\r
- // null parameter\r
- *cOptions = NULL;\r
- *cOptionCount = 0;\r
- return NOERROR;\r
- }\r
- else if( VT_DISPATCH == V_VT(options) )\r
- {\r
- // collection parameter\r
- VARIANT colEnum;\r
- V_VT(&colEnum) = VT_UNKNOWN;\r
- hr = GetObjectProperty(V_DISPATCH(options), DISPID_NEWENUM, colEnum);\r
- if( SUCCEEDED(hr) )\r
- {\r
- IEnumVARIANT *enumVar;\r
- hr = V_UNKNOWN(&colEnum)->QueryInterface(IID_IEnumVARIANT, (LPVOID *)&enumVar);\r
- if( SUCCEEDED(hr) )\r
- {\r
- long pos = 0;\r
- long capacity = 16;\r
- VARIANT option;\r
-\r
- *cOptions = (char **)malloc(capacity*sizeof(char *));\r
- if( NULL != *cOptions )\r
- {\r
- ZeroMemory(*cOptions, sizeof(char *)*capacity);\r
- while( SUCCEEDED(hr) && (S_OK == enumVar->Next(1, &option, NULL)) )\r
- {\r
- if( VT_BSTR == V_VT(&option) )\r
- {\r
- char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));\r
- (*cOptions)[pos] = cOption;\r
- if( NULL != cOption )\r
- {\r
- ++pos;\r
- if( pos == capacity )\r
- {\r
- char **moreOptions = (char **)realloc(*cOptions, (capacity+16)*sizeof(char *));\r
- if( NULL != moreOptions )\r
- {\r
- ZeroMemory(moreOptions+capacity, sizeof(char *)*16);\r
- capacity += 16;\r
- *cOptions = moreOptions;\r
- }\r
- else\r
- hr = E_OUTOFMEMORY;\r
- }\r
- }\r
- else\r
- hr = E_OUTOFMEMORY;\r
- }\r
- else\r
- hr = E_INVALIDARG;\r
-\r
- VariantClear(&option);\r
- }\r
- *cOptionCount = pos;\r
- if( FAILED(hr) )\r
- {\r
- // free already processed elements\r
- freeTargetOptions(*cOptions, *cOptionCount);\r
- }\r
- }\r
- else\r
- hr = E_OUTOFMEMORY;\r
- enumVar->Release();\r
- }\r
- }\r
- }\r
- else if( V_ISARRAY(options) )\r
- {\r
- // array parameter\r
- SAFEARRAY *array = V_ISBYREF(options) ? *V_ARRAYREF(options) : V_ARRAY(options);\r
-\r
- if( SafeArrayGetDim(array) != 1 )\r
- return E_INVALIDARG;\r
-\r
- long lBound = 0;\r
- long uBound = 0;\r
- SafeArrayGetLBound(array, 1, &lBound);\r
- SafeArrayGetUBound(array, 1, &uBound);\r
-\r
- // have we got any options\r
- if( uBound > lBound )\r
- {\r
- VARTYPE vType;\r
- HRESULT hr = SafeArrayGetVartype(array, &vType);\r
- if( FAILED(hr) )\r
- return hr;\r
-\r
- long pos;\r
-\r
- // marshall options into an array of C strings\r
- if( VT_VARIANT == vType )\r
- {\r
- *cOptions = (char **)malloc(sizeof(char *)*(uBound-lBound));\r
- if( NULL != options )\r
- return E_OUTOFMEMORY;\r
-\r
- for(pos=lBound; SUCCEEDED(hr) && (pos<uBound); ++pos )\r
- {\r
- VARIANT option;\r
- hr = SafeArrayGetElement(array, &pos, &option);\r
- if( SUCCEEDED(hr) )\r
- {\r
- if( VT_BSTR == V_VT(&option) ) \r
- {\r
- char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));\r
- (*cOptions)[pos-lBound] = cOption;\r
- if( NULL == cOption )\r
- hr = E_OUTOFMEMORY;\r
- }\r
- else\r
- hr = E_INVALIDARG;\r
- VariantClear(&option);\r
- }\r
- }\r
- }\r
- else if( VT_BSTR == vType )\r
- {\r
- *cOptions = (char **)malloc(sizeof(char *)*(uBound-lBound));\r
- if( NULL != options )\r
- return E_OUTOFMEMORY;\r
-\r
- ZeroMemory(cOptions, sizeof(char *)*(uBound-lBound));\r
- for(pos=lBound; SUCCEEDED(hr) && (pos<uBound); ++pos )\r
- {\r
- BSTR option;\r
- hr = SafeArrayGetElement(array, &pos, &option);\r
- if( SUCCEEDED(hr) )\r
- {\r
- char *cOption = CStrFromBSTR(codePage, option);\r
- (*cOptions)[pos-lBound] = cOption;\r
- if( NULL == cOption )\r
- hr = E_OUTOFMEMORY;\r
- SysFreeString(option);\r
- }\r
- }\r
- }\r
- else\r
- // unsupported type\r
- return E_INVALIDARG;\r
-\r
- *cOptionCount = pos-lBound;\r
- if( FAILED(hr) )\r
- {\r
- // free already processed elements\r
- freeTargetOptions(*cOptions, *cOptionCount);\r
- }\r
- }\r
- else\r
- {\r
- // empty array\r
- *cOptions = NULL;\r
- *cOptionCount = 0;\r
- return NOERROR;\r
- }\r
- }\r
- return hr;\r
-};\r
-\r
-/*\r
-** use VARIANT rather than a SAFEARRAY as argument type\r
-** for compatibility with some scripting language (JScript)\r
-*/\r
-\r
-STDMETHODIMP VLCControl::addTarget( BSTR uri, VARIANT options, enum VLCPlaylistMode mode, int position)\r
-{\r
- if( NULL == uri )\r
- return E_INVALIDARG;\r
-\r
- HRESULT hr = E_UNEXPECTED;\r
-\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- int codePage = _p_instance->getCodePage();\r
- char *cUri = CStrFromBSTR(codePage, uri);\r
- if( NULL == cUri )\r
- return E_OUTOFMEMORY;\r
-\r
- int cOptionsCount;\r
- char **cOptions;\r
-\r
- if( FAILED(createTargetOptions(codePage, &options, &cOptions, &cOptionsCount)) )\r
- return E_INVALIDARG;\r
-\r
- VLC_AddTarget(i_vlc, cUri, (const char **)cOptions, cOptionsCount, mode, position);\r
- hr = NOERROR;\r
-\r
- freeTargetOptions(cOptions, cOptionsCount);\r
- free(cUri);\r
- }\r
- return hr;\r
-};\r
- \r
-STDMETHODIMP VLCControl::get_PlaylistIndex(int *index)\r
-{\r
- if( NULL == index )\r
- return E_INVALIDARG;\r
-\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- *index = VLC_PlaylistIndex(i_vlc);\r
- return NOERROR;\r
- }\r
- *index = 0;\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::get_PlaylistCount(int *count)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- *count = VLC_PlaylistNumberOfItems(i_vlc);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::playlistNext(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_PlaylistNext(i_vlc);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::playlistPrev(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_PlaylistPrev(i_vlc);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::playlistClear(void)\r
-{\r
- int i_vlc = _p_instance->getVLCObject();\r
- if( i_vlc )\r
- {\r
- VLC_PlaylistClear(i_vlc);\r
- return NOERROR;\r
- }\r
- return E_UNEXPECTED;\r
-};\r
- \r
-STDMETHODIMP VLCControl::get_VersionInfo(BSTR *version)\r
-{\r
- if( NULL == version )\r
- return E_INVALIDARG;\r
-\r
- const char *versionStr = VLC_Version();\r
- if( NULL != versionStr )\r
- {\r
- *version = BSTRFromCStr(_p_instance->getCodePage(), versionStr);\r
- \r
- return NULL == *version ? E_OUTOFMEMORY : NOERROR;\r
- }\r
- *version = NULL;\r
- return E_FAIL;\r
-};\r
- \r
+/*****************************************************************************
+ * vlccontrol.cpp: ActiveX control for VLC
+ *****************************************************************************
+ * Copyright (C) 2005 the VideoLAN team
+ *
+ * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "plugin.h"
+#include "vlccontrol.h"
+
+#include "utils.h"
+
+using namespace std;
+
+VLCControl::~VLCControl()
+{
+ if( _p_typeinfo )
+ _p_typeinfo->Release();
+};
+
+HRESULT VLCControl::getTypeInfo(void)
+{
+ HRESULT hr = NOERROR;
+ if( NULL == _p_typeinfo )
+ {
+ ITypeLib *p_typelib;
+
+ hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
+ if( SUCCEEDED(hr) )
+ {
+ hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCControl, &_p_typeinfo);
+ if( FAILED(hr) )
+ {
+ _p_typeinfo = NULL;
+ }
+ p_typelib->Release();
+ }
+ }
+ return hr;
+};
+
+STDMETHODIMP VLCControl::GetTypeInfoCount(UINT* pctInfo)
+{
+ if( NULL == pctInfo )
+ return E_INVALIDARG;
+
+ if( SUCCEEDED(getTypeInfo()) )
+ *pctInfo = 1;
+ else
+ *pctInfo = 0;
+
+ return NOERROR;
+};
+
+STDMETHODIMP VLCControl::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
+{
+ if( NULL == ppTInfo )
+ return E_INVALIDARG;
+
+ if( SUCCEEDED(getTypeInfo()) )
+ {
+ _p_typeinfo->AddRef();
+ *ppTInfo = _p_typeinfo;
+ return NOERROR;
+ }
+ *ppTInfo = NULL;
+ return E_NOTIMPL;
+};
+
+STDMETHODIMP VLCControl::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
+ UINT cNames, LCID lcid, DISPID* rgDispID)
+{
+ if( SUCCEEDED(getTypeInfo()) )
+ {
+ return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
+ }
+ return E_NOTIMPL;
+};
+
+STDMETHODIMP VLCControl::Invoke(DISPID dispIdMember, REFIID riid,
+ LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
+ VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
+{
+ if( SUCCEEDED(getTypeInfo()) )
+ {
+ return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
+ pVarResult, pExcepInfo, puArgErr);
+ }
+ return E_NOTIMPL;
+};
+
+STDMETHODIMP VLCControl::get_Visible(VARIANT_BOOL *isVisible)
+{
+ if( NULL == isVisible )
+ return E_POINTER;
+
+ *isVisible = _p_instance->getVisible() ? VARIANT_TRUE : VARIANT_FALSE;
+
+ return NOERROR;
+};
+
+STDMETHODIMP VLCControl::put_Visible(VARIANT_BOOL isVisible)
+{
+ _p_instance->setVisible(isVisible != VARIANT_FALSE);
+
+ return NOERROR;
+};
+
+STDMETHODIMP VLCControl::play(void)
+{
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_Play(i_vlc);
+ _p_instance->fireOnPlayEvent();
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::pause(void)
+{
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_Pause(i_vlc);
+ _p_instance->fireOnPauseEvent();
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::stop(void)
+{
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_Stop(i_vlc);
+ _p_instance->fireOnStopEvent();
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::get_Playing(VARIANT_BOOL *isPlaying)
+{
+ if( NULL == isPlaying )
+ return E_POINTER;
+
+ HRESULT result = NOERROR;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ *isPlaying = VLC_IsPlaying(i_vlc) ? VARIANT_TRUE : VARIANT_FALSE;
+ return NOERROR;
+ }
+ }
+ *isPlaying = VARIANT_FALSE;
+ return result;
+};
+
+STDMETHODIMP VLCControl::get_Position(float *position)
+{
+ if( NULL == position )
+ return E_POINTER;
+
+ HRESULT result = E_UNEXPECTED;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ *position = VLC_PositionGet(i_vlc);
+ return NOERROR;
+ }
+ }
+ *position = 0.0f;
+ return result;
+};
+
+STDMETHODIMP VLCControl::put_Position(float position)
+{
+ HRESULT result = E_UNEXPECTED;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_PositionSet(i_vlc, position);
+ }
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::get_Time(int *seconds)
+{
+ if( NULL == seconds )
+ return E_POINTER;
+
+ HRESULT result = NOERROR;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ *seconds = VLC_TimeGet(i_vlc);
+ }
+ }
+ else
+ *seconds = _p_instance->getTime();
+
+ return result;
+};
+
+STDMETHODIMP VLCControl::put_Time(int seconds)
+{
+ _p_instance->setTime(seconds);
+
+ return NOERROR;
+};
+
+STDMETHODIMP VLCControl::shuttle(int seconds)
+{
+ HRESULT result = E_UNEXPECTED;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_TimeSet(i_vlc, seconds, VLC_TRUE);
+ }
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::fullscreen(void)
+{
+ HRESULT result = E_UNEXPECTED;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_FullScreen(i_vlc);
+ }
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::get_Length(int *seconds)
+{
+ if( NULL == seconds )
+ return E_POINTER;
+
+ HRESULT result = NOERROR;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ *seconds = VLC_LengthGet(i_vlc);
+ return NOERROR;
+ }
+ }
+ *seconds = 0;
+ return result;
+};
+
+STDMETHODIMP VLCControl::playFaster(void)
+{
+ HRESULT result = E_UNEXPECTED;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_SpeedFaster(i_vlc);
+ }
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::playSlower(void)
+{
+ HRESULT result = E_UNEXPECTED;
+ if( _p_instance->isRunning() )
+ {
+ int i_vlc;
+ result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_SpeedSlower(i_vlc);
+ }
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::get_Volume(int *volume)
+{
+ if( NULL == volume )
+ return E_POINTER;
+
+ *volume = _p_instance->getVolume();
+ return NOERROR;
+};
+
+STDMETHODIMP VLCControl::put_Volume(int volume)
+{
+ _p_instance->setVolume(volume);
+ return NOERROR;
+};
+
+STDMETHODIMP VLCControl::toggleMute(void)
+{
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_VolumeMute(i_vlc);
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::setVariable(BSTR name, VARIANT value)
+{
+ if( 0 == SysStringLen(name) )
+ return E_INVALIDARG;
+
+ int i_vlc;
+ HRESULT hr = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(hr) )
+ {
+ int codePage = _p_instance->getCodePage();
+ char *psz_varname = CStrFromBSTR(codePage, name);
+ if( NULL == psz_varname )
+ return E_OUTOFMEMORY;
+
+ int i_type;
+ vlc_value_t val;
+
+ if( VLC_SUCCESS == VLC_VariableType(i_vlc, psz_varname, &i_type) )
+ {
+ VARIANT arg;
+ VariantInit(&arg);
+
+ switch( i_type )
+ {
+ case VLC_VAR_BOOL:
+ hr = VariantChangeType(&arg, &value, 0, VT_BOOL);
+ if( SUCCEEDED(hr) )
+ val.b_bool = (VARIANT_TRUE == V_BOOL(&arg)) ? VLC_TRUE : VLC_FALSE;
+ break;
+
+ case VLC_VAR_INTEGER:
+ case VLC_VAR_HOTKEY:
+ hr = VariantChangeType(&arg, &value, 0, VT_I4);
+ if( SUCCEEDED(hr) )
+ val.i_int = V_I4(&arg);
+ break;
+
+ case VLC_VAR_FLOAT:
+ hr = VariantChangeType(&arg, &value, 0, VT_R4);
+ if( SUCCEEDED(hr) )
+ val.f_float = V_R4(&arg);
+ break;
+
+ case VLC_VAR_STRING:
+ case VLC_VAR_MODULE:
+ case VLC_VAR_FILE:
+ case VLC_VAR_DIRECTORY:
+ case VLC_VAR_VARIABLE:
+ hr = VariantChangeType(&arg, &value, 0, VT_BSTR);
+ if( SUCCEEDED(hr) )
+ {
+ i_type = VLC_VAR_STRING;
+ val.psz_string = CStrFromBSTR(codePage, V_BSTR(&arg));
+ VariantClear(&arg);
+ }
+ break;
+
+ case VLC_VAR_TIME:
+ // use a double value to represent time (base is expressed in seconds)
+ hr = VariantChangeType(&arg, &value, 0, VT_R8);
+ if( SUCCEEDED(hr) )
+ val.i_time = (signed __int64)(V_R8(&arg)*1000000.0);
+ break;
+
+ default:
+ hr = DISP_E_TYPEMISMATCH;
+ }
+ }
+ else {
+ // no defined type, use type in VARIANT
+ hr = NO_ERROR;
+ switch( V_VT(&value) )
+ {
+ case VT_BOOL:
+ val.b_bool = (VARIANT_TRUE == V_BOOL(&value)) ? VLC_TRUE : VLC_FALSE;
+ i_type = VLC_VAR_BOOL;
+ break;
+ case VT_I4:
+ val.i_int = V_I4(&value);
+ i_type = VLC_VAR_INTEGER;
+ break;
+ case VT_R4:
+ val.f_float = V_R4(&value);
+ i_type = VLC_VAR_FLOAT;
+ break;
+ case VT_BSTR:
+ val.psz_string = CStrFromBSTR(codePage, V_BSTR(&value));
+ i_type = VLC_VAR_STRING;
+ break;
+ case VT_R8:
+ // use a double value to represent time (base is expressed in seconds)
+ val.i_time = (signed __int64)(V_R8(&value)*1000000.0);
+ i_type = VLC_VAR_TIME;
+ break;
+ default:
+ hr = DISP_E_TYPEMISMATCH;
+ }
+ }
+ if( SUCCEEDED(hr) )
+ {
+ hr = (VLC_SUCCESS == VLC_VariableSet(i_vlc, psz_varname, val)) ? NOERROR : E_FAIL;
+
+ if( (VLC_VAR_STRING == i_type) && (NULL != val.psz_string) )
+ CoTaskMemFree(val.psz_string);
+ }
+ CoTaskMemFree(psz_varname);
+ }
+ return hr;
+};
+
+STDMETHODIMP VLCControl::getVariable( BSTR name, VARIANT *value)
+{
+ if( NULL == value )
+ return E_POINTER;
+
+ VariantInit(value);
+
+ if( 0 == SysStringLen(name) )
+ return E_INVALIDARG;
+
+ int i_vlc;
+ HRESULT hr = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(hr) )
+ {
+ UINT codePage = _p_instance->getCodePage();
+ char *psz_varname = CStrFromBSTR(codePage, name);
+ if( NULL == psz_varname )
+ return E_OUTOFMEMORY;
+
+ hr = E_INVALIDARG;
+
+ vlc_value_t val;
+ int i_type;
+
+ if( (VLC_SUCCESS == VLC_VariableGet(i_vlc, psz_varname, &val))
+ && (VLC_SUCCESS == VLC_VariableType(i_vlc, psz_varname, &i_type)) )
+ {
+ hr = NOERROR;
+ switch( i_type )
+ {
+ case VLC_VAR_BOOL:
+ V_VT(value) = VT_BOOL;
+ V_BOOL(value) = val.b_bool ? VARIANT_TRUE : VARIANT_FALSE;
+ break;
+
+ case VLC_VAR_INTEGER:
+ case VLC_VAR_HOTKEY:
+ V_VT(value) = VT_I4;
+ V_I4(value) = val.i_int;
+ break;
+
+ case VLC_VAR_FLOAT:
+ V_VT(value) = VT_R4;
+ V_R4(value) = val.f_float;
+ break;
+
+ case VLC_VAR_STRING:
+ case VLC_VAR_MODULE:
+ case VLC_VAR_FILE:
+ case VLC_VAR_DIRECTORY:
+ case VLC_VAR_VARIABLE:
+ V_VT(value) = VT_BSTR;
+ V_BSTR(value) = BSTRFromCStr(codePage, val.psz_string);
+ if( NULL != val.psz_string)
+ free(val.psz_string);
+ break;
+
+ case VLC_VAR_TIME:
+ // use a double value to represent time (base is expressed in seconds)
+ V_VT(value) = VT_R8;
+ V_R8(value) = ((double)val.i_time)/1000000.0;
+ break;
+
+ default:
+ hr = DISP_E_TYPEMISMATCH;
+ }
+ }
+ CoTaskMemFree(psz_varname);
+ return hr;
+ }
+ return hr;
+};
+
+void VLCControl::FreeTargetOptions(char **cOptions, int cOptionCount)
+{
+ // clean up
+ if( NULL != cOptions )
+ {
+ for( int pos=0; pos<cOptionCount; ++pos )
+ {
+ char *cOption = cOptions[pos];
+ if( NULL != cOption )
+ CoTaskMemFree(cOption);
+ else
+ break;
+ }
+ CoTaskMemFree(cOptions);
+ }
+};
+
+static HRESULT parseStringOptions(int codePage, BSTR bstr, char*** cOptions, int *cOptionCount)
+{
+ HRESULT hr = E_INVALIDARG;
+ if( SysStringLen(bstr) > 0 )
+ {
+ hr = E_OUTOFMEMORY;
+ char *s = CStrFromBSTR(codePage, bstr);
+ char *val = s;
+ if( val )
+ {
+ long capacity = 16;
+ char **options = (char **)CoTaskMemAlloc(capacity*sizeof(char *));
+ if( options )
+ {
+ int nOptions = 0;
+
+ char *end = val + strlen(val);
+ while( val < end )
+ {
+ // skip leading blanks
+ while( (val < end)
+ && ((*val == ' ' ) || (*val == '\t')) )
+ ++val;
+
+ char *start = val;
+ // skip till we get a blank character
+ while( (val < end)
+ && (*val != ' ' )
+ && (*val != '\t') )
+ {
+ char c = *(val++);
+ if( ('\'' == c) || ('"' == c) )
+ {
+ // skip till end of string
+ while( (val < end) && (*(val++) != c ) );
+ }
+ }
+
+ if( val > start )
+ {
+ if( nOptions == capacity )
+ {
+ capacity += 16;
+ char **moreOptions = (char **)CoTaskMemRealloc(options, capacity*sizeof(char*));
+ if( ! moreOptions )
+ {
+ /* failed to allocate more memory */
+ CoTaskMemFree(s);
+ /* return what we got so far */
+ *cOptionCount = nOptions;
+ *cOptions = options;
+ return NOERROR;
+ }
+ options = moreOptions;
+ }
+ *(val++) = '\0';
+ options[nOptions] = (char *)CoTaskMemAlloc(val-start);
+ if( options[nOptions] )
+ {
+ memcpy(options[nOptions], start, val-start);
+ ++nOptions;
+ }
+ else
+ {
+ /* failed to allocate memory */
+ CoTaskMemFree(s);
+ /* return what we got so far */
+ *cOptionCount = nOptions;
+ *cOptions = options;
+ return NOERROR;
+ }
+ }
+ else
+ // must be end of string
+ break;
+ }
+ *cOptionCount = nOptions;
+ *cOptions = options;
+ hr = NOERROR;
+ }
+ CoTaskMemFree(s);
+ }
+ }
+ return hr;
+}
+
+HRESULT VLCControl::CreateTargetOptions(int codePage, VARIANT *options, char ***cOptions, int *cOptionCount)
+{
+ HRESULT hr = E_INVALIDARG;
+ if( VT_ERROR == V_VT(options) )
+ {
+ if( DISP_E_PARAMNOTFOUND == V_ERROR(options) )
+ {
+ // optional parameter not set
+ *cOptions = NULL;
+ *cOptionCount = 0;
+ return NOERROR;
+ }
+ }
+ else if( (VT_EMPTY == V_VT(options)) || (VT_NULL == V_VT(options)) )
+ {
+ // null parameter
+ *cOptions = NULL;
+ *cOptionCount = 0;
+ return NOERROR;
+ }
+ else if( VT_DISPATCH == V_VT(options) )
+ {
+ // if object is a collection, retrieve enumerator
+ VARIANT colEnum;
+ V_VT(&colEnum) = VT_UNKNOWN;
+ hr = GetObjectProperty(V_DISPATCH(options), DISPID_NEWENUM, colEnum);
+ if( SUCCEEDED(hr) )
+ {
+ IEnumVARIANT *enumVar;
+ hr = V_UNKNOWN(&colEnum)->QueryInterface(IID_IEnumVARIANT, (LPVOID *)&enumVar);
+ if( SUCCEEDED(hr) )
+ {
+ long pos = 0;
+ long capacity = 16;
+ VARIANT option;
+
+ *cOptions = (char **)CoTaskMemAlloc(capacity*sizeof(char *));
+ if( NULL != *cOptions )
+ {
+ ZeroMemory(*cOptions, sizeof(char *)*capacity);
+ while( SUCCEEDED(hr) && (S_OK == enumVar->Next(1, &option, NULL)) )
+ {
+ if( VT_BSTR == V_VT(&option) )
+ {
+ char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));
+ (*cOptions)[pos] = cOption;
+ if( NULL != cOption )
+ {
+ ++pos;
+ if( pos == capacity )
+ {
+ char **moreOptions = (char **)CoTaskMemRealloc(*cOptions, (capacity+16)*sizeof(char *));
+ if( NULL != moreOptions )
+ {
+ ZeroMemory(moreOptions+capacity, sizeof(char *)*16);
+ capacity += 16;
+ *cOptions = moreOptions;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ hr = ( SysStringLen(V_BSTR(&option)) > 0 ) ?
+ E_OUTOFMEMORY : E_INVALIDARG;
+ }
+ else
+ hr = E_INVALIDARG;
+
+ VariantClear(&option);
+ }
+ *cOptionCount = pos;
+ if( FAILED(hr) )
+ {
+ // free already processed elements
+ FreeTargetOptions(*cOptions, *cOptionCount);
+ }
+ }
+ else
+ hr = E_OUTOFMEMORY;
+
+ enumVar->Release();
+ }
+ }
+ else
+ {
+ // coerce object into a string and parse it
+ VARIANT v_name;
+ VariantInit(&v_name);
+ hr = VariantChangeType(&v_name, options, 0, VT_BSTR);
+ if( SUCCEEDED(hr) )
+ {
+ hr = parseStringOptions(codePage, V_BSTR(&v_name), cOptions, cOptionCount);
+ VariantClear(&v_name);
+ }
+ }
+ }
+ else if( V_ISARRAY(options) )
+ {
+ // array parameter
+ SAFEARRAY *array = V_ISBYREF(options) ? *V_ARRAYREF(options) : V_ARRAY(options);
+
+ if( SafeArrayGetDim(array) != 1 )
+ return E_INVALIDARG;
+
+ long lBound = 0;
+ long uBound = 0;
+ SafeArrayGetLBound(array, 1, &lBound);
+ SafeArrayGetUBound(array, 1, &uBound);
+
+ // have we got any options
+ if( uBound >= lBound )
+ {
+ VARTYPE vType;
+ hr = SafeArrayGetVartype(array, &vType);
+ if( FAILED(hr) )
+ return hr;
+
+ long pos;
+
+ // marshall options into an array of C strings
+ if( VT_VARIANT == vType )
+ {
+ *cOptions = (char **)CoTaskMemAlloc(sizeof(char *)*(uBound-lBound+1));
+ if( NULL == *cOptions )
+ return E_OUTOFMEMORY;
+
+ ZeroMemory(*cOptions, sizeof(char *)*(uBound-lBound+1));
+ for(pos=lBound; (pos<=uBound) && SUCCEEDED(hr); ++pos )
+ {
+ VARIANT option;
+ hr = SafeArrayGetElement(array, &pos, &option);
+ if( SUCCEEDED(hr) )
+ {
+ if( VT_BSTR == V_VT(&option) )
+ {
+ char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));
+ (*cOptions)[pos-lBound] = cOption;
+ if( NULL == cOption )
+ hr = ( SysStringLen(V_BSTR(&option)) > 0 ) ?
+ E_OUTOFMEMORY : E_INVALIDARG;
+ }
+ else
+ hr = E_INVALIDARG;
+ VariantClear(&option);
+ }
+ }
+ }
+ else if( VT_BSTR == vType )
+ {
+ *cOptions = (char **)CoTaskMemAlloc(sizeof(char *)*(uBound-lBound+1));
+ if( NULL == *cOptions )
+ return E_OUTOFMEMORY;
+
+ ZeroMemory(*cOptions, sizeof(char *)*(uBound-lBound+1));
+ for(pos=lBound; (pos<=uBound) && SUCCEEDED(hr); ++pos )
+ {
+ BSTR option;
+ hr = SafeArrayGetElement(array, &pos, &option);
+ if( SUCCEEDED(hr) )
+ {
+ char *cOption = CStrFromBSTR(codePage, option);
+
+ (*cOptions)[pos-lBound] = cOption;
+ if( NULL == cOption )
+ hr = ( SysStringLen(option) > 0 ) ?
+ E_OUTOFMEMORY : E_INVALIDARG;
+ SysFreeString(option);
+ }
+ }
+ }
+ else
+ {
+ // unsupported type
+ return E_INVALIDARG;
+ }
+
+ *cOptionCount = pos-lBound;
+ if( FAILED(hr) )
+ {
+ // free already processed elements
+ FreeTargetOptions(*cOptions, *cOptionCount);
+ }
+ }
+ else
+ {
+ // empty array
+ *cOptions = NULL;
+ *cOptionCount = 0;
+ return NOERROR;
+ }
+ }
+ else if( VT_UNKNOWN == V_VT(options) )
+ {
+ // coerce object into a string and parse it
+ VARIANT v_name;
+ VariantInit(&v_name);
+ hr = VariantChangeType(&v_name, options, 0, VT_BSTR);
+ if( SUCCEEDED(hr) )
+ {
+ hr = parseStringOptions(codePage, V_BSTR(&v_name), cOptions, cOptionCount);
+ VariantClear(&v_name);
+ }
+ }
+ else if( VT_BSTR == V_VT(options) )
+ {
+ hr = parseStringOptions(codePage, V_BSTR(options), cOptions, cOptionCount);
+ }
+ return hr;
+};
+
+/*
+** use VARIANT rather than a SAFEARRAY as argument type
+** for compatibility with some scripting language (JScript)
+*/
+
+STDMETHODIMP VLCControl::addTarget( BSTR uri, VARIANT options, enum VLCPlaylistMode mode, int position)
+{
+ if( 0 == SysStringLen(uri) )
+ return E_INVALIDARG;
+
+ int i_vlc;
+ HRESULT hr = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(hr) )
+ {
+ char *cUri = CStrFromBSTR(CP_UTF8, uri);
+ if( NULL == cUri )
+ return E_OUTOFMEMORY;
+
+ int cOptionsCount;
+ char **cOptions;
+
+ if( FAILED(CreateTargetOptions(CP_UTF8, &options, &cOptions, &cOptionsCount)) )
+ return E_INVALIDARG;
+
+ if( VLC_SUCCESS <= VLC_AddTarget(i_vlc, cUri, (const char **)cOptions, cOptionsCount, mode, position) )
+ {
+ hr = NOERROR;
+ if( mode & PLAYLIST_GO )
+ _p_instance->fireOnPlayEvent();
+ }
+ else
+ {
+ hr = E_FAIL;
+ if( mode & PLAYLIST_GO )
+ _p_instance->fireOnStopEvent();
+ }
+
+ FreeTargetOptions(cOptions, cOptionsCount);
+ CoTaskMemFree(cUri);
+ }
+ return hr;
+};
+
+STDMETHODIMP VLCControl::get_PlaylistIndex(int *index)
+{
+ if( NULL == index )
+ return E_POINTER;
+
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ *index = VLC_PlaylistIndex(i_vlc);
+ return NOERROR;
+ }
+ *index = 0;
+ return result;
+};
+
+STDMETHODIMP VLCControl::get_PlaylistCount(int *count)
+{
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ *count = VLC_PlaylistNumberOfItems(i_vlc);
+ return NOERROR;
+ }
+ *count = 0;
+ return result;
+};
+
+STDMETHODIMP VLCControl::playlistNext(void)
+{
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_PlaylistNext(i_vlc);
+ return NOERROR;
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::playlistPrev(void)
+{
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_PlaylistPrev(i_vlc);
+ return NOERROR;
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::playlistClear(void)
+{
+ int i_vlc;
+ HRESULT result = _p_instance->getVLCObject(&i_vlc);
+ if( SUCCEEDED(result) )
+ {
+ VLC_PlaylistClear(i_vlc);
+ return NOERROR;
+ }
+ return result;
+};
+
+STDMETHODIMP VLCControl::get_VersionInfo(BSTR *version)
+{
+ if( NULL == version )
+ return E_POINTER;
+
+ const char *versionStr = VLC_Version();
+ if( NULL != versionStr )
+ {
+ *version = BSTRFromCStr(CP_UTF8, versionStr);
+
+ return NULL == *version ? E_OUTOFMEMORY : NOERROR;
+ }
+ *version = NULL;
+ return E_FAIL;
+};
+
+STDMETHODIMP VLCControl::get_MRL(BSTR *mrl)
+{
+ if( NULL == mrl )
+ return E_POINTER;
+
+ *mrl = SysAllocStringLen(_p_instance->getMRL(),
+ SysStringLen(_p_instance->getMRL()));
+ return NOERROR;
+};
+
+STDMETHODIMP VLCControl::put_MRL(BSTR mrl)
+{
+ _p_instance->setMRL(mrl);
+
+ return S_OK;
+};
+
+STDMETHODIMP VLCControl::get_AutoPlay(VARIANT_BOOL *autoplay)
+{
+ if( NULL == autoplay )
+ return E_POINTER;
+
+ *autoplay = _p_instance->getAutoPlay() ? VARIANT_TRUE: VARIANT_FALSE;
+ return S_OK;
+};
+
+STDMETHODIMP VLCControl::put_AutoPlay(VARIANT_BOOL autoplay)
+{
+ _p_instance->setAutoPlay((VARIANT_FALSE != autoplay) ? TRUE: FALSE);
+ return S_OK;
+};
+
+STDMETHODIMP VLCControl::get_AutoLoop(VARIANT_BOOL *autoloop)
+{
+ if( NULL == autoloop )
+ return E_POINTER;
+
+ *autoloop = _p_instance->getAutoLoop() ? VARIANT_TRUE: VARIANT_FALSE;
+ return S_OK;
+};
+
+STDMETHODIMP VLCControl::put_AutoLoop(VARIANT_BOOL autoloop)
+{
+ _p_instance->setAutoLoop((VARIANT_FALSE != autoloop) ? TRUE: FALSE);
+ return S_OK;
+};