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