TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/ofx/OfxhImageEffectPlugin.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License :
00003  *
00004  * Copyright (c) 2007-2009, The Open Effects Association Ltd. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * Redistributions of source code must retain the above copyright notice,
00010  *    this list of conditions and the following disclaimer.
00011  * Redistributions in binary form must reproduce the above copyright notice,
00012  *    this list of conditions and the following disclaimer in the documentation
00013  *    and/or other materials provided with the distribution.
00014  * Neither the name The Open Effects Association Ltd, nor the names of its
00015  *    contributors may be used to endorse or promote products derived from this
00016  *    software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00022  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00024  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00025  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 
00031 // ofx host
00032 #include "OfxhBinary.hpp"
00033 #include "OfxhMemory.hpp"
00034 #include "OfxhImageEffectNode.hpp"
00035 #include "OfxhPluginCache.hpp"
00036 #include "OfxhHost.hpp"
00037 #include "OfxhImageEffectPlugin.hpp"
00038 #include "OfxhPluginAPICache.hpp"
00039 #include "OfxhImageEffectPluginCache.hpp"
00040 #include "property/OfxhSet.hpp"
00041 #include "attribute/OfxhClip.hpp"
00042 #include "attribute/OfxhParam.hpp"
00043 
00044 ///@todo tuttle: remove this !
00045 #include <tuttle/host/Core.hpp>
00046 #include <tuttle/host/serialization.hpp>
00047 
00048 // ofx
00049 #include <ofxImageEffect.h>
00050 
00051 #include <string>
00052 #include <map>
00053 
00054 // Disable the "this pointer used in base member initialiser list" warning in Windows
00055 namespace tuttle {
00056 namespace host {
00057 namespace ofx {
00058 namespace imageEffect {
00059 
00060 #if defined( WINDOWS ) && !defined( __GNUC__ )
00061 #pragma warning( disable : 4355 )
00062 #endif
00063 
00064 OfxhImageEffectPlugin::OfxhImageEffectPlugin()
00065         : OfxhPlugin()
00066         , _imageEffectPluginCache( NULL )
00067         , _pluginLoadGuard( NULL )
00068         , _baseDescriptor( NULL )
00069 {
00070         /// @todo tuttle
00071 }
00072 
00073 OfxhImageEffectPlugin::OfxhImageEffectPlugin( OfxhImageEffectPluginCache& imageEffectPluginCache, OfxhPluginBinary& pluginBinary, int pluginIndex, OfxPlugin& plugin )
00074         : OfxhPlugin( pluginBinary, pluginIndex, plugin )
00075         , _imageEffectPluginCache( &imageEffectPluginCache )
00076         , _pluginLoadGuard( NULL )
00077         , _baseDescriptor( core().getHost().makeDescriptor( *this ) )
00078 {
00079         //      loadAndDescribeActions();
00080 }
00081 
00082 OfxhImageEffectPlugin::OfxhImageEffectPlugin( OfxhImageEffectPluginCache& imageEffectPluginCache,
00083                                               OfxhPluginBinary&           pluginBinary,
00084                                               int                         pluginIndex,
00085                                               const std::string&          api,
00086                                               int                         apiVersion,
00087                                               const std::string&          pluginId,
00088                                               const std::string&          rawId,
00089                                               int                         pluginMajorVersion,
00090                                               int                         pluginMinorVersion )
00091         : OfxhPlugin( pluginBinary, pluginIndex, api, apiVersion, pluginId, rawId, pluginMajorVersion, pluginMinorVersion )
00092         , _imageEffectPluginCache( &imageEffectPluginCache )
00093         , _pluginLoadGuard( NULL )
00094         , _baseDescriptor( core().getHost().makeDescriptor( *this ) )
00095 {
00096         //      loadAndDescribeActions();
00097 }
00098 
00099 #if defined( WINDOWS ) && !defined( __GNUC__ )
00100 #pragma warning( default : 4355 )
00101 #endif
00102 
00103 OfxhImageEffectPlugin::~OfxhImageEffectPlugin()
00104 {
00105         if( _pluginLoadGuard )
00106         {
00107                 _pluginLoadGuard->getOfxPlugin()->mainEntry( kOfxActionUnload, 0, 0, 0 );
00108         }
00109 }
00110 
00111 bool OfxhImageEffectPlugin::operator==( const OfxhImageEffectPlugin& other ) const
00112 {
00113         if( OfxhPlugin::operator!=( other ) ||
00114             *_baseDescriptor != *( other._baseDescriptor ) )
00115                 return false;
00116         return true;
00117 }
00118 
00119 void OfxhImageEffectPlugin::setApiHandler( APICache::OfxhPluginAPICacheI& api )
00120 {
00121         _imageEffectPluginCache = &dynamic_cast<OfxhImageEffectPluginCache&>( api );
00122 }
00123 
00124 APICache::OfxhPluginAPICacheI& OfxhImageEffectPlugin::getApiHandler()
00125 {
00126         return *_imageEffectPluginCache;
00127 }
00128 
00129 const APICache::OfxhPluginAPICacheI& OfxhImageEffectPlugin::getApiHandler() const
00130 {
00131         return *_imageEffectPluginCache;
00132 }
00133 
00134 /// get the image effect descriptor
00135 OfxhImageEffectNodeDescriptor& OfxhImageEffectPlugin::getDescriptor()
00136 {
00137         return *_baseDescriptor;
00138 }
00139 
00140 /// get the image effect descriptor const version
00141 const OfxhImageEffectNodeDescriptor& OfxhImageEffectPlugin::getDescriptor() const
00142 {
00143         return *_baseDescriptor;
00144 }
00145 
00146 void OfxhImageEffectPlugin::addContext( const std::string& context, OfxhImageEffectNodeDescriptor* ied )
00147 {
00148         std::string key( context ); // for constness
00149         
00150         _contexts.insert( key, ied );
00151         _knownContexts.insert( context );
00152 }
00153 
00154 void OfxhImageEffectPlugin::addContext( const std::string& context )
00155 {
00156         _knownContexts.insert( context );
00157         //TUTTLE_TLOG( TUTTLE_TRACE, "OfxhImageEffectPlugin::addContext " << context << " on plugin " << this->getRawIdentifier() );
00158 }
00159 
00160 const std::set<std::string>& OfxhImageEffectPlugin::getContexts() const
00161 {
00162         return _knownContexts;
00163 }
00164 
00165 bool OfxhImageEffectPlugin::supportsContext( const std::string& context ) const
00166 {
00167         /*
00168         TUTTLE_LOG( TUTTLE_TRACE, context << " supportsContext? " << _knownContexts.size() );
00169         BOOST_FOREACH( const std::string& c, _knownContexts )
00170         {
00171                 TUTTLE_LOG( TUTTLE_TRACE, "context " << c );
00172         }
00173         */
00174         return _knownContexts.find( context ) != _knownContexts.end();
00175 }
00176 
00177 void OfxhImageEffectPlugin::initContexts()
00178 {
00179         const tuttle::host::ofx::property::OfxhSet& eProps = getDescriptor().getProperties();
00180         int size                                           = eProps.getDimension( kOfxImageEffectPropSupportedContexts );
00181 
00182         for( int j = 0; j < size; ++j )
00183         {
00184                 std::string context = eProps.getStringProperty( kOfxImageEffectPropSupportedContexts, j );
00185                 addContext( context );
00186         }
00187 }
00188 
00189 void OfxhImageEffectPlugin::loadAndDescribeActions()
00190 {
00191         if( _pluginLoadGuard )
00192         {
00193                 //TUTTLE_TLOG( TUTTLE_TRACE, "loadAndDescribeAction already called on plugin " + getApiHandler()._infos._apiName );
00194                 return;
00195         }
00196         _pluginLoadGuard.reset( new tuttle::host::ofx::OfxhPluginLoadGuard( *this, getApiHandler().getHost() ) );
00197 
00198         OfxPlugin* op = _pluginLoadGuard->getOfxPlugin();
00199 
00200         if( op == NULL )
00201         {
00202                 _pluginLoadGuard.reset( NULL );
00203                 BOOST_THROW_EXCEPTION( exception::Data()
00204                     << exception::dev( "loadAndDescribeAction: OfxPlugin is NULL." )
00205                     << exception::pluginIdentifier( getIdentifier() )
00206                     << exception::ofxApi( getApiHandler()._apiName ) );
00207         }
00208 
00209         int rval = op->mainEntry( kOfxActionLoad, 0, 0, 0 );
00210 
00211         if( rval != kOfxStatOK && rval != kOfxStatReplyDefault )
00212         {
00213                 _pluginLoadGuard.reset( NULL );
00214                 BOOST_THROW_EXCEPTION( exception::Data()
00215                     << exception::dev( "Load Action failed." )
00216                     << exception::pluginIdentifier( getIdentifier() )
00217                     << exception::ofxApi( getApiHandler()._apiName ) );
00218         }
00219 
00220         rval = op->mainEntry( kOfxActionDescribe, getDescriptor().getHandle(), 0, 0 );
00221 
00222         if( rval != kOfxStatOK && rval != kOfxStatReplyDefault )
00223         {
00224                 _pluginLoadGuard.reset( NULL );
00225                 BOOST_THROW_EXCEPTION( exception::Data()
00226                     << exception::dev( "Describe Action failed." )
00227                     << exception::pluginIdentifier( getIdentifier() )
00228                     << exception::ofxApi( getApiHandler()._apiName ) );
00229         }
00230         initContexts();
00231 }
00232 
00233 OfxhImageEffectNodeDescriptor& OfxhImageEffectPlugin::getDescriptorInContext( const std::string& context )
00234 {
00235         ContextMap::iterator it = _contexts.find( context );
00236 
00237         //TUTTLE_TLOG( TUTTLE_TRACE, "context : " << context );
00238         if( it != _contexts.end() )
00239         {
00240                 //TUTTLE_TLOG( TUTTLE_TRACE, "found context description : " << it->second->getLabel() );
00241                 return *( it->second );
00242         }
00243 
00244         if( _knownContexts.find( context ) == _knownContexts.end() )
00245         {
00246                 BOOST_THROW_EXCEPTION( exception::Bug()
00247                     << exception::dev( "Context not found." )
00248                     << exception::pluginIdentifier( getIdentifier() )
00249                     << exception::ofxContext( context ) );
00250         }
00251         return describeInContextAction( context );
00252 }
00253 
00254 OfxhImageEffectNodeDescriptor& OfxhImageEffectPlugin::describeInContextAction( const std::string& context )
00255 {
00256         tuttle::host::ofx::property::OfxhPropSpec inargspec[] = {
00257                 { kOfxImageEffectPropContext, tuttle::host::ofx::property::ePropTypeString, 1, true, context.c_str() },
00258                 { 0 }
00259         };
00260 
00261         tuttle::host::ofx::property::OfxhSet inarg( inargspec );
00262 
00263         std::auto_ptr<tuttle::host::ofx::imageEffect::OfxhImageEffectNodeDescriptor> newContext( core().getHost().makeDescriptor( getDescriptor(), *this ) );
00264         int rval = kOfxStatFailed;
00265         if( _pluginLoadGuard->getOfxPlugin() )
00266                 rval = _pluginLoadGuard->getOfxPlugin()->mainEntry( kOfxImageEffectActionDescribeInContext, newContext->getHandle(), inarg.getHandle(), 0 );
00267 
00268         if( rval != kOfxStatOK && rval != kOfxStatReplyDefault )
00269         {
00270                 BOOST_THROW_EXCEPTION( OfxhException( rval, "kOfxImageEffectActionDescribeInContext failed." ) );
00271         }
00272         std::string key( context ); // for constness
00273         _contexts.insert( key, newContext.release() );
00274         return _contexts.at( context );
00275 }
00276 
00277 imageEffect::OfxhImageEffectNode* OfxhImageEffectPlugin::createInstance( const std::string& context )
00278 {
00279         /**
00280          * @todo - we need to make sure action:load is called, then action:describe again
00281          * (not because we are expecting the results to change, but because plugin
00282          * might get confused otherwise), then a describe_in_context
00283          */
00284         loadAndDescribeActions();
00285         
00286         OfxhImageEffectNodeDescriptor& desc        = getDescriptorInContext( context );
00287         imageEffect::OfxhImageEffectNode* instance = core().getHost().newInstance( *this, desc, context ); /// @todo tuttle: don't use singleton here.
00288         instance->createInstanceAction(); // Is it not possible to move this in a constructor ? In some cases it's interesting to initialize host side values before creation of plugin side objets (eg. node duplication or creation from file).
00289         return instance;
00290 }
00291 
00292 void OfxhImageEffectPlugin::unloadAction()
00293 {
00294         if( _pluginLoadGuard )
00295         {
00296                 _pluginLoadGuard->getOfxPlugin()->mainEntry( kOfxActionUnload, 0, 0, 0 );
00297         }
00298 }
00299 
00300 }
00301 }
00302 }
00303 }
00304 
00305 BOOST_CLASS_EXPORT_IMPLEMENT( tuttle::host::ofx::imageEffect::OfxhImageEffectPlugin )
00306