TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/ofx/property/OfxhSet.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License :
00003  *
00004  * Copyright (c) 2007-2009, The Open Effects Association Ltd. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * Redistributions of source code must retain the above copyright notice,
00010  * this list of conditions and the following disclaimer.
00011  * Redistributions in binary form must reproduce the above copyright notice,
00012  * this list of conditions and the following disclaimer in the documentation
00013  * and/or other materials provided with the distribution.
00014  * Neither the name The Open Effects Association Ltd, nor the names of its
00015  * contributors may be used to endorse or promote products derived from this
00016  * software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00022  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00024  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00025  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 #include "OfxhSet.hpp"
00030 #include "OfxhPropertyTemplate.hpp"
00031 #include "OfxhGetHook.hpp"
00032 #include "OfxhNotifyHook.hpp"
00033 
00034 #include <tuttle/host/ofx/OfxhCore.hpp>
00035 
00036 #include <ofxCore.h>
00037 #include <ofxImageEffect.h>
00038 
00039 #include <iostream>
00040 #include <cstring>
00041 
00042 //#define DEBUG_PROPERTIES true
00043 
00044 namespace tuttle {
00045 namespace host {
00046 namespace ofx {
00047 namespace property {
00048 
00049 
00050 OfxhProperty& OfxhSet::localAt( const int index )
00051 {
00052         if( index >= getLocalSize() )
00053         {
00054                 if( index >= getSize() )
00055                 {
00056                         BOOST_THROW_EXCEPTION( OfxhException( kOfxStatErrValue)
00057                                 << exception::dev() + "OfxhSet::at: " + index + ", property not found." );
00058                 }
00059                 else
00060                 {
00061                         BOOST_THROW_EXCEPTION( OfxhException( kOfxStatErrValue)
00062                                 << exception::dev() + "OfxhSet::at: " + index + " is a non-local property." );
00063                 }
00064         }
00065         
00066         PropertyMap::iterator it = _props.begin();
00067         std::advance(it, index);
00068         return * it->second;
00069 }
00070 
00071 const OfxhProperty& OfxhSet::at( const int index ) const
00072 {
00073         if( index < getLocalSize() )
00074         {
00075                 PropertyMap::const_iterator it = _props.begin();
00076                 std::advance(it, index);
00077                 return * it->second;
00078         }
00079         if( _chainedSet == NULL )
00080         {
00081                 BOOST_THROW_EXCEPTION( OfxhException( kOfxStatErrValue)
00082                         << exception::dev() + "OfxhSet::at: " + index + ", property not found." );
00083         }
00084         return _chainedSet->at(index - getLocalSize());
00085 }
00086 
00087 void OfxhSet::setGetHook( const std::string& s, OfxhGetHook* ghook )
00088 {
00089         fetchLocalProperty( s ).setGetHook( ghook );
00090 }
00091 
00092 /**
00093  * add a notify hook for a particular property.  users may need to call particular
00094  * specialised versions of this.
00095  */
00096 void OfxhSet::addNotifyHook( const std::string& s, OfxhNotifyHook* hook )
00097 {
00098         fetchLocalProperty( s ).addNotifyHook( hook );
00099 }
00100 
00101 OfxhProperty& OfxhSet::fetchLocalProperty( const std::string& name )
00102 {
00103         PropertyMap::iterator i = _props.find( name );
00104 
00105         if( i == _props.end() )
00106         {
00107                 BOOST_THROW_EXCEPTION( OfxhException( kOfxStatErrValue, "fetchLocalProperty: " + name + ". Property not found." ) ); //+ " on type:" + getStringProperty(kOfxPropType) + " name:" + getStringProperty(kOfxPropName) );// " NULL, (followChain: " << followChain << ").";
00108         }
00109         return *( i->second );
00110 }
00111 
00112 const OfxhProperty& OfxhSet::fetchProperty( const std::string& name ) const
00113 {
00114         PropertyMap::const_iterator i = _props.find( name );
00115 
00116         if( i == _props.end() )
00117         {
00118                 if( _chainedSet )
00119                 {
00120                         return _chainedSet->fetchProperty( name );
00121                 }
00122                 BOOST_THROW_EXCEPTION( OfxhException( kOfxStatErrValue )
00123                         << exception::dev() + "fetchProperty: " + name + " property not found." );
00124         }
00125         return *( i->second );
00126 }
00127 
00128 /**
00129  * add one new property
00130  */
00131 void OfxhSet::createProperty( const OfxhPropSpec& spec )
00132 {
00133         if( _props.find( spec.name ) != _props.end() )
00134         {
00135                 BOOST_THROW_EXCEPTION( OfxhException( kOfxStatErrExists )
00136                         << exception::dev() + "Tried to add a duplicate property to a Property::Set (" + spec.name + ")" );
00137         }
00138         std::string key( spec.name ); // for constness
00139         switch( spec.type )
00140         {
00141                 case ePropTypeInt:
00142                         _props.insert( key, new Int( spec.name, spec.dimension, spec.readonly, spec.defaultValue ? std::atoi( spec.defaultValue ) : 0 ) );
00143                         break;
00144                 case ePropTypeDouble:
00145                         _props.insert( key, new Double( spec.name, spec.dimension, spec.readonly, spec.defaultValue ? std::atof( spec.defaultValue ) : 0 ) );
00146                         break;
00147                 case ePropTypeString:
00148                         _props.insert( key, new String( spec.name, spec.dimension, spec.readonly, spec.defaultValue ? spec.defaultValue : "" ) );
00149                         break;
00150                 case ePropTypePointer:
00151                         _props.insert( key, new Pointer( spec.name, spec.dimension, spec.readonly, (void*) spec.defaultValue ) );
00152                         break;
00153                 case ePropTypeNone:
00154                         BOOST_THROW_EXCEPTION( OfxhException( kOfxStatErrUnsupported )
00155                                 << exception::dev() + "Tried to create a property of an unrecognized type (" + spec.name + ", " + mapTypeEnumToString( spec.type ) + ")" );
00156         }
00157 }
00158 
00159 void OfxhSet::addProperties( const OfxhPropSpec spec[] )
00160 {
00161         while( spec->name )
00162         {
00163                 createProperty( *spec );
00164                 ++spec;
00165         }
00166 }
00167 
00168 void OfxhSet::eraseProperty( const std::string& propName )
00169 {
00170         _props.erase( propName );
00171 }
00172 
00173 bool OfxhSet::hasProperty( const std::string& propName, bool followChain ) const
00174 {
00175         PropertyMap::const_iterator it = _props.find( propName );
00176 
00177         if( it == _props.end() )
00178         {
00179                 if( followChain && _chainedSet )
00180                 {
00181                         return _chainedSet->hasProperty( propName, true );
00182                 }
00183         }
00184         return it != _props.end();
00185 }
00186 
00187 bool OfxhSet::hasLocalProperty( const std::string& propName ) const
00188 {
00189         return hasProperty( propName, false );
00190 }
00191 
00192 /**
00193  * add one new property
00194  */
00195 void OfxhSet::addProperty( OfxhProperty* prop )
00196 {
00197         std::string key( prop->getName() ); // for constness
00198 
00199         _props.insert( key, prop );
00200 }
00201 
00202 /**
00203  * empty ctor
00204  */
00205 OfxhSet::OfxhSet()
00206         : _magic( kMagic )
00207         , _chainedSet( NULL )
00208 {}
00209 
00210 OfxhSet::OfxhSet( const OfxhPropSpec spec[] )
00211         : _magic( kMagic )
00212         , _chainedSet( NULL )
00213 {
00214         addProperties( spec );
00215 }
00216 
00217 OfxhSet::OfxhSet( const OfxhSet& other )
00218         : _magic( kMagic )
00219 {
00220         operator=( other );
00221 }
00222 
00223 OfxhSet::~OfxhSet()
00224 {
00225         clear();
00226 }
00227 
00228 void OfxhSet::clear()
00229 {
00230         _props.clear();
00231 }
00232 
00233 OfxhSet& OfxhSet::operator=( const This& other )
00234 {
00235         _props      = other._props.clone();
00236         _chainedSet = other._chainedSet;
00237         return *this;
00238 }
00239 
00240 bool OfxhSet::operator==( const This& other ) const
00241 {
00242         if( _props != other._props )
00243                 return false;
00244         if( _chainedSet == NULL )
00245         {
00246                 if( other._chainedSet != NULL )
00247                         if( other._chainedSet->getSize() != 0 )
00248                                 return false;
00249         }
00250         else
00251         {
00252                 if( other._chainedSet == NULL )
00253                         if( _chainedSet->getSize() != 0 )
00254                                 return false;
00255                 if( *_chainedSet != *( other._chainedSet ) )
00256                         return false;
00257         }
00258         return true;
00259 }
00260 
00261 void OfxhSet::copyValues( const This& other )
00262 {
00263         if( _props.size() != other._props.size() )
00264         {
00265                 BOOST_THROW_EXCEPTION( exception::Bug()
00266                     << exception::dev( "You try to copy properties values, but the two lists are not identical." ) );
00267         }
00268 
00269         PropertyMap::const_iterator oit = other._props.begin(), oitEnd = other._props.end();
00270         for( PropertyMap::iterator it = _props.begin(), itEnd = _props.end();
00271              it != itEnd && oit != oitEnd;
00272              ++it, ++oit )
00273         {
00274                 OfxhProperty& p        = *( it->second );
00275                 const OfxhProperty& op = *( oit->second );
00276                 if( p.getName() != op.getName() )
00277                 {
00278                         BOOST_THROW_EXCEPTION( exception::Bug()
00279                             << exception::dev( "You try to copy properties values, but it is not the same property in the two lists." ) );
00280                 }
00281                 p.copyValues( op );
00282         }
00283 }
00284 
00285 /// get a particular int property
00286 int OfxhSet::getIntPropertyRaw( const std::string& property, int index ) const
00287 {
00288         return getPropertyRaw<OfxhIntValue>( property, index );
00289 }
00290 
00291 /// get a particular double property
00292 
00293 double OfxhSet::getDoublePropertyRaw( const std::string& property, int index ) const
00294 {
00295         return getPropertyRaw<OfxhDoubleValue>( property, index );
00296 }
00297 
00298 /// get a particular double property
00299 
00300 void* OfxhSet::getPointerPropertyRaw( const std::string& property, int index ) const
00301 {
00302         return getPropertyRaw<OfxhPointerValue>( property, index );
00303 }
00304 
00305 /// get a particular double property
00306 
00307 const std::string& OfxhSet::getStringPropertyRaw( const std::string& property, int index ) const
00308 {
00309         return fetchTypedProperty<String>( property ).getValueRaw( index );
00310         //return OfxhStringValue::kEmpty;
00311 }
00312 
00313 /// get a particular int property
00314 
00315 int OfxhSet::getIntProperty( const std::string& property, int index ) const
00316 {
00317         return getProperty<OfxhIntValue >( property, index );
00318 }
00319 
00320 /// get the value of a particular double property
00321 
00322 void OfxhSet::getIntPropertyN( const std::string& property, int* v, int N ) const
00323 {
00324         return getPropertyN<OfxhIntValue >( property, N, v );
00325 }
00326 
00327 /// get a particular double property
00328 
00329 double OfxhSet::getDoubleProperty( const std::string& property, int index ) const
00330 {
00331         return getProperty<OfxhDoubleValue >( property, index );
00332 }
00333 
00334 /// get the value of a particular double property
00335 
00336 void OfxhSet::getDoublePropertyN( const std::string& property, double* v, int N ) const
00337 {
00338         return getPropertyN<OfxhDoubleValue >( property, N, v );
00339 }
00340 
00341 /// get a particular double property
00342 
00343 void* OfxhSet::getPointerProperty( const std::string& property, int index ) const
00344 {
00345         return getProperty<OfxhPointerValue >( property, index );
00346 }
00347 
00348 /// get a particular double property
00349 
00350 const std::string& OfxhSet::getStringProperty( const std::string& property, int index ) const
00351 {
00352         return getProperty<OfxhStringValue >( property, index );
00353 }
00354 
00355 /// is the given string one of the values of a multi-dimensional string prop
00356 /// this returns a non negative index if it is found, otherwise, -1
00357 
00358 int OfxhSet::findStringPropValueIndex( const std::string& propName,
00359                                        const std::string& propValue ) const
00360 {
00361         const String& prop = fetchStringProperty( propName );
00362 
00363         const std::vector<std::string>& values     = prop.getValues();
00364         std::vector<std::string>::const_iterator i = find( values.begin(), values.end(), propValue );
00365         if( i != values.end() )
00366         {
00367                 return int(i - values.begin() );
00368         }
00369         return -1;
00370 }
00371 
00372 std::ostream& operator<<( std::ostream& os, const OfxhSet& v )
00373 {
00374         os << "property::Set {" << std::endl;
00375         for( PropertyMap::const_iterator it = v._props.begin(), itEnd = v._props.end();
00376              it != itEnd;
00377              ++it )
00378         {
00379                 const OfxhProperty& prop = *( it->second );
00380                 os << "    " << it->first << " ";
00381                 os << "(type:" << mapTypeEnumToString( prop.getType() )
00382                    << " dim:" << prop.getDimension() << " ro:" << prop.getPluginReadOnly()
00383                    << " modifiedBy:" << ( prop.getModifiedBy() == eModifiedByHost ? "host" : "plugin" )
00384                    << ") : [";
00385                 int i = 0;
00386                 for( ; i < (int)( prop.getDimension() ) - 1; ++i )
00387                 {
00388                         os << prop.getStringValueAt( i ) << ", ";
00389                 }
00390                 if( prop.getDimension() > 0 )
00391                         os << prop.getStringValueAt( i );
00392                 os << "] " << std::endl;
00393         }
00394         os << "}" << std::endl;
00395         return os;
00396 }
00397 
00398 }
00399 }
00400 }
00401 }