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