TuttleOFX
1
|
00001 #ifndef _TUTTLE_HOST_CORE_COMPUTEOPTIONS_HPP_ 00002 #define _TUTTLE_HOST_CORE_COMPUTEOPTIONS_HPP_ 00003 00004 #include <tuttle/common/utils/global.hpp> 00005 00006 #include <ofxCore.h> 00007 00008 #include <tuttle/common/utils/Formatter.hpp> 00009 00010 #include <tuttle/common/atomic.hpp> 00011 #include <boost/shared_ptr.hpp> 00012 00013 #include <limits> 00014 #include <list> 00015 00016 namespace tuttle { 00017 namespace host { 00018 00019 class IProgressHandle 00020 { 00021 public: 00022 virtual ~IProgressHandle() = 0; 00023 00024 virtual void beginSequence() {} 00025 virtual void beginFrame() {} 00026 virtual void setupAtTime() {} 00027 virtual void processAtTime() {} 00028 virtual void endFrame() {} 00029 virtual void endSequence() {} 00030 }; 00031 00032 struct TimeRange 00033 { 00034 TimeRange() 00035 : _begin( std::numeric_limits<int>::min() ) 00036 , _end ( std::numeric_limits<int>::max() ) 00037 , _step ( 1 ) 00038 {} 00039 TimeRange( const int frame ) 00040 : _begin( frame ) 00041 , _end ( frame ) 00042 , _step ( 1 ) 00043 {} 00044 TimeRange( const int begin, const int end, const int step = 1 ) 00045 : _begin( begin ) 00046 , _end ( end ) 00047 , _step ( step ) 00048 {} 00049 TimeRange( const OfxRangeD& range, const int step = 1 ); 00050 00051 int _begin; 00052 int _end; 00053 int _step; 00054 }; 00055 00056 enum EVerboseLevel 00057 { 00058 eVerboseLevelTrace = boost::log::trivial::trace, 00059 eVerboseLevelDebug = boost::log::trivial::debug, 00060 eVerboseLevelInfo = boost::log::trivial::info, 00061 eVerboseLevelWarning = boost::log::trivial::warning, 00062 eVerboseLevelError = boost::log::trivial::error, 00063 eVerboseLevelFatal = boost::log::trivial::fatal 00064 }; 00065 00066 class ComputeOptions 00067 { 00068 public: 00069 typedef ComputeOptions This; 00070 00071 ComputeOptions() 00072 : _begin ( std::numeric_limits<int>::min() ) 00073 , _end ( std::numeric_limits<int>::max() ) 00074 , _abort ( false ) 00075 { 00076 init(); 00077 } 00078 00079 explicit 00080 ComputeOptions( const int frame ) 00081 : _begin ( std::numeric_limits<int>::min() ) 00082 , _end ( std::numeric_limits<int>::max() ) 00083 , _abort ( false ) 00084 { 00085 init(); 00086 _timeRanges.push_back( TimeRange( frame, frame ) ); 00087 } 00088 00089 ComputeOptions( const int begin, const int end, const int step = 1 ) 00090 : _begin ( std::numeric_limits<int>::min() ) 00091 , _end ( std::numeric_limits<int>::max() ) 00092 , _abort ( false ) 00093 { 00094 init(); 00095 _timeRanges.push_back( TimeRange( begin, end, step ) ); 00096 } 00097 00098 ComputeOptions( const ComputeOptions& options ) 00099 : _begin ( std::numeric_limits<int>::min() ) 00100 , _end ( std::numeric_limits<int>::max() ) 00101 , _abort ( false ) 00102 { 00103 *this = options; 00104 } 00105 00106 ComputeOptions& operator=( const ComputeOptions& other ) 00107 { 00108 _timeRanges = other._timeRanges; 00109 00110 _begin = other._begin; 00111 _end = other._end; 00112 _renderScale = other._renderScale; 00113 _continueOnError = other._continueOnError; 00114 _continueOnMissingFile = other._continueOnMissingFile; 00115 _forceIdentityNodesProcess = other._forceIdentityNodesProcess; 00116 _returnBuffers = other._returnBuffers; 00117 _isInteractive = other._isInteractive; 00118 00119 // don't modify the abort status? 00120 //_abort.store( false, boost::memory_order_relaxed ); 00121 00122 return *this; 00123 } 00124 00125 private: 00126 void init() 00127 { 00128 setRenderScale( 1.0, 1.0 ); 00129 setVerboseLevel( eVerboseLevelWarning ); 00130 setReturnBuffers ( true ); 00131 setContinueOnError ( false ); 00132 setContinueOnMissingFile ( false ); 00133 setColorEnable ( false ); 00134 setIsInteractive ( false ); 00135 setForceIdentityNodesProcess( false ); 00136 } 00137 00138 public: 00139 const std::list<TimeRange>& getTimeRanges() const { return _timeRanges; } 00140 00141 int getBegin( ) const { return _begin; } 00142 int getEnd ( ) const { return _end; } 00143 00144 This& setTimeRange( const int begin, const int end, const int step = 1 ) 00145 { 00146 _timeRanges.clear(); 00147 addTimeRange( begin, end, step ); 00148 return *this; 00149 } 00150 This& setTimeRange( const TimeRange& timeRange ) 00151 { 00152 _timeRanges.clear(); 00153 _timeRanges.push_back( timeRange ); 00154 return *this; 00155 } 00156 This& addTimeRange( const int begin, const int end, const int step = 1 ) 00157 { 00158 addTimeRange( TimeRange(begin, end, step) ); 00159 return *this; 00160 } 00161 This& addTimeRange( const TimeRange& timeRange ) 00162 { 00163 _timeRanges.push_back( timeRange ); 00164 return *this; 00165 } 00166 00167 This& setBegin( const int& beginTime ) 00168 { 00169 _begin = beginTime; 00170 return *this; 00171 } 00172 00173 This& setEnd( const int& endTime ) 00174 { 00175 _end = endTime; 00176 return *this; 00177 } 00178 00179 /** 00180 * @brief To get a preview of the result, you could set a renderscale. 00181 */ 00182 This& setRenderScale( const double x, const double y ) 00183 { 00184 _renderScale.x = x; 00185 _renderScale.y = y; 00186 return *this; 00187 } 00188 const OfxPointD& getRenderScale() const { return _renderScale; } 00189 00190 /** 00191 * @brief Continue as much as possible after an error. 00192 * If an image file inside an image sequence failed to be loaded, we continue to process other images of the sequence. 00193 */ 00194 This& setContinueOnError( const bool v = true ) 00195 { 00196 _continueOnError = v; 00197 return *this; 00198 } 00199 bool getContinueOnError() const { return _continueOnError; } 00200 00201 /** 00202 * @brief Continue as much as possible after an error. 00203 * If an image file inside an image sequence failed to be loaded, we continue to process other images of the sequence. 00204 */ 00205 This& setContinueOnMissingFile( const bool v = true ) 00206 { 00207 _continueOnMissingFile = v; 00208 return *this; 00209 } 00210 bool getContinueOnMissingFile() const { return _continueOnMissingFile; } 00211 00212 /** 00213 * @brief To get output buffer of all output nodes. 00214 */ 00215 This& setReturnBuffers( const bool v = true ) 00216 { 00217 _returnBuffers = v; 00218 return *this; 00219 } 00220 bool getReturnBuffers() const { return _returnBuffers; } 00221 00222 /** 00223 * @brief Set the verbose level of the process. 00224 */ 00225 This& setVerboseLevel( const EVerboseLevel level ) 00226 { 00227 tuttle::common::Formatter::get()->setLogLevel( static_cast<boost::log::trivial::severity_level>( level ) ); 00228 return *this; 00229 } 00230 00231 /** 00232 * @brief Set the output color enabled or not. 00233 */ 00234 This& setColorEnable( const bool enable = true ) 00235 { 00236 enable ? 00237 tuttle::common::Color::get()->enable() : 00238 tuttle::common::Color::get()->disable(); 00239 return *this; 00240 } 00241 00242 /** 00243 * @brief Inform plugins about the kind of process: batch or interactive. 00244 */ 00245 This& setIsInteractive( const bool v = true ) 00246 { 00247 _isInteractive = v; 00248 return *this; 00249 } 00250 bool getIsInteractive() const { return _isInteractive; } 00251 00252 /** 00253 * @brief For debug puposes only, you could force to call the process on all identity nodes. 00254 * This case should never happens to the plugin, so it may fail to do it. 00255 */ 00256 This& setForceIdentityNodesProcess( const bool v = true ) 00257 { 00258 _forceIdentityNodesProcess = v; 00259 return *this; 00260 } 00261 bool getForceIdentityNodesProcess() const { return _forceIdentityNodesProcess; } 00262 00263 /** 00264 * @brief The application would like to abort the process (from another thread). 00265 */ 00266 void abort() 00267 { 00268 _abort.store( true, boost::memory_order_relaxed ); 00269 } 00270 /** 00271 * @brief Has someone asked to abort the process? 00272 */ 00273 bool getAbort() const { return _abort.load( boost::memory_order_relaxed ); } 00274 00275 /** 00276 * @brief A handle to follow the progress (start, end...) of the compute 00277 */ 00278 void setProgressHandle( boost::shared_ptr<IProgressHandle> progressHandle) 00279 { 00280 _progressHandle = progressHandle; 00281 } 00282 bool isProgressHandleSet() const 00283 { 00284 return _progressHandle.get() != NULL; 00285 } 00286 void beginSequenceHandle() const 00287 { 00288 if( isProgressHandleSet() ) 00289 _progressHandle->beginSequence(); 00290 } 00291 void beginFrameHandle() const 00292 { 00293 if( isProgressHandleSet() ) 00294 _progressHandle->beginFrame(); 00295 } 00296 void setupAtTimeHandle() const 00297 { 00298 if( isProgressHandleSet() ) 00299 _progressHandle->setupAtTime(); 00300 } 00301 void processAtTimeHandle() const 00302 { 00303 if( isProgressHandleSet() ) 00304 _progressHandle->processAtTime(); 00305 } 00306 void endFrameHandle() const 00307 { 00308 if( isProgressHandleSet() ) 00309 _progressHandle->endFrame(); 00310 } 00311 void endSequenceHandle() const 00312 { 00313 if( isProgressHandleSet() ) 00314 _progressHandle->endSequence(); 00315 } 00316 00317 private: 00318 std::list<TimeRange> _timeRanges; 00319 00320 OfxPointD _renderScale; 00321 // different to range 00322 int _begin; 00323 int _end; 00324 00325 bool _continueOnError; 00326 bool _continueOnMissingFile; 00327 bool _forceIdentityNodesProcess; 00328 bool _returnBuffers; 00329 bool _isInteractive; 00330 00331 boost::atomic_bool _abort; 00332 00333 boost::shared_ptr<IProgressHandle> _progressHandle; 00334 }; 00335 00336 } 00337 } 00338 00339 #endif