Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

persiststreaminit.cpp

00001 /*****************************************************************************
00002  * persiststreaminit.cpp: ActiveX control for VLC
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  *
00006  * Authors: Damien Fouilleul <[email protected]>
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00021  *****************************************************************************/
00022 
00023 #include "plugin.h"
00024 #include "persiststreaminit.h"
00025 
00026 #include "utils.h"
00027 #include <map>
00028 
00029 #include <malloc.h>
00030 #include <wchar.h>
00031 
00032 using namespace std;
00033 
00034 class AxVLCVariant 
00035 {
00036 
00037 public:
00038 
00039     AxVLCVariant(void)
00040     {
00041         VariantInit(&_v);
00042     };
00043 
00044     ~AxVLCVariant(void)
00045     {
00046         VariantClear(&_v);
00047     }
00048 
00049     AxVLCVariant(VARIANTARG &v)
00050     {
00051         //VariantInit(&_v);
00052         //VariantCopy(&_v, &v);
00053         _v = v;
00054     };
00055 
00056     AxVLCVariant(VARIANTARG *v)
00057     {
00058         VariantInit(&_v);
00059         VariantCopy(&_v, v);
00060     };
00061 
00062     AxVLCVariant(const AxVLCVariant &vv)
00063     {
00064         VariantInit(&_v);
00065         VariantCopy(&_v, const_cast<VARIANTARG *>(&(vv._v)));
00066     };
00067 
00068     AxVLCVariant(int i)
00069     {
00070         V_VT(&_v) = VT_I4;
00071         V_I4(&_v) = i;
00072     };
00073 
00074     AxVLCVariant(BSTR bstr)
00075     {
00076         VARIANT arg;
00077         V_VT(&arg) = VT_BSTR;
00078         V_BSTR(&arg) = bstr;
00079         VariantInit(&_v);
00080         VariantCopy(&_v, &arg);
00081     };
00082 
00083     inline const VARIANTARG *variantArg(void) const {
00084         return &_v;
00085     }
00086 
00087     inline void swap(AxVLCVariant &v1, AxVLCVariant &v2)
00088     {
00089         VARIANTARG tmp = v1._v;
00090         v1._v = v2._v;
00091         v2._v = tmp;
00092     };
00093 
00094 private:
00095 
00096     VARIANTARG _v;
00097 };
00098 
00099 class AxVLCWSTR 
00100 {
00101 
00102 public:
00103 
00104     AxVLCWSTR(void) : _data(NULL) {};
00105 
00106     virtual ~AxVLCWSTR()
00107     {
00108         if( NULL != _data )
00109         {
00110             ULONG refcount = InterlockedDecrement(&(_data->refcount));
00111             if( 0 == refcount )
00112                 CoTaskMemFree(_data);
00113         }
00114     };
00115 
00116     AxVLCWSTR(LPCWSTR s)
00117     {
00118         if( NULL != s )
00119         {
00120             size_t len = wcslen(s);
00121             if( len > 0 )
00122             {
00123                 size_t size = len*sizeof(WCHAR);
00124                 _data = (struct data *)CoTaskMemAlloc(sizeof(struct data)+size);
00125                 if( NULL != _data )
00126                 {
00127                     _data->len = len;
00128                     _data->refcount = 1;
00129                     memcpy(_data->wstr, s, size);
00130                     _data->wstr[len]=L'\0';
00131                     return;
00132                 }
00133             }
00134         }
00135         _data = NULL;
00136     };
00137 
00138     AxVLCWSTR(const AxVLCWSTR &s)
00139     {
00140         _data = s._data;
00141         if( NULL != _data )
00142             InterlockedIncrement(&(_data->refcount));
00143     };
00144 
00145     inline bool operator<(const AxVLCWSTR &s) const
00146     {
00147         return compareNoCase(s.wstr()) < 0;
00148     };
00149 
00150     inline bool operator<(LPCWSTR s) const
00151     {
00152         return compareNoCase(s) < 0;
00153     };
00154 
00155     inline bool operator==(const AxVLCWSTR &s) const
00156     {
00157         return size() == s.size() ?
00158                     (compareNoCase(s.wstr()) == 0) : false;
00159     };
00160 
00161     inline bool operator==(LPCWSTR s) const
00162     {
00163         return compareNoCase(s) == 0;
00164     };
00165 
00166     LPCWSTR wstr(void) const
00167     {
00168         return (NULL != _data) ? _data->wstr : NULL;
00169     };
00170 
00171     size_t size(void) const
00172     {
00173         return (NULL != _data) ? _data->len : 0;
00174     };
00175 
00176 private:
00177 
00178     inline int compareNoCase(LPCWSTR s) const
00179     {
00180         if( NULL == _data )
00181         {
00182             return (NULL == s) ? 0 : -1;
00183         }
00184         if( NULL == s )
00185             return 1;
00186 
00187         return _wcsicmp(_data->wstr, s);
00188     };
00189 
00190     struct data {
00191         size_t  len;
00192         LONG    refcount;
00193         wchar_t wstr[1];
00194     } *_data;
00195 };
00196 
00197 typedef pair<class AxVLCWSTR, class AxVLCVariant> AxVLCPropertyPair;
00198 typedef map<class AxVLCWSTR, class AxVLCVariant> AxVLCPropertyMap;
00199 
00201 
00202 class VLCPropertyBag : public IPropertyBag
00203 {
00204 
00205 public:
00206 
00207     VLCPropertyBag(void) : _i_ref(1) {};
00208     virtual ~VLCPropertyBag() {};
00209 
00210     // IUnknown methods
00211     STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
00212     {
00213         if( NULL == ppv )
00214             return E_POINTER;
00215         if( (IID_IUnknown == riid) 
00216          && (IID_IPropertyBag == riid) )
00217         {
00218             AddRef();
00219             *ppv = reinterpret_cast<LPVOID>(this);
00220             return NOERROR;
00221         }
00222         // standalone object
00223         return E_NOINTERFACE;
00224     };
00225 
00226     STDMETHODIMP_(ULONG) AddRef(void)
00227         { return InterlockedIncrement(&_i_ref); };
00228 
00229     STDMETHODIMP_(ULONG) Release(void)
00230     {
00231         ULONG refcount = InterlockedDecrement(&_i_ref);
00232         if( 0 == refcount )
00233         {
00234             delete this;
00235             return 0;
00236         }
00237         return refcount;
00238     };
00239 
00240     // IPropertyBag methods
00241 
00242     STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
00243     {
00244         if( (NULL == pszPropName) || (NULL == pVar) )
00245             return E_POINTER;
00246 
00247         AxVLCPropertyMap::const_iterator notfound = _pm.end();
00248         AxVLCPropertyMap::const_iterator iter = _pm.find(pszPropName);
00249         if( notfound != iter )
00250         {
00251             VARTYPE vtype = V_VT(pVar);
00252             VARIANTARG v;
00253             VariantInit(&v);
00254             VariantCopy(&v, const_cast<VARIANTARG*>((*iter).second.variantArg()));
00255             if( (V_VT(&v) != vtype) && FAILED(VariantChangeType(&v, &v, 0, vtype)) )
00256             {
00257                 VariantClear(&v);
00258                 return E_FAIL;
00259             }
00260             *pVar = v;
00261             return S_OK;
00262         }
00263         else
00264             return E_INVALIDARG;
00265     };
00266     
00267     STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar)
00268     {
00269         if( (NULL == pszPropName) || (NULL == pVar) )
00270             return E_POINTER;
00271 
00272         AxVLCPropertyPair val(pszPropName, pVar);
00273         pair<AxVLCPropertyMap::iterator, bool> p = _pm.insert(val);
00274         if( false == p.second )
00275             // replace existing key value
00276             (*p.first).second = val.second;
00277         return S_OK;
00278     };
00279    
00280     // custom methods
00281 
00282     HRESULT Load(LPSTREAM pStm)
00283     {
00284         if( NULL == pStm )
00285             return E_INVALIDARG;
00286 
00287         HRESULT result;
00288 
00289         AxVLCPropertyPair *val;
00290         result = ReadProperty(pStm, &val);
00291         if( SUCCEEDED(result) )
00292         {
00293             if( (val->first == L"(Count)") && (VT_I4 == V_VT(val->second.variantArg())) )
00294             {
00295                 size_t count =  V_I4(val->second.variantArg());
00296                 delete val;
00297                 while( count-- )
00298                 {
00299                     result = ReadProperty(pStm, &val);
00300                     if( FAILED(result) )
00301                         return result;
00302 
00303                     pair<AxVLCPropertyMap::iterator, bool> p = _pm.insert(*val);
00304                     if( false == p.second )
00305                         // replace existing key value
00306                         (*p.first).second = val->second;
00307                     delete val;
00308                 }
00309             }
00310         }
00311         return result;
00312     };
00313 
00314     HRESULT Save(LPSTREAM pStm)
00315     {
00316         if( NULL == pStm )
00317             return E_INVALIDARG;
00318 
00319         HRESULT result;
00320 
00321         AxVLCPropertyPair header(L"(Count)", _pm.size());
00322         result = WriteProperty(pStm, header);
00323         if( SUCCEEDED(result) )
00324         {
00325             AxVLCPropertyMap::const_iterator iter = _pm.begin();
00326             AxVLCPropertyMap::const_iterator end  = _pm.end();
00327 
00328             while( iter != end )
00329             {
00330                 result = WriteProperty(pStm, *(iter++));
00331                 if( FAILED(result) )
00332                     return result;
00333             }
00334         }
00335         return result;
00336     };
00337 
00338     BOOL IsEmpty()
00339     {
00340         return _pm.size() == 0;
00341     }
00342 
00343 private:
00344 
00345     HRESULT WriteProperty(LPSTREAM pStm, const AxVLCPropertyPair &prop)
00346     {
00347         HRESULT result;
00348 
00349         const AxVLCWSTR propName = prop.first;
00350 
00351         ULONG len = propName.size();
00352 
00353         if( 0 == len )
00354             return E_INVALIDARG;
00355 
00356         result = pStm->Write(&len, sizeof(len), NULL);
00357         if( FAILED(result) )
00358             return result;
00359 
00360         result = pStm->Write(propName.wstr(), len*sizeof(WCHAR), NULL);
00361         if( FAILED(result) )
00362             return result;
00363 
00364         const VARIANTARG *propValue = prop.second.variantArg();
00365         VARTYPE vtype = V_VT(propValue);
00366         switch( vtype )
00367         {
00368             case VT_BOOL:
00369                 result = pStm->Write(&vtype, sizeof(vtype), NULL);
00370                 if( FAILED(result) )
00371                     return result;
00372                 result = pStm->Write(&V_BOOL(propValue), sizeof(V_BOOL(propValue)), NULL);
00373                 if( FAILED(result) )
00374                     return result;
00375                 break;
00376             case VT_I4:
00377                 result = pStm->Write(&vtype, sizeof(vtype), NULL);
00378                 if( FAILED(result) )
00379                     return result;
00380                 result = pStm->Write(&V_I4(propValue), sizeof(V_I4(propValue)), NULL);
00381                 if( FAILED(result) )
00382                     return result;
00383                 break;
00384             case VT_BSTR:
00385                 result = pStm->Write(&vtype, sizeof(vtype), NULL);
00386                 if( FAILED(result) )
00387                     return result;
00388                 len = SysStringLen(V_BSTR(propValue));
00389                 result = pStm->Write(&len, sizeof(len), NULL);
00390                 if( FAILED(result) )
00391                     return result;
00392                 if( len > 0 )
00393                 { 
00394                     result = pStm->Write(V_BSTR(propValue), len*sizeof(OLECHAR), NULL);
00395                     if( FAILED(result) )
00396                         return result;
00397                 }
00398                 break;
00399             default:
00400                 vtype = VT_EMPTY;
00401                 result = pStm->Write(&vtype, sizeof(vtype), NULL);
00402                 if( FAILED(result) )
00403                     return result;
00404         }
00405         return result;
00406     };
00407 
00408     HRESULT ReadProperty(LPSTREAM pStm, AxVLCPropertyPair **prop)
00409     {
00410         HRESULT result;
00411 
00412         ULONG len;
00413 
00414         result = pStm->Read(&len, sizeof(len), NULL);
00415         if( FAILED(result) )
00416             return result;
00417 
00418         if( 0 == len )
00419             return E_INVALIDARG;
00420 
00421         LPWSTR propName = (LPOLESTR)::alloca((len+1)*sizeof(WCHAR));
00422         if( NULL == propName )
00423             return E_OUTOFMEMORY;
00424 
00425         result = pStm->Read(propName, len*sizeof(WCHAR), NULL);
00426         if( FAILED(result) )
00427             return result;
00428 
00429         propName[len] = L'\0';
00430 
00431         VARIANTARG propValue;
00432 
00433         VARTYPE vtype;
00434         result = pStm->Read(&vtype, sizeof(vtype), NULL);
00435         if( FAILED(result) )
00436             return result;
00437 
00438         switch( vtype )
00439         {
00440             case VT_BOOL:
00441                 V_VT(&propValue) = vtype;
00442                 result = pStm->Read(&V_BOOL(&propValue), sizeof(V_BOOL(&propValue)), NULL);
00443                 if( FAILED(result) )
00444                     return result;
00445                 break;
00446             case VT_I4:
00447                 V_VT(&propValue) = vtype;
00448                 result = pStm->Read(&V_I4(&propValue), sizeof(V_I4(&propValue)), NULL);
00449                 if( FAILED(result) )
00450                     return result;
00451                 break;
00452             case VT_BSTR:
00453                 V_VT(&propValue) = vtype;
00454                 result = pStm->Read(&len, sizeof(len), NULL);
00455                 if( FAILED(result) )
00456                     return result;
00457 
00458                 V_BSTR(&propValue) = NULL;
00459                 if( len > 0 )
00460                 {
00461                     V_BSTR(&propValue) = SysAllocStringLen(NULL, len);
00462                     if( NULL == V_BSTR(&propValue) )
00463                         return E_OUTOFMEMORY;
00464 
00465                     result = pStm->Read(V_BSTR(&propValue), len*sizeof(OLECHAR), NULL);
00466                     if( FAILED(result) )
00467                     {
00468                         SysFreeString(V_BSTR(&propValue));
00469                         return result;
00470                     }
00471                 }
00472                 break;
00473             default:
00474                 VariantInit(&propValue);
00475         }
00476 
00477         *prop = new AxVLCPropertyPair(propName, propValue);
00478 
00479         return S_OK;
00480     };
00481 
00482     AxVLCPropertyMap _pm;
00483     LONG _i_ref;
00484 };
00485 
00487 
00488 VLCPersistStreamInit::VLCPersistStreamInit(VLCPlugin *p_instance) : _p_instance(p_instance)
00489 {
00490     _p_props = new VLCPropertyBag();
00491 };
00492 
00493 VLCPersistStreamInit::~VLCPersistStreamInit()
00494 {
00495     _p_props->Release();
00496 };
00497 
00498 STDMETHODIMP VLCPersistStreamInit::GetClassID(LPCLSID pClsID)
00499 {
00500     if( NULL == pClsID )
00501         return E_POINTER;
00502 
00503     *pClsID = _p_instance->getClassID();
00504 
00505     return S_OK;
00506 };
00507 
00508 STDMETHODIMP VLCPersistStreamInit::InitNew(void)
00509 {
00510     return _p_instance->onInit();
00511 };
00512 
00513 STDMETHODIMP VLCPersistStreamInit::Load(LPSTREAM pStm)
00514 {
00515     HRESULT result = _p_props->Load(pStm);
00516     if( FAILED(result) )
00517         return result;
00518 
00519     LPPERSISTPROPERTYBAG pPersistPropBag;
00520     if( FAILED(QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropBag)) )
00521         return E_FAIL;
00522 
00523     result = pPersistPropBag->Load(_p_props, NULL);
00524     pPersistPropBag->Release();
00525 
00526     return result;
00527 };
00528 
00529 STDMETHODIMP VLCPersistStreamInit::Save(LPSTREAM pStm, BOOL fClearDirty)
00530 {
00531     if( NULL == pStm )
00532         return E_INVALIDARG;
00533 
00534     LPPERSISTPROPERTYBAG pPersistPropBag;
00535     if( FAILED(QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropBag)) )
00536         return E_FAIL;
00537 
00538     HRESULT result = pPersistPropBag->Save(_p_props, fClearDirty, _p_props->IsEmpty());
00539     pPersistPropBag->Release();
00540     if( FAILED(result) )
00541         return result;
00542 
00543     return _p_props->Save(pStm);
00544 };
00545 
00546 STDMETHODIMP VLCPersistStreamInit::IsDirty(void)
00547 {
00548     return _p_instance->isDirty() ? S_OK : S_FALSE;
00549 };
00550 
00551 STDMETHODIMP VLCPersistStreamInit::GetSizeMax(ULARGE_INTEGER *pcbSize)
00552 {
00553     pcbSize->HighPart = 0UL;
00554     pcbSize->LowPart  = 4096UL; // just a guess
00555 
00556     return S_OK;
00557 };
00558 

Generated on Tue Dec 20 10:14:18 2005 for vlc-0.8.4a by  doxygen 1.4.2