TuttleOFX
1
|
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