/**************************************************************************** * * RealNetworks Transform Architecture * * $Id: rtaconfigagenthelper.h,v 1.6.4.2 2002/06/21 00:04:49 rbunnage Exp $ * * Copyright (C) 1995-2001 RealNetworks, Inc. All rights reserved. * * http://www.real.com/devzone * * This program contains proprietary information of RealNetworks, Inc, * and is licensed subject to restrictions on use and distribution. * * Defines a configuration agent template for implementing the property bag * and configuration classes for external plugin agent classes. * */ // what about error bag // what about logging #ifndef _rtaconfigagenthelper_h #define _rtaconfigagenthelper_h #include "rtabase.h" #include "rtapropertybag.h" class CRSConfigurationAgentHelper: public IRTAConfigurationAgent { public: CRSConfigurationAgentHelper() : m_pPropertyBag( NULL ) , m_pFactory( NULL ) , m_bInitDone( FALSE ) , m_bAllowChanges(TRUE) { } ~CRSConfigurationAgentHelper() { PN_RELEASE( m_pPropertyBag ); PN_RELEASE( m_pFactory ); } STDMETHODIMP Initialize( IRTAPropertyBag* pPropBag, IRTAPropertyBag** ppErrorBag ) { PN_RESULT res = PNR_OK; // Allow successful initialization at most once if (m_bInitDone || !m_pFactory || !m_pPropertyBag) { return PNR_ENC_IMPROPER_STATE; } // Create new bag to hold props consumed during filter initialization IRTAPropertyBag *pConsumedProps = NULL; res = m_pFactory->CreateInstance( IID_IRTAPropertyBag, (void **) &pConsumedProps ); // Create new bag to hold properties that failed validation IRTAPropertyBag *pErrorBag = NULL; if (SUCCEEDED(res)) res = m_pFactory->CreateInstance( IID_IRTAPropertyBag, (void **) &pErrorBag ); if (SUCCEEDED(res)) res = OnInitialize( pPropBag, pConsumedProps, pErrorBag ); // Add consumed props to internal prop bag if (SUCCEEDED(res)) { IRTAPropertyEnumerator *pEnum = NULL; res = pConsumedProps->GetPropertyEnumerator( &pEnum ); IRTAProperty* pProp = NULL; PN_RESULT resEnum = PNR_OK; if (SUCCEEDED(res)) resEnum = pEnum->First( &pProp ); while (SUCCEEDED(resEnum) && resEnum != PNR_ELEMENT_NOT_FOUND && SUCCEEDED(res)) { res = m_pPropertyBag->SetProperty( pProp ); PN_RELEASE( pProp ); if (SUCCEEDED(res)) resEnum = pEnum->Next( &pProp ); } PN_RELEASE( pEnum ); PN_RELEASE( pProp ); } // Enumerate through the unconsumed props and dispatch them appropriately if (SUCCEEDED(res) && pPropBag) { IRTAPropertyEnumerator *pEnum = NULL; res = pPropBag->GetPropertyEnumerator( &pEnum ); IRTAProperty* pProp = NULL; PN_RESULT resEnum = PNR_OK; if (SUCCEEDED(res)) resEnum = pEnum->First( &pProp ); while (SUCCEEDED(resEnum) && resEnum != PNR_ELEMENT_NOT_FOUND && SUCCEEDED(res)) { // If the property wasn't already consumed, call the overrideable SetProp function IRTAProperty *pConsumedProp = NULL; PN_RESULT resConsumed = pConsumedProps->GetProperty( pProp->GetKey(), &pConsumedProp ); if (FAILED(resConsumed)) { switch ( pProp->GetType()) { case eTypeBOOL: { BOOL bValue = 0; res = pPropBag->GetBool( pProp->GetKey(), &bValue ); if (SUCCEEDED(res)) res = SetBool( pProp->GetKey(), bValue ); break; } case eTypeINT32: { INT32 lValue = 0; res = pPropBag->GetInt( pProp->GetKey(), &lValue); if (SUCCEEDED(res)) res = SetInt( pProp->GetKey(), lValue); break; } case eTypeUINT32: { UINT32 ulValue = 0; res = pPropBag->GetUint(pProp->GetKey(), &ulValue); if (SUCCEEDED(res)) res = SetUint(pProp->GetKey(), ulValue); break; } case eTypeINT64: { INT64 llValue = 0; res = pPropBag->GetInt64(pProp->GetKey(), &llValue); if (SUCCEEDED(res)) res = SetInt64(pProp->GetKey(), llValue); break; } case eTypeDouble: { double dValue = 0; res = pPropBag->GetDouble(pProp->GetKey(), &dValue); if (SUCCEEDED(res)) res = SetDouble(pProp->GetKey(), dValue); break; } case eTypeCString: { const char* szValue = NULL; res = pPropBag->GetString(pProp->GetKey(), &szValue); if (SUCCEEDED(res)) res = SetString( pProp->GetKey(), szValue ); break; } case eTypeComposite: { IRTAPropertyBag* pTempBag; res = pPropBag->GetPropertyBag( pProp->GetKey(), &pTempBag ); if (SUCCEEDED(res)) res = SetPropertyBag( pProp->GetKey(), pTempBag ); PN_RELEASE( pTempBag ); break; } case eTypeUnknown: { IUnknown* pUnknown = NULL; res = pPropBag->GetUnknown(pProp->GetKey(), &pUnknown ); if (SUCCEEDED(res)) res = SetUnknown(pProp->GetKey(), pUnknown ); PN_RELEASE( pUnknown ); break; } // Revisit when more types are added default: res = SetProperty(pProp); }; } // Add any properties that failed validation to the error bag if (FAILED(res)) PN_RESULT resAppend = pErrorBag->SetProperty(pProp); PN_RELEASE( pConsumedProp ); resEnum = pEnum->Next( &pProp ); } PN_RELEASE( pEnum ); PN_RELEASE( pProp ); } // If everything was successful, mark initialization as complete if (SUCCEEDED(res)) m_bInitDone = TRUE; if (ppErrorBag) { *ppErrorBag = pErrorBag; (*ppErrorBag)->AddRef(); } PN_RELEASE( pErrorBag ); PN_RELEASE( pConsumedProps ); return res; } STDMETHOD_(UINT32, GetCount)() { return m_pPropertyBag->GetCount(); } STDMETHODIMP GetProperty( const char* szName, IRTAProperty** ppProperty ) { if (!szName || !ppProperty) { return PNR_POINTER; } PN_RESULT res = m_pPropertyBag->GetProperty(szName, ppProperty); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to get property: %s", szName); } return res; } STDMETHODIMP SetProperty( IRTAProperty *pProperty ) { PN_RESULT res = PNR_OK; if (!pProperty) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetProperty(pProperty); if (SUCCEEDED(res)) res = m_pPropertyBag->SetProperty(pProperty); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set property: %s", pProperty->GetKey()); } return res; } STDMETHODIMP GetBool( const char* szName, BOOL *pbValue) { if (!szName || !pbValue) { return PNR_POINTER; } PN_RESULT res = m_pPropertyBag->GetBool(szName, pbValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to get bool: %s", szName); } return res; } STDMETHODIMP SetBool( const char* szName, BOOL bValue) { PN_RESULT res = PNR_OK; if (!szName) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetBool(szName, bValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetBool(szName, bValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set bool: %s", szName); } return res; } STDMETHODIMP GetInt( const char* szName, INT32 *puValue) { if (!szName || !puValue) { return PNR_POINTER; } PN_RESULT res = m_pPropertyBag->GetInt(szName, puValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to get int: %s", szName); } return res; } STDMETHODIMP SetInt( const char* szName, INT32 uValue) { PN_RESULT res = PNR_OK; if (!szName) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetInt(szName, uValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetInt(szName, uValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set int: %s", szName); } return res; } STDMETHODIMP GetUint( const char* szName, UINT32* pulValue) { if (!szName || !pulValue) { return PNR_POINTER; } PN_RESULT res = m_pPropertyBag->GetUint(szName, pulValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to get uint: %s", szName); } return res; } STDMETHODIMP SetUint( const char* szName, UINT32 uValue) { PN_RESULT res = PNR_OK; if (!szName) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetUint(szName, uValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetUint(szName, uValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set uint: %s", szName); } return res; } STDMETHODIMP GetInt64( const char* szName, INT64 *puValue) { if (!szName || !puValue) { return PNR_POINTER; } PN_RESULT res = m_pPropertyBag->GetInt64(szName, puValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to get int64: %s", szName); } return res; } STDMETHODIMP SetInt64( const char* szName, INT64 uValue) { PN_RESULT res = PNR_OK; if (!szName) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetInt64(szName, uValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetInt64(szName, uValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set int64: %s", szName); } return res; } STDMETHODIMP GetDouble( const char* szName, double *puValue) { if (!szName || !puValue) { return PNR_POINTER; } PN_RESULT res = m_pPropertyBag->GetDouble(szName, puValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set double: %s", szName); } return res; } STDMETHODIMP SetDouble( const char* szName, double uValue) { PN_RESULT res = PNR_OK; if (!szName) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetDouble(szName, uValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetDouble(szName, uValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set double: %s", szName); } return res; } STDMETHODIMP GetString( const char* szName, const CHAR **pcszValue ) { if (!szName || !pcszValue) { return PNR_POINTER; } PN_RESULT res = m_pPropertyBag->GetString(szName, pcszValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to get string: %s", szName); } return res; } STDMETHODIMP SetString( const char* szName, const CHAR *cszValue ) { PN_RESULT res = PNR_OK; if (!szName || !cszValue) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetString(szName, cszValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetString(szName, cszValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set string: %s", szName); } return res; } STDMETHODIMP GetPropertyBag( const char* szName, IRTAPropertyBag **ppValue) { if (!szName || !ppValue) { return PNR_POINTER; } PN_RESULT res = m_pPropertyBag->GetPropertyBag(szName, ppValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to get property bag: %s", szName); } return res; } STDMETHODIMP SetPropertyBag( const char* szName, IRTAPropertyBag *pValue) { PN_RESULT res = PNR_OK; if (!szName || !pValue) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetPropertyBag(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetPropertyBag(szName, pValue); if (FAILED(res)) { //RSLOG(LC_SDK_WARN, FA_GEN_FILTER, "Failed to set property bag: %s", szName); } return res; } STDMETHODIMP GetIntList( const char* szName, IRTAIntList **ppValue) { return m_pPropertyBag->GetIntList(szName, ppValue); } STDMETHODIMP SetIntList( const char* szName, IRTAIntList *pValue) { PN_RESULT res = OnSetIntList(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetIntList(szName, pValue); return res; } STDMETHODIMP GetUintList( const char* szName, IRTAUintList **ppValue) { return m_pPropertyBag->GetUintList(szName, ppValue); } STDMETHODIMP SetUintList( const char* szName, IRTAUintList *pValue) { PN_RESULT res = OnSetUintList(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetUintList(szName, pValue); return res; } STDMETHODIMP GetInt64List( const char* szName, IRTAInt64List **ppValue) { return m_pPropertyBag->GetInt64List(szName, ppValue); } STDMETHODIMP SetInt64List( const char* szName, IRTAInt64List *pValue) { PN_RESULT res = OnSetInt64List(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetInt64List(szName, pValue); return res; } STDMETHODIMP GetDoubleList( const char* szName, IRTADoubleList **ppValue) { return m_pPropertyBag->GetDoubleList(szName, ppValue); } STDMETHODIMP SetDoubleList( const char* szName, IRTADoubleList *pValue) { PN_RESULT res = OnSetDoubleList(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetDoubleList(szName, pValue); return res; } STDMETHODIMP GetIntRange( const char* szName, IRTAIntRange **ppValue) { return m_pPropertyBag->GetIntRange(szName, ppValue); } STDMETHODIMP SetIntRange( const char* szName, IRTAIntRange *pValue) { PN_RESULT res = OnSetIntRange(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetIntRange(szName, pValue); return res; } STDMETHODIMP GetUintRange( const char* szName, IRTAUintRange **ppValue) { return m_pPropertyBag->GetUintRange(szName, ppValue); } STDMETHODIMP SetUintRange( const char* szName, IRTAUintRange *pValue) { PN_RESULT res = OnSetUintRange(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetUintRange(szName, pValue); return res; } STDMETHODIMP GetInt64Range( const char* szName, IRTAInt64Range **ppValue) { return m_pPropertyBag->GetInt64Range(szName, ppValue); } STDMETHODIMP SetInt64Range( const char* szName, IRTAInt64Range *pValue) { PN_RESULT res = OnSetInt64Range(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetInt64Range(szName, pValue); return res; } STDMETHODIMP GetDoubleRange( const char* szName, IRTADoubleRange **ppValue) { return m_pPropertyBag->GetDoubleRange(szName, ppValue); } STDMETHODIMP SetDoubleRange( const char* szName, IRTADoubleRange *pValue) { PN_RESULT res = OnSetDoubleRange(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetDoubleRange(szName, pValue); return res; } STDMETHODIMP GetUnknown( const char* szName, IUnknown **ppType ) { return m_pPropertyBag->GetUnknown( szName, ppType ); } STDMETHODIMP SetUnknown( const char* szName, IUnknown *pValue ) { PN_RESULT res = PNR_OK; if (!szName || !pValue) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnSetUnknown(szName, pValue); if (SUCCEEDED(res)) res = m_pPropertyBag->SetUnknown(szName, pValue); //if (FAILED(res)) // RSLOG(LC_SDK_DIAG, FA_GEN_FILTER, "Failed to set IUnknown: %s", szName); return res; } STDMETHODIMP Remove( const char* szName ) { PN_RESULT res = PNR_OK; // Validate params if (!szName) { return PNR_POINTER; } // Check if changes are allowed if (!m_bAllowChanges) { res = PNR_ENC_IMPROPER_STATE; } if (SUCCEEDED(res)) res = OnRemove(szName); if (SUCCEEDED(res)) res = m_pPropertyBag->Remove( szName ); //if (FAILED(res)) // RSLOG(LC_SDK_DIAG, FA_GEN_FILTER, "Failed to remove IUnknown: %s", szName); return res; } STDMETHODIMP GetPropertyEnumerator( IRTAPropertyEnumerator **ppEnumerator ) { return m_pPropertyBag->GetPropertyEnumerator(ppEnumerator); } STDMETHODIMP GetPropertyBagEnumerator( IRTAPropertyEnumerator **ppEnumerator ) { return m_pPropertyBag->GetPropertyBagEnumerator(ppEnumerator); } protected: // Override this function to handle special properties that can only be // set at init time. Any properties that are consumed should be placed in pConsumedPropBag. // Any properties that are not consumed will be propagated via the usual OnSetXXX call. // Any invalid properties should be placed in pErrorBag. STDMETHOD(OnInitialize)( IRTAPropertyBag* pPropBag, IRTAPropertyBag* pConsumedPropBag, IRTAPropertyBag* pErrorBag ) {return PNR_OK;} // Override these functions to verify/take action on properties -- they will only be added to the property bag // if the overriding function returns SUCCESS. STDMETHOD(OnSetBool)( const char* szName, BOOL bValue) {return PNR_FAIL;} STDMETHOD(OnSetInt)( const char* szName, INT32 uValue) {return PNR_FAIL;} STDMETHOD(OnSetUint)( const char* szName, UINT32 uValue) {return PNR_FAIL;} STDMETHOD(OnSetInt64)( const char* szName, INT64 uValue) {return PNR_FAIL;} STDMETHOD(OnSetDouble)( const char* szName, double uValue) {return PNR_FAIL;} STDMETHOD(OnSetIntList)( const char* szName, IRTAIntList *pValue) {return PNR_FAIL;} STDMETHOD(OnSetUintList)( const char* szName, IRTAUintList *pValue) {return PNR_FAIL;} STDMETHOD(OnSetInt64List)( const char* szName, IRTAInt64List *pValue) {return PNR_FAIL;} STDMETHOD(OnSetDoubleList)( const char* szName, IRTADoubleList *pValue) {return PNR_FAIL;} STDMETHOD(OnSetIntRange)( const char* szName, IRTAIntRange *pValue) {return PNR_FAIL;} STDMETHOD(OnSetUintRange)( const char* szName, IRTAUintRange *pValue) {return PNR_FAIL;} STDMETHOD(OnSetInt64Range)( const char* szName, IRTAInt64Range *pValue) {return PNR_FAIL;} STDMETHOD(OnSetDoubleRange)( const char* szName, IRTADoubleRange *pValue) {return PNR_FAIL;} STDMETHOD(OnSetString)( const char* szName, const CHAR *cszValue ) {return PNR_FAIL;} STDMETHOD(OnSetUnknown)( const char* szName, IUnknown *pObject ) {return PNR_FAIL;} STDMETHOD(OnSetProperty)( IRTAProperty *pProperty ) {return PNR_FAIL;} STDMETHOD(OnSetPropertyBag)( const char* szName, IRTAPropertyBag *pValue) {return PNR_FAIL;} STDMETHOD(OnRemove)( const char* szName ) {return PNR_FAIL;} // Note: This is not ref-counted since caller should never hang on to it IRTAPropertyBag* GetActualPropertyBag() { return m_pPropertyBag;} void setAllowPropertyChanges(BOOL bAllowChanges) {m_bAllowChanges = bAllowChanges;} PN_RESULT init( IRMACommonClassFactory* pFactory ) { if (!pFactory) return PNR_POINTER; PN_RELEASE( m_pFactory ); m_pFactory = pFactory; m_pFactory->AddRef(); PN_RESULT res = PNR_OK; // Create internal property bag -- used to hold filter properties if (!m_pPropertyBag) res = m_pFactory->CreateInstance( IID_IRTAPropertyBag, (void **) &m_pPropertyBag ); return res; } IRTAPropertyBag *m_pPropertyBag; protected: inline BOOL isInitDone() {return m_bInitDone;} IRMACommonClassFactory *m_pFactory; private: BOOL m_bInitDone; BOOL m_bAllowChanges; }; #endif // _rtaconfigagenthelper_h