TuttleOFX  1
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         , _pc( NULL )
00067         , _pluginHandle( NULL )
00068         , _baseDescriptor( NULL )
00069 {
00070         /// @todo tuttle
00071 }
00072 
00073 OfxhImageEffectPlugin::OfxhImageEffectPlugin( OfxhImageEffectPluginCache& pc, OfxhPluginBinary& pb, int pi, OfxPlugin& pl )
00074         : OfxhPlugin( pb, pi, pl )
00075         , _pc( &pc )
00076         , _pluginHandle( 0 )
00077         , _baseDescriptor( core().getHost().makeDescriptor( *this ) )
00078 {
00079         //      loadAndDescribeActions();
00080 }
00081 
00082 OfxhImageEffectPlugin::OfxhImageEffectPlugin( OfxhImageEffectPluginCache& pc,
00083                                               OfxhPluginBinary&           pb,
00084                                               int                         pi,
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( pb, pi, api, apiVersion, pluginId, rawId, pluginMajorVersion, pluginMinorVersion )
00092         , _pc( &pc )
00093         , _pluginHandle( 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( getPluginHandle() )
00106         {
00107                 getPluginHandle()->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         _pc = &dynamic_cast<OfxhImageEffectPluginCache&>( api );
00122 }
00123 
00124 APICache::OfxhPluginAPICacheI& OfxhImageEffectPlugin::getApiHandler()
00125 {
00126         return *_pc;
00127 }
00128 
00129 const APICache::OfxhPluginAPICacheI& OfxhImageEffectPlugin::getApiHandler() const
00130 {
00131         return *_pc;
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_TLOG( TUTTLE_TRACE, context << " supportsContext? " << _knownContexts.size() << std::endl;
00169         
00170         for( ContextSet::iterator it = _knownContexts.begin(),
00171                  it != _knownContexts.end();
00172                  ++it )
00173         {
00174                 TUTTLE_TLOG( TUTTLE_TRACE, "context " << *it );
00175         }
00176         */
00177         return _knownContexts.find( context ) != _knownContexts.end();
00178 }
00179 
00180 void OfxhImageEffectPlugin::initContexts()
00181 {
00182         const tuttle::host::ofx::property::OfxhSet& eProps = getDescriptor().getProperties();
00183         int size                                           = eProps.getDimension( kOfxImageEffectPropSupportedContexts );
00184 
00185         for( int j = 0; j < size; ++j )
00186         {
00187                 std::string context = eProps.getStringProperty( kOfxImageEffectPropSupportedContexts, j );
00188                 addContext( context );
00189         }
00190 }
00191 
00192 void OfxhImageEffectPlugin::loadAndDescribeActions()
00193 {
00194         if( getPluginHandle() )
00195         {
00196                 //TUTTLE_TLOG( TUTTLE_TRACE, "loadAndDescribeAction already called on plugin " + getApiHandler()._infos._apiName );
00197                 return;
00198         }
00199         _pluginHandle.reset( new tuttle::host::ofx::OfxhPluginHandle( *this, getApiHandler().getHost() ) );
00200 
00201         OfxPlugin* op = _pluginHandle->getOfxPlugin();
00202 
00203         if( op == NULL )
00204         {
00205                 _pluginHandle.reset( NULL );
00206                 BOOST_THROW_EXCEPTION( exception::Data()
00207                     << exception::dev( "loadAndDescribeAction: OfxPlugin is NULL." )
00208                     << exception::ofxApi( getApiHandler()._apiName ) );
00209         }
00210 
00211         int rval = op->mainEntry( kOfxActionLoad, 0, 0, 0 );
00212 
00213         if( rval != kOfxStatOK && rval != kOfxStatReplyDefault )
00214         {
00215                 _pluginHandle.reset( NULL );
00216                 BOOST_THROW_EXCEPTION( exception::Data()
00217                     << exception::dev( "Load Action failed." )
00218                     << exception::ofxApi( getApiHandler()._apiName ) );
00219         }
00220 
00221         rval = op->mainEntry( kOfxActionDescribe, getDescriptor().getHandle(), 0, 0 );
00222 
00223         if( rval != kOfxStatOK && rval != kOfxStatReplyDefault )
00224         {
00225                 _pluginHandle.reset( NULL );
00226                 BOOST_THROW_EXCEPTION( exception::Data()
00227                     << exception::dev( "Describe Action failed." )
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::ofxContext( context ) );
00249         }
00250         return describeInContextAction( context );
00251 }
00252 
00253 OfxhImageEffectNodeDescriptor& OfxhImageEffectPlugin::describeInContextAction( const std::string& context )
00254 {
00255         tuttle::host::ofx::property::OfxhPropSpec inargspec[] = {
00256                 { kOfxImageEffectPropContext, tuttle::host::ofx::property::ePropTypeString, 1, true, context.c_str() },
00257                 { 0 }
00258         };
00259 
00260         tuttle::host::ofx::property::OfxhSet inarg( inargspec );
00261 
00262         OfxhPluginHandle* ph = getPluginHandle();
00263 
00264         std::auto_ptr<tuttle::host::ofx::imageEffect::OfxhImageEffectNodeDescriptor> newContext( core().getHost().makeDescriptor( getDescriptor(), *this ) );
00265         int rval = kOfxStatFailed;
00266         if( ph->getOfxPlugin() )
00267                 rval = ph->getOfxPlugin()->mainEntry( kOfxImageEffectActionDescribeInContext, newContext->getHandle(), inarg.getHandle(), 0 );
00268 
00269         if( rval != kOfxStatOK && rval != kOfxStatReplyDefault )
00270         {
00271                 BOOST_THROW_EXCEPTION( OfxhException( rval, "kOfxImageEffectActionDescribeInContext failed." ) );
00272         }
00273         std::string key( context ); // for constness
00274         _contexts.insert( key, newContext.release() );
00275         return _contexts.at( context );
00276 }
00277 
00278 imageEffect::OfxhImageEffectNode* OfxhImageEffectPlugin::createInstance( const std::string& context )
00279 {
00280         /**
00281          * @todo - we need to make sure action:load is called, then action:describe again
00282          * (not because we are expecting the results to change, but because plugin
00283          * might get confused otherwise), then a describe_in_context
00284          */
00285         loadAndDescribeActions();
00286         if( getPluginHandle() == NULL )
00287         {
00288                 BOOST_THROW_EXCEPTION( exception::BadHandle() );
00289         }
00290         OfxhImageEffectNodeDescriptor& desc        = getDescriptorInContext( context );
00291         imageEffect::OfxhImageEffectNode* instance = core().getHost().newInstance( *this, desc, context ); /// @todo tuttle: don't use singleton here.
00292         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).
00293         return instance;
00294 }
00295 
00296 void OfxhImageEffectPlugin::unloadAction()
00297 {
00298         if( getPluginHandle() )
00299         {
00300                 ( *_pluginHandle )->mainEntry( kOfxActionUnload, 0, 0, 0 );
00301         }
00302 }
00303 
00304 }
00305 }
00306 }
00307 }
00308 
00309 BOOST_CLASS_EXPORT_IMPLEMENT( tuttle::host::ofx::imageEffect::OfxhImageEffectPlugin )
00310