TuttleOFX  1
ofxsCore.h
Go to the documentation of this file.
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