TuttleOFX
1
|
00001 #ifndef _ofxsCore_H_ 00002 #define _ofxsCore_H_ 00003 /* 00004 * OFX Support Library, a library that skins the OFX plug-in API with C++ classes. 00005 * Copyright (C) 2004-2005 The Open Effects Association Ltd 00006 * Author Bruno Nicoletti bruno@thefoundry.co.uk 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions are met: 00010 * 00011 * Redistributions of source code must retain the above copyright notice, 00012 * this list of conditions and the following disclaimer. 00013 * Redistributions in binary form must reproduce the above copyright notice, 00014 * this list of conditions and the following disclaimer in the documentation 00015 * and/or other materials provided with the distribution. 00016 * Neither the name The Open Effects Association Ltd, nor the names of its 00017 * contributors may be used to endorse or promote products derived from this 00018 * software without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00021 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00023 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 00024 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00027 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 * The Open Effects Association Ltd 00032 * 1 Wardour St 00033 * London W1D 6PA 00034 * England 00035 * 00036 * 00037 * 00038 */ 00039 00040 /** @mainpage OFX Support Library 00041 * 00042 * @section mainpageIntro Introduction 00043 * 00044 * This support library skins the raw OFX C API with a set of C++ classes and functions that makes it easier to understand and write plug-ins to the API. Look at the examples to see how it is done. 00045 * 00046 * <HR> 00047 * 00048 * @section fifteenLineGuide Fifteen Line Plugin Writing Guide 00049 * 00050 * - work from the examples 00051 * - you need to write the following functions.... 00052 * - void OFX::Plugin::getPluginID(OFX::PluginID &id) 00053 * - gives the unique name and version numbers of the plug-in 00054 * - void OFX::Plugin::loadAction(void) 00055 * - called after the plug-in is first loaded, and before any instance has been made, 00056 * - void OFX::Plugin::unloadAction(void) 00057 * - called before the plug-in is unloaded, and all instances have been destroyed, 00058 * - void OFX::Plugin::describe(OFX::ImageEffectDescriptor &desc) 00059 * - called to describe the plugin to the host 00060 * - void OFX::Plugin::describeInContext(OFX::ImageEffectDescriptor &desc, OFX::EContext context) 00061 * - called to describe the plugin to the host for a context reported in OFX::Plugin::describe 00062 * - OFX::ImageEffect * OFX::Plugin::createInstance(OfxImageEffectHandle handle, OFX::EContext context) 00063 * - called when a new instance of a plug-in needs to be created. You need to derive a class from ImageEffect, new it and return it. 00064 * 00065 * The OFX::ImageEffect class has a set of members you can override to do various things, like rendering an effect. Again, look at the examples. 00066 * 00067 * <HR> 00068 * 00069 * @section license Copyright and License 00070 * 00071 * The library is copyright 2004-2005, The Open Effects Association Ltd, and was 00072 * written by Bruno Nicoletti (bruno@thefoundry.co.uk). 00073 * 00074 * It has been released under the GNU Lesser General Public License, see the 00075 * top of any source file for details. 00076 * 00077 */ 00078 00079 /** @file This file contains core code that wraps OFX 'objects' with C++ classes. 00080 * 00081 * This file only holds code that is visible to a plugin implementation, and so hides much 00082 * of the direct OFX objects and any library side only functions. 00083 */ 00084 00085 #ifdef _MSC_VER 00086 #pragma warning( disable : 4290 ) 00087 #endif 00088 00089 #include "ofxsMemory.h" 00090 00091 #include <ofxCore.h> 00092 #include <ofxImageEffect.h> 00093 #include <ofxInteract.h> 00094 #include <ofxKeySyms.h> 00095 #include <ofxMemory.h> 00096 #include <ofxMessage.h> 00097 #include <ofxMultiThread.h> 00098 #include <ofxParam.h> 00099 #include <ofxProperty.h> 00100 00101 #include <tuttle/common/utils/backtrace.hpp> 00102 #include <tuttle/common/exceptions.hpp> 00103 00104 #include <cmath> 00105 #include <cassert> 00106 #include <vector> 00107 #include <string> 00108 #include <map> 00109 #include <exception> 00110 #include <stdexcept> 00111 #include <sstream> 00112 #include <ostream> 00113 00114 #ifdef OFX_CLIENT_EXCEPTION_HEADER 00115 #include OFX_CLIENT_EXCEPTION_HEADER 00116 #endif 00117 00118 00119 inline bool operator==( const OfxRectI& a, const OfxRectI& b ) { return a.x1 == b.x1 && a.y1 == b.y1 && 00120 a.x2 == b.x2 && a.y2 == b.y2; } 00121 inline bool operator!=( const OfxRectI& a, const OfxRectI& b ) { return a.x1 != b.x1 || a.y1 != b.y1 || 00122 a.x2 != b.x2 || a.y2 != b.y2; } 00123 00124 inline bool operator==( const OfxRangeI& a, const OfxRangeI& b ) { return a.min == b.min && a.max == b.max; } 00125 inline bool operator!=( const OfxRangeI& a, const OfxRangeI& b ) { return a.min != b.min || a.max != b.max; } 00126 00127 inline bool operator==( const OfxRangeD& a, const OfxRangeD& b ) { return a.min == b.min && a.max == b.max; } 00128 inline bool operator!=( const OfxRangeD& a, const OfxRangeD& b ) { return a.min != b.min || a.max != b.max; } 00129 00130 inline bool operator==( const OfxPointI& a, const OfxPointI& b ) { return a.x == b.x && a.y == b.y; } 00131 inline bool operator!=( const OfxPointI& a, const OfxPointI& b ) { return a.x != b.x || a.y != b.y; } 00132 00133 inline OfxPointD& operator+=( OfxPointD& p1, const OfxPointD& p2 ) { p1.x+=p2.x; p1.y+=p2.y; return p1; } 00134 inline OfxPointD& operator+=( OfxPointD& p, const double v ) { p.x+=v; p.y+=v; return p; } 00135 inline OfxPointD& operator-=( OfxPointD& p1, const OfxPointD& p2 ) { p1.x-=p2.x; p1.y-=p2.y; return p1; } 00136 inline OfxPointD& operator-=( OfxPointD& p, const double v ) { p.x-=v; p.y-=v; return p; } 00137 inline OfxPointD& operator/=( OfxPointD& p1, const OfxPointD& p2 ) { p1.x/=p2.x; p1.y/=p2.y; return p1; } 00138 inline OfxPointD& operator/=( OfxPointD& p, const double v ) { p.x/=v; p.y/=v; return p; } 00139 inline OfxPointD& operator*=( OfxPointD& p1, const OfxPointD& p2 ) { p1.x*=p2.x; p1.y*=p2.y; return p1; } 00140 inline OfxPointD& operator*=( OfxPointD& p, const double v ) { p.x *= v; p.y *= v; return p; } 00141 00142 inline bool operator==( const OfxPointD& p1, const OfxPointD& p2 ) { return (p1.x==p2.x && p1.y==p2.y); } 00143 inline bool operator!=( const OfxPointD& p1, const OfxPointD& p2 ) { return p1.x!=p2.x || p1.y!=p2.y; } 00144 inline OfxPointD operator+( const OfxPointD& p1, const OfxPointD& p2 ) { OfxPointD r = {p1.x+p2.x,p1.y+p2.y}; return r; } 00145 inline OfxPointD operator+( const OfxPointD& p, const double t ) { OfxPointD r = { p.x + t, p.y + t }; return r; } 00146 inline OfxPointD operator-( const OfxPointD& p ) { OfxPointD r = {-p.x,-p.y}; return r; } 00147 inline OfxPointD operator-( const OfxPointD& p1, const OfxPointD& p2 ) { OfxPointD r = {p1.x-p2.x,p1.y-p2.y}; return r; } 00148 inline OfxPointD operator-( const OfxPointD& p, const double t ) { OfxPointD r = { p.x - t, p.y - t }; return r; } 00149 inline OfxPointD operator*( const double t, const OfxPointD& p ) { OfxPointD r = { p.x * t, p.y * t }; return r; } 00150 inline OfxPointD operator*( const OfxPointD& p, const double t ) { OfxPointD r = { p.x * t, p.y * t }; return r; } 00151 inline OfxPointD operator*( const OfxPointD& a, const OfxPointD& b ) { OfxPointD r = { a.x * b.x, a.y * b.y }; return r; } 00152 inline OfxPointD operator/( const OfxPointD& a, const OfxPointD& b ) { OfxPointD r = { a.x / b.x, a.y / b.y }; return r; } 00153 inline OfxPointD operator/( const OfxPointD& p, const double t ) 00154 { 00155 OfxPointD r; 00156 if( t==0 ) 00157 { 00158 r.x=0; 00159 r.y=0; 00160 } 00161 else 00162 { 00163 r.x=p.x/t; 00164 r.y=p.y/t; 00165 } 00166 return r; 00167 } 00168 inline OfxPointD operator/( const double t, const OfxPointD& p ) 00169 { 00170 OfxPointD res = { 0.0, 0.0 }; 00171 if( p.x != 0 ) 00172 res.x = t / p.x; 00173 if( p.y != 0 ) 00174 res.y = t / p.y; 00175 return res; 00176 } 00177 00178 inline OfxRectI rectDoubleToInt( const OfxRectD& r ) 00179 { 00180 OfxRectI rect; 00181 rect.x1 = static_cast<int>(r.x1); 00182 rect.y1 = static_cast<int>(r.y1); 00183 rect.x2 = static_cast<int>(std::ceil(r.x2)); 00184 rect.y2 = static_cast<int>(std::ceil(r.y2)); 00185 return rect; 00186 } 00187 00188 inline OfxRectD rectIntToDouble( const OfxRectI& r ) 00189 { 00190 OfxRectD rect; 00191 rect.x1 = r.x1; 00192 rect.y1 = r.y1; 00193 rect.x2 = r.x2; 00194 rect.y2 = r.y2; 00195 return rect; 00196 } 00197 00198 /** @brief Nasty macro used to define empty protected copy ctors and assign ops */ 00199 #define mDeclareProtectedAssignAndCC( CLASS ) \ 00200 CLASS& operator=( const CLASS& v1 ) { assert( false ); return *this; } \ 00201 CLASS( const CLASS &v ) { assert( false ); } 00202 00203 /** @brief The core 'OFX Support' namespace, used by plugin implementations. All code for these are defined in the common support libraries. 00204 */ 00205 namespace OFX { 00206 /** forward class declarations */ 00207 class PropertySet; 00208 00209 /** @brief Enumerates the different types a property can be */ 00210 enum PropertyTypeEnum 00211 { 00212 ePointer, 00213 eInt, 00214 eString, 00215 eDouble 00216 }; 00217 00218 /** @brief Enumerates the reasons a plug-in instance may have had one of its values changed */ 00219 enum InstanceChangeReason 00220 { 00221 eChangeUserEdit, /**< @brief A user actively edited something in the plugin, eg: changed the value of an integer param on an interface */ 00222 eChangePluginEdit, /**< @brief The plugin's own code changed something in the instance, eg: a callback on on param setting the value of another */ 00223 eChangeTime /**< @brief The current value of a parameter has changed because the param animates and the current time has changed */ 00224 }; 00225 00226 /** @brief maps a status to a string for debugging purposes, note a c-str for printf */ 00227 std::string mapStatusToString( const OfxStatus stat ); 00228 00229 /** @brief namespace for OFX support lib exceptions, all derive from std::exception, calling it */ 00230 namespace Exception { 00231 00232 /** @brief thrown when a suite returns a failure status code 00233 */ 00234 class Suite : public std::runtime_error 00235 , virtual public ::boost::exception 00236 , virtual public ::boost::backtrace 00237 { 00238 protected: 00239 OfxStatus _status; 00240 00241 public: 00242 explicit Suite( OfxStatus s ) 00243 : std::runtime_error( mapStatusToString( _status ) ) 00244 , _status( s ) {} 00245 explicit Suite( OfxStatus s, const std::string& what ) 00246 : std::runtime_error( mapStatusToString( _status ) + " : " + what ) 00247 , _status( s ) {} 00248 OfxStatus status( void ) { return _status; } 00249 operator OfxStatus() { return _status; } 00250 }; 00251 00252 /** @brief Exception indicating that a host doesn't know about a property that is should do */ 00253 class PropertyUnknownToHost : public std::runtime_error 00254 { 00255 public: 00256 explicit PropertyUnknownToHost( const std::string& what ) : std::runtime_error( what ) {} 00257 }; 00258 00259 /** @brief exception indicating that the host thinks a property has an illegal value */ 00260 class PropertyValueIllegalToHost : public std::invalid_argument 00261 { 00262 public: 00263 explicit PropertyValueIllegalToHost( const std::string& what ) : std::invalid_argument( what ) {} 00264 }; 00265 00266 /** @brief exception indicating a request for a named thing exists (eg: a param), but is of the wrong type, should never make it back to the main entry 00267 * indicates a logical error in the code. Asserts are raised in debug code in these situations. 00268 */ 00269 class TypeRequest : public std::logic_error 00270 { 00271 public: 00272 explicit TypeRequest( const std::string& what ) : std::logic_error( what ) {} 00273 }; 00274 00275 //////////////////////////////////////////////////////////////////////////////// 00276 // These exceptions are to be thrown by the plugin if it hits a problem, the 00277 // code managing the main entry will trap the exception and return a suitable 00278 // status code to the host. 00279 00280 /** @brief exception indicating a required host feature is missing */ 00281 class HostInadequate : public std::runtime_error 00282 { 00283 public: 00284 explicit HostInadequate( const std::string& what ) : std::runtime_error( what ) {} 00285 }; 00286 00287 }; // end of Exception namespace 00288 00289 /** @brief Throws an @ref OFX::Exception::Suite depending on the status flag passed in */ 00290 void throwSuiteStatusException( OfxStatus stat ); 00291 00292 void throwHostMissingSuiteException( const std::string& name ); 00293 00294 /** @brief This struct is used to return an identifier for the plugin by the function @ref OFX:Plugin::getPlugin. 00295 * The members correspond to those in the OfxPlugin struct defined in ofxCore.h. 00296 */ 00297 00298 class ImageEffectDescriptor; 00299 class ImageEffect; 00300 00301 /** @brief This class wraps up an OFX property set */ 00302 class PropertySet 00303 { 00304 protected: 00305 /** @brief The raw property handle */ 00306 OfxPropertySetHandle _propHandle; 00307 00308 /** @brief Class static, whether we are logging each property action */ 00309 static int _gPropLogging; 00310 00311 /** @brief Do not throw an exception if a host returns 'unsupported' when setting a property */ 00312 static bool _gThrowOnUnsupported; 00313 00314 public: 00315 /** @brief turns on logging of property access functions */ 00316 static void propEnableLogging( void ) { ++_gPropLogging; } 00317 00318 /** @brief turns off logging of property access functions */ 00319 static void propDisableLogging( void ) { --_gPropLogging; } 00320 00321 /** @brief Do we throw an exception if a host returns 'unsupported' when setting a property. Default is true */ 00322 static void setThrowOnUnsupportedProperties( bool v ) { _gThrowOnUnsupported = v; } 00323 00324 /** @brief Do we throw an exception if a host returns 'unsupported' when setting a property. Default is true */ 00325 static bool getThrowOnUnsupportedProperties( void ) { return _gThrowOnUnsupported; } 00326 00327 /** @brief construct a property set */ 00328 PropertySet( OfxPropertySetHandle h = 0 ) : _propHandle( h ) {} 00329 virtual ~PropertySet(); 00330 00331 /** @brief set the handle to use for this set */ 00332 void propSetHandle( OfxPropertySetHandle h ) { _propHandle = h; } 00333 00334 /** @brief return the handle for this property set */ 00335 OfxPropertySetHandle propSetHandle( void ) { return _propHandle; } 00336 00337 inline int propGetDimension( const std::string& property, bool throwOnFailure = true ) const 00338 { 00339 return propGetDimension( property.c_str(), throwOnFailure ); 00340 } 00341 00342 int propGetDimension( const char* property, bool throwOnFailure = true ) const; 00343 void propReset( const char* property ); 00344 00345 // set single values 00346 // @tuttle todo: replace int with std::size_t for idx 00347 void propSetPointer( const char* property, void* value, int idx, bool throwOnFailure = true ); 00348 void propSetString( const char* property, const std::string& value, int idx, bool throwOnFailure = true ); 00349 void propSetDouble( const char* property, double value, int idx, bool throwOnFailure = true ); 00350 void propSetInt( const char* property, int value, int idx, bool throwOnFailure = true ); 00351 00352 void propSetPointer( const char* property, void* value, bool throwOnFailure = true ) 00353 { propSetPointer( property, value, 0, throwOnFailure ); } 00354 00355 void propSetString( const char* property, const std::string& value, bool throwOnFailure = true ) 00356 { propSetString( property, value, 0, throwOnFailure ); } 00357 00358 void propSetDouble( const char* property, double value, bool throwOnFailure = true ) 00359 { propSetDouble( property, value, 0, throwOnFailure ); } 00360 00361 void propSetInt( const char* property, int value, bool throwOnFailure = true ) 00362 { propSetInt( property, value, 0, throwOnFailure ); } 00363 00364 /// get a pointer property 00365 void* propGetPointer( const char* property, int idx, bool throwOnFailure = true ) const; 00366 00367 /// get a string property 00368 std::string propGetString( const char* property, int idx, bool throwOnFailure = true ) const; 00369 /// get a double property 00370 double propGetDouble( const char* property, int idx, bool throwOnFailure = true ) const; 00371 00372 /// get an int property 00373 int propGetInt( const char* property, int idx, bool throwOnFailure = true ) const; 00374 00375 /// get a string property with index 0 00376 void* propGetPointer( const std::string& property, bool throwOnFailure = true ) const 00377 { 00378 return propGetPointer( property.c_str(), throwOnFailure ); 00379 } 00380 00381 void* propGetPointer( const char* property, bool throwOnFailure = true ) const 00382 { 00383 return propGetPointer( property, 0, throwOnFailure ); 00384 } 00385 00386 /// get a string property with index 0 00387 inline std::string propGetString( const std::string& property, bool throwOnFailure = true ) const 00388 { 00389 return propGetString( property.c_str(), throwOnFailure ); 00390 } 00391 00392 std::string propGetString( const char* property, bool throwOnFailure = true ) const 00393 { 00394 return propGetString( property, 0, throwOnFailure ); 00395 } 00396 00397 /// get a double property with index 0 00398 inline double propGetDouble( const std::string& property, bool throwOnFailure = true ) const 00399 { 00400 return propGetDouble( property.c_str(), throwOnFailure ); 00401 } 00402 00403 double propGetDouble( const char* property, bool throwOnFailure = true ) const 00404 { 00405 return propGetDouble( property, 0, throwOnFailure ); 00406 } 00407 00408 /// get an int property with index 0 00409 inline int propGetInt( const std::string& property, bool throwOnFailure = true ) const 00410 { 00411 return propGetInt( property.c_str(), throwOnFailure ); 00412 } 00413 00414 int propGetInt( const char* property, bool throwOnFailure = true ) const 00415 { 00416 return propGetInt( property, 0, throwOnFailure ); 00417 } 00418 00419 }; 00420 00421 }; 00422 00423 // undeclare the protected assign and CC macro 00424 #undef mDeclareProtectedAssignAndCC 00425 00426 #endif