1 /*****************************************************************************
2 * persiststreaminit.cpp: ActiveX control for VLC
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
6 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
24 #include "persiststreaminit.h"
49 AxVLCVariant(VARIANTARG &v)
52 //VariantCopy(&_v, &v);
56 AxVLCVariant(VARIANTARG *v)
62 AxVLCVariant(const AxVLCVariant &vv)
65 VariantCopy(&_v, const_cast<VARIANTARG *>(&(vv._v)));
74 AxVLCVariant(BSTR bstr)
80 VariantCopy(&_v, &arg);
83 inline const VARIANTARG *variantArg(void) const {
87 inline void swap(AxVLCVariant &v1, AxVLCVariant &v2)
89 VARIANTARG tmp = v1._v;
104 AxVLCWSTR(void) : _data(NULL) {};
110 ULONG refcount = InterlockedDecrement(&(_data->refcount));
112 CoTaskMemFree(_data);
120 size_t len = wcslen(s);
123 size_t size = len*sizeof(WCHAR);
124 _data = (struct data *)CoTaskMemAlloc(sizeof(struct data)+size);
129 memcpy(_data->wstr, s, size);
130 _data->wstr[len]=L'\0';
138 AxVLCWSTR(const AxVLCWSTR &s)
142 InterlockedIncrement(&(_data->refcount));
145 inline bool operator<(const AxVLCWSTR &s) const
147 return compareNoCase(s.wstr()) < 0;
150 inline bool operator<(LPCWSTR s) const
152 return compareNoCase(s) < 0;
155 inline bool operator==(const AxVLCWSTR &s) const
157 return size() == s.size() ?
158 (compareNoCase(s.wstr()) == 0) : false;
161 inline bool operator==(LPCWSTR s) const
163 return compareNoCase(s) == 0;
166 LPCWSTR wstr(void) const
168 return (NULL != _data) ? _data->wstr : NULL;
171 size_t size(void) const
173 return (NULL != _data) ? _data->len : 0;
178 inline int compareNoCase(LPCWSTR s) const
182 return (NULL == s) ? 0 : -1;
187 return _wcsicmp(_data->wstr, s);
197 typedef pair<class AxVLCWSTR, class AxVLCVariant> AxVLCPropertyPair;
198 typedef map<class AxVLCWSTR, class AxVLCVariant> AxVLCPropertyMap;
200 ///////////////////////////
202 class VLCPropertyBag : public IPropertyBag
207 VLCPropertyBag(void) : _i_ref(1) {};
208 virtual ~VLCPropertyBag() {};
211 STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
215 if( (IID_IUnknown == riid)
216 || (IID_IPropertyBag == riid) )
219 *ppv = reinterpret_cast<LPVOID>(this);
223 return E_NOINTERFACE;
226 STDMETHODIMP_(ULONG) AddRef(void)
227 { return InterlockedIncrement(&_i_ref); };
229 STDMETHODIMP_(ULONG) Release(void)
231 ULONG refcount = InterlockedDecrement(&_i_ref);
240 // IPropertyBag methods
242 STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
244 if( (NULL == pszPropName) || (NULL == pVar) )
247 AxVLCPropertyMap::const_iterator notfound = _pm.end();
248 AxVLCPropertyMap::const_iterator iter = _pm.find(pszPropName);
249 if( notfound != iter )
251 VARTYPE vtype = V_VT(pVar);
254 VariantCopy(&v, const_cast<VARIANTARG*>((*iter).second.variantArg()));
255 if( (V_VT(&v) != vtype) && FAILED(VariantChangeType(&v, &v, 0, vtype)) )
267 STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar)
269 if( (NULL == pszPropName) || (NULL == pVar) )
272 AxVLCPropertyPair val(pszPropName, pVar);
273 pair<AxVLCPropertyMap::iterator, bool> p = _pm.insert(val);
274 if( false == p.second )
275 // replace existing key value
276 (*p.first).second = val.second;
282 HRESULT Load(LPSTREAM pStm)
289 AxVLCPropertyPair *val;
290 result = ReadProperty(pStm, &val);
291 if( SUCCEEDED(result) )
293 if( (val->first == L"(Count)") && (VT_I4 == V_VT(val->second.variantArg())) )
295 size_t count = V_I4(val->second.variantArg());
299 result = ReadProperty(pStm, &val);
303 pair<AxVLCPropertyMap::iterator, bool> p = _pm.insert(*val);
304 if( false == p.second )
305 // replace existing key value
306 (*p.first).second = val->second;
314 HRESULT Save(LPSTREAM pStm)
321 AxVLCPropertyPair header(L"(Count)", _pm.size());
322 result = WriteProperty(pStm, header);
323 if( SUCCEEDED(result) )
325 AxVLCPropertyMap::const_iterator iter = _pm.begin();
326 AxVLCPropertyMap::const_iterator end = _pm.end();
330 result = WriteProperty(pStm, *(iter++));
340 return _pm.size() == 0;
345 HRESULT WriteProperty(LPSTREAM pStm, const AxVLCPropertyPair &prop)
349 const AxVLCWSTR propName = prop.first;
351 ULONG len = propName.size();
356 result = pStm->Write(&len, sizeof(len), NULL);
360 result = pStm->Write(propName.wstr(), len*sizeof(WCHAR), NULL);
364 const VARIANTARG *propValue = prop.second.variantArg();
365 VARTYPE vtype = V_VT(propValue);
369 result = pStm->Write(&vtype, sizeof(vtype), NULL);
372 result = pStm->Write(&V_BOOL(propValue), sizeof(V_BOOL(propValue)), NULL);
377 result = pStm->Write(&vtype, sizeof(vtype), NULL);
380 result = pStm->Write(&V_I4(propValue), sizeof(V_I4(propValue)), NULL);
385 result = pStm->Write(&vtype, sizeof(vtype), NULL);
388 len = SysStringLen(V_BSTR(propValue));
389 result = pStm->Write(&len, sizeof(len), NULL);
394 result = pStm->Write(V_BSTR(propValue), len*sizeof(OLECHAR), NULL);
401 result = pStm->Write(&vtype, sizeof(vtype), NULL);
408 HRESULT ReadProperty(LPSTREAM pStm, AxVLCPropertyPair **prop)
414 result = pStm->Read(&len, sizeof(len), NULL);
421 LPWSTR propName = (LPOLESTR)::alloca((len+1)*sizeof(WCHAR));
422 if( NULL == propName )
423 return E_OUTOFMEMORY;
425 result = pStm->Read(propName, len*sizeof(WCHAR), NULL);
429 propName[len] = L'\0';
431 VARIANTARG propValue;
434 result = pStm->Read(&vtype, sizeof(vtype), NULL);
441 V_VT(&propValue) = vtype;
442 result = pStm->Read(&V_BOOL(&propValue), sizeof(V_BOOL(&propValue)), NULL);
447 V_VT(&propValue) = vtype;
448 result = pStm->Read(&V_I4(&propValue), sizeof(V_I4(&propValue)), NULL);
453 V_VT(&propValue) = vtype;
454 result = pStm->Read(&len, sizeof(len), NULL);
458 V_BSTR(&propValue) = NULL;
461 V_BSTR(&propValue) = SysAllocStringLen(NULL, len);
462 if( NULL == V_BSTR(&propValue) )
463 return E_OUTOFMEMORY;
465 result = pStm->Read(V_BSTR(&propValue), len*sizeof(OLECHAR), NULL);
468 SysFreeString(V_BSTR(&propValue));
474 VariantInit(&propValue);
477 *prop = new AxVLCPropertyPair(propName, propValue);
482 AxVLCPropertyMap _pm;
486 ///////////////////////////
488 VLCPersistStreamInit::VLCPersistStreamInit(VLCPlugin *p_instance) : _p_instance(p_instance)
490 _p_props = new VLCPropertyBag();
493 VLCPersistStreamInit::~VLCPersistStreamInit()
498 STDMETHODIMP VLCPersistStreamInit::GetClassID(LPCLSID pClsID)
503 *pClsID = _p_instance->getClassID();
508 STDMETHODIMP VLCPersistStreamInit::InitNew(void)
510 return _p_instance->onInit();
513 STDMETHODIMP VLCPersistStreamInit::Load(LPSTREAM pStm)
515 HRESULT result = _p_props->Load(pStm);
519 LPPERSISTPROPERTYBAG pPersistPropBag;
520 if( FAILED(QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropBag)) )
523 result = pPersistPropBag->Load(_p_props, NULL);
524 pPersistPropBag->Release();
529 STDMETHODIMP VLCPersistStreamInit::Save(LPSTREAM pStm, BOOL fClearDirty)
534 LPPERSISTPROPERTYBAG pPersistPropBag;
535 if( FAILED(QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropBag)) )
538 HRESULT result = pPersistPropBag->Save(_p_props, fClearDirty, _p_props->IsEmpty());
539 pPersistPropBag->Release();
543 return _p_props->Save(pStm);
546 STDMETHODIMP VLCPersistStreamInit::IsDirty(void)
548 return _p_instance->isDirty() ? S_OK : S_FALSE;
551 STDMETHODIMP VLCPersistStreamInit::GetSizeMax(ULARGE_INTEGER *pcbSize)
553 pcbSize->HighPart = 0UL;
554 pcbSize->LowPart = 4096UL; // just a guess