TuttleOFX
1
|
00001 #include <tuttle/common/utils/global.hpp> 00002 #include <tuttle/common/exceptions.hpp> 00003 #include <tuttle/host/Core.hpp> 00004 #include <tuttle/host/ofx/OfxhImageEffectPlugin.hpp> 00005 00006 #include <boost/algorithm/string/join.hpp> 00007 #include <boost/foreach.hpp> 00008 #include <boost/filesystem.hpp> 00009 #include <boost/algorithm/string.hpp> 00010 00011 #include <iostream> 00012 #include <cstring> 00013 #include <algorithm> 00014 00015 #include "nodeDummy.hpp" 00016 00017 namespace sam { 00018 namespace samdo { 00019 00020 bool Dummy::isDummyReaderNode( const std::string& nodeName ) 00021 { 00022 return ( ( nodeName == READER_DUMMY_FULLNAME ) || ( nodeName == READER_DUMMY_NAME ) || ( nodeName == READER_DUMMY_SHORTNAME ) ); 00023 } 00024 00025 bool Dummy::isDummyWriterNode( const std::string& nodeName ) 00026 { 00027 return ( ( nodeName == WRITER_DUMMY_FULLNAME ) || ( nodeName == WRITER_DUMMY_NAME ) || ( nodeName == WRITER_DUMMY_SHORTNAME ) ); 00028 } 00029 00030 bool Dummy::isDummyNode( const std::string& nodeName ) 00031 { 00032 return ( isDummyReaderNode( nodeName ) || isDummyWriterNode( nodeName ) ); 00033 } 00034 00035 void Dummy::getFullName( std::string& inputNode ) 00036 { 00037 if( isDummyReaderNode( inputNode ) ) 00038 { 00039 inputNode = READER_DUMMY_NAME; 00040 return; 00041 } 00042 if( isDummyWriterNode( inputNode ) ) 00043 { 00044 inputNode = WRITER_DUMMY_NAME; 00045 return; 00046 } 00047 } 00048 00049 bpo::options_description Dummy::getInfoOptions() 00050 { 00051 bpo::options_description infoOptions; 00052 infoOptions.add_options() 00053 ( kHelpOptionString, kHelpOptionMessage ) 00054 ( kVersionOptionString, kVersionOptionMessage ) 00055 ( kExpertOptionString, kExpertOptionMessage ) 00056 ( kPluginsOptionString, kPluginsOptionMessage ) 00057 ( kFormatOptionString, kFormatOptionMessage ); 00058 return infoOptions; 00059 } 00060 00061 bpo::options_description Dummy::getConfOptions() 00062 { 00063 bpo::options_description confOptions; 00064 confOptions.add_options() 00065 ( kVerboseOptionString, kVerboseOptionMessage ) 00066 ( kIdOptionString, bpo::value<std::string > (), kIdOptionMessage ) 00067 ( kNbCoresOptionString, bpo::value<std::size_t > (), kNbCoresOptionMessage ); 00068 return confOptions; 00069 } 00070 00071 bpo::options_description Dummy::getOpenFXOptions() 00072 { 00073 bpo::options_description openFXOptions; 00074 openFXOptions.add_options() 00075 ( kAttributesOptionString, kAttributesOptionMessage ) 00076 ( kPropertiesOptionString, kPropertiesOptionMessage ) 00077 ( kClipsOptionString, kClipsOptionMessage ) 00078 ( kClipOptionString, bpo::value<std::string > (), kClipOptionMessage ) 00079 ( kParametersOptionString, kParametersOptionMessage ) 00080 ( kParamInfosOptionString, bpo::value<std::string > (), kParamInfosOptionMessage ) 00081 ( kParamValuesOptionString, bpo::value<std::vector<std::string> >(), kParamValuesOptionMessage ) 00082 // for auto completion 00083 ( kParametersReduxOptionString, kParametersReduxOptionMessage ) 00084 ( kParamTypeOptionString, bpo::value<std::string > (), kParamTypeOptionMessage ) 00085 ( kParamPossibleValuesOptionString, bpo::value<std::string > (), kParamPossibleValuesOptionMessage ) 00086 ( kParamDefaultOptionString, bpo::value<std::string > (), kParamDefaultOptionMessage ) 00087 ( kParamGroupOptionString, kParamGroupOptionMessage ); 00088 return openFXOptions; 00089 } 00090 00091 void Dummy::getCommandLineParameters( bpo::variables_map& node_vm, const std::vector<std::string>& nodeArgs ) 00092 { 00093 // Declare the supported options. 00094 bpo::options_description infoOptions = getInfoOptions(); 00095 bpo::options_description confOptions = getConfOptions(); 00096 // describe openFX options 00097 bpo::options_description openfxOptions = getOpenFXOptions(); 00098 00099 bpo::positional_options_description param_values; 00100 param_values.add( kParamValuesOptionLongName, -1 ); 00101 00102 bpo::options_description all_options; 00103 all_options.add( infoOptions ).add( confOptions ).add( openfxOptions ); 00104 00105 bpo::store( bpo::command_line_parser( nodeArgs ).options( all_options ).positional( param_values ).run(), node_vm ); 00106 } 00107 00108 void Dummy::getParametersFromCommandLine( std::vector<std::string>& parameters, const std::vector<std::string>& nodeArgs ) 00109 { 00110 bpo::variables_map node_vm; 00111 getCommandLineParameters( node_vm, nodeArgs ); 00112 00113 if( node_vm.count( kParamValuesOptionLongName ) ) 00114 { 00115 parameters = node_vm[kParamValuesOptionLongName].as< std::vector< std::string> > (); 00116 } 00117 } 00118 00119 void Dummy::getPathsFromCommandLine( std::vector<std::string>& paths, const std::vector<std::string>& nodeArgs ) 00120 { 00121 getParametersFromCommandLine( paths, nodeArgs ); 00122 00123 std::vector<std::string>::iterator it = paths.begin(); 00124 for( ; it < paths.end(); it++ ) 00125 { 00126 if( (*it).find("=") != std::string::npos ) 00127 { 00128 paths.erase( it ); 00129 it--; 00130 } 00131 } 00132 if( paths.size() == 0 ) 00133 { 00134 paths.push_back( "./" ); 00135 } 00136 } 00137 00138 void Dummy::getExtensionsFromCommandLine( std::vector<std::string>& extensions, const std::vector<std::string>& nodeArgs ) 00139 { 00140 getParametersFromCommandLine( extensions, nodeArgs ); 00141 00142 std::vector<std::string>::iterator it = extensions.begin(); 00143 for( ; it < extensions.end(); it++ ) 00144 { 00145 if( std::strncmp( (*it).c_str() , "ext=" , 4 ) != 0 ) 00146 { 00147 extensions.erase( it ); 00148 it--; 00149 } 00150 else 00151 { 00152 *it = (*it).erase( 0, 4 ); // erase ext= 00153 } 00154 } 00155 } 00156 00157 void Dummy::addDummyNodeInList( std::vector<std::string>& list ) 00158 { 00159 list.push_back( READER_DUMMY_NAME ); 00160 list.push_back( WRITER_DUMMY_NAME ); 00161 } 00162 00163 void Dummy::addFullNameDummyNodeInList( std::vector<std::string>& list ) 00164 { 00165 list.push_back( READER_DUMMY_FULLNAME ); 00166 list.push_back( WRITER_DUMMY_FULLNAME ); 00167 } 00168 00169 void Dummy::addShortNameDummyNodeInList( std::vector<std::string>& list ) 00170 { 00171 list.push_back( READER_DUMMY_SHORTNAME ); 00172 list.push_back( WRITER_DUMMY_SHORTNAME ); 00173 } 00174 00175 std::vector<std::string> Dummy::getAllSupportedNodes( const std::string& context ) 00176 { 00177 const NodeList& nodeList = ttl::core().getImageEffectPluginCache().getPlugins(); 00178 std::vector<std::string> listOfPlugins; 00179 00180 BOOST_FOREACH( ttl::ofx::imageEffect::OfxhImageEffectPlugin* node, nodeList ) 00181 { 00182 try 00183 { 00184 const std::string pluginName = node->getRawIdentifier(); 00185 node->loadAndDescribeActions(); 00186 if( node->supportsContext( context ) ) 00187 { 00188 listOfPlugins.push_back( pluginName ); 00189 } 00190 } 00191 catch(...) 00192 { 00193 /// @todo Create a list of loading errors? 00194 } 00195 } 00196 00197 // sort results 00198 std::sort( listOfPlugins.begin(), listOfPlugins.end() ); 00199 return listOfPlugins; 00200 } 00201 00202 std::vector<std::string> Dummy::getSupportedExtensions( const std::string& context ) 00203 { 00204 const NodeList& nodeList = ttl::core().getImageEffectPluginCache().getPlugins(); 00205 std::vector<std::string> listOfExtensions; 00206 00207 BOOST_FOREACH( ttl::ofx::imageEffect::OfxhImageEffectPlugin* node, nodeList ) 00208 { 00209 try 00210 { 00211 node->loadAndDescribeActions(); 00212 if( node->supportsContext( context ) ) 00213 { 00214 //TUTTLE_LOG_INFO( pluginName ); 00215 if( node->getDescriptorInContext( context ).getProperties().hasProperty( kTuttleOfxImageEffectPropSupportedExtensions ) ) 00216 { 00217 const tuttle::host::ofx::property::OfxhProperty& prop = node->getDescriptorInContext( context ).getProperties().fetchProperty( kTuttleOfxImageEffectPropSupportedExtensions ); 00218 00219 for( std::size_t n = 0; n < prop.getDimension(); ++n ) 00220 { 00221 listOfExtensions.push_back( prop.getStringValue( n ) ); 00222 } 00223 } 00224 } 00225 } 00226 catch(...) 00227 {} 00228 } 00229 00230 // sort results 00231 std::sort( listOfExtensions.begin(), listOfExtensions.end() ); 00232 00233 // delete similar extension 00234 listOfExtensions.erase( std::unique( listOfExtensions.begin(), listOfExtensions.end() ), listOfExtensions.end() ); 00235 00236 return listOfExtensions; 00237 } 00238 00239 void Dummy::printAllSupportedNodes( const std::string& context ) 00240 { 00241 BOOST_FOREACH( const std::string& pluginName, getAllSupportedNodes( context ) ) 00242 { 00243 TUTTLE_LOG_INFO( pluginName ); 00244 } 00245 } 00246 00247 void Dummy::printAllSupportedExtensions( const std::string& context ) 00248 { 00249 TUTTLE_LOG_INFO( boost::algorithm::join( getSupportedExtensions( context ), "," ) ); 00250 } 00251 00252 void Dummy::displayHelp( const std::string& nodeFullName ) 00253 { 00254 using namespace sam; 00255 boost::shared_ptr<tuttle::common::Color> color( tuttle::common::Color::get() ); 00256 00257 TUTTLE_LOG_INFO( color->_blue << "TuttleOFX project [" << kUrlTuttleofxProject << "]" << color->_std ); 00258 TUTTLE_LOG_INFO( "" ); 00259 TUTTLE_LOG_INFO( color->_blue << "NODE" << color->_std ); 00260 TUTTLE_LOG_INFO( color->_green << "\tsam do " << nodeFullName << " - OpenFX node." << color->_std ); 00261 TUTTLE_LOG_INFO( "" ); 00262 TUTTLE_LOG_INFO( color->_blue << "DESCRIPTION" << color->_std ); 00263 TUTTLE_LOG_INFO( color->_green << "\tnode type: dummy (specific to TuttleOFX)" << color->_std ); 00264 // internal node help 00265 TUTTLE_LOG_INFO( "" ); 00266 TUTTLE_LOG_INFO( "Dummy reader call specific reader detected by the extension of the sequence name." ); 00267 TUTTLE_LOG_INFO( "" ); 00268 TUTTLE_LOG_INFO( color->_blue << "ASSOCIATED PLUGINS" << color->_std ); 00269 if( isDummyReaderNode( nodeFullName ) ) 00270 printAllSupportedNodes( kOfxImageEffectContextReader ); 00271 if( isDummyWriterNode( nodeFullName ) ) 00272 printAllSupportedNodes( kOfxImageEffectContextWriter ); 00273 TUTTLE_LOG_INFO( "" ); 00274 TUTTLE_LOG_INFO( color->_blue << "SUPPORTED FORMATS" << color->_std ); 00275 if( isDummyReaderNode( nodeFullName ) ) 00276 printAllSupportedExtensions( kOfxImageEffectContextReader ); 00277 if( isDummyWriterNode( nodeFullName ) ) 00278 printAllSupportedExtensions( kOfxImageEffectContextWriter ); 00279 TUTTLE_LOG_INFO( "" ); 00280 TUTTLE_LOG_INFO( color->_blue << "PARAMETERS" << color->_std ); 00281 TUTTLE_LOG_INFO( color->_green << "\t" << std::left << std::setw( 25 ) << "ext" << ": " << color->_std << " String\n\t select extension from supported format list."); 00282 TUTTLE_LOG_INFO( "" ); 00283 //TUTTLE_LOG_INFO( color->_blue << "CLIPS" << color->_std ); 00284 //coutClipsWithDetails( currentNode ); 00285 00286 TUTTLE_LOG_INFO( "" ); 00287 TUTTLE_LOG_INFO( color->_blue << "DISPLAY OPTIONS (override the process)" << color->_std ); 00288 TUTTLE_LOG_INFO( getInfoOptions() ); 00289 TUTTLE_LOG_INFO( color->_blue << "CONFIGURE PROCESS" << color->_std ); 00290 TUTTLE_LOG_INFO( getConfOptions() ); 00291 00292 TUTTLE_LOG_INFO( "" ); 00293 } 00294 00295 void Dummy::displayExpertHelp( const std::string& nodeFullName ) 00296 { 00297 using namespace sam; 00298 boost::shared_ptr<tuttle::common::Color> color( tuttle::common::Color::get() ); 00299 00300 displayHelp( nodeFullName ); 00301 00302 TUTTLE_LOG_INFO( color->_blue << "EXPERT OPTIONS" << color->_std ); 00303 TUTTLE_LOG_INFO( getOpenFXOptions() ); 00304 } 00305 00306 void Dummy::foundAssociateSpecificDummyNode( std::string& inputNode, const std::string& dummyNodeName, const NodeList& nodeList, const std::vector<std::string>& nodeArgs ) 00307 { 00308 if( std::strcmp( inputNode.c_str(), dummyNodeName.c_str() ) ) 00309 return; 00310 00311 bpo::variables_map node_vm; 00312 getCommandLineParameters( node_vm, nodeArgs ); 00313 00314 if( node_vm.count( kHelpOptionLongName ) ) 00315 { 00316 displayHelp( dummyNodeName ); 00317 exit( 0 ); 00318 } 00319 if( node_vm.count( kExpertOptionLongName ) ) 00320 { 00321 displayExpertHelp( dummyNodeName ); 00322 exit( 0 ); 00323 } 00324 if( node_vm.count( kPluginsOptionLongName ) ) 00325 { 00326 if( isDummyReaderNode( dummyNodeName ) ) 00327 printAllSupportedNodes( kOfxImageEffectContextReader ); 00328 if( isDummyWriterNode( dummyNodeName ) ) 00329 printAllSupportedNodes( kOfxImageEffectContextWriter ); 00330 exit( 0 ); 00331 } 00332 00333 if( node_vm.count( kFormatOptionLongName ) ) 00334 { 00335 if( isDummyReaderNode( dummyNodeName ) ) 00336 printAllSupportedExtensions( kOfxImageEffectContextReader ); 00337 if( isDummyWriterNode( dummyNodeName ) ) 00338 printAllSupportedExtensions( kOfxImageEffectContextWriter ); 00339 exit( 0 ); 00340 } 00341 00342 if( node_vm.count( kVersionOptionLongName ) ) 00343 { 00344 TUTTLE_LOG_INFO( "\tsam do " << dummyNodeName ); 00345 TUTTLE_LOG_INFO( "Version 1.0" ); 00346 TUTTLE_LOG_INFO( "" ); 00347 exit( 0 ); 00348 } 00349 00350 if( nodeArgs.size() == 0 ) 00351 { 00352 if( isDummyWriterNode( dummyNodeName ) ) 00353 { 00354 inputNode = "tuttle.dummy"; 00355 return; 00356 } 00357 00358 BOOST_THROW_EXCEPTION( tuttle::exception::Value() 00359 << tuttle::exception::user() + "specify and input name (file or sequence)." ); 00360 } 00361 00362 std::vector<std::string> paths; 00363 bool needRecursiveProcess = false; 00364 if( kParamValuesOptionLongName ) 00365 { 00366 paths = node_vm[kParamValuesOptionLongName].as< std::vector< std::string> > (); 00367 BOOST_FOREACH( const std::string& basePath, paths ) 00368 { 00369 //TUTTLE_LOG_VAR( TUTTLE_TRACE, basePath ); 00370 boost::filesystem::path p( basePath ); 00371 std::string inputExtension = p.extension().string(); 00372 boost::algorithm::to_lower( inputExtension ); 00373 if( inputExtension.size() ) 00374 { 00375 break; 00376 } 00377 else 00378 { 00379 needRecursiveProcess = true; 00380 } 00381 } 00382 } 00383 else 00384 { 00385 paths.push_back( "./" ); 00386 } 00387 00388 if( needRecursiveProcess ) 00389 { 00390 TUTTLE_LOG_INFO("recursive"); 00391 inputNode = "tuttle.dummy"; 00392 return; 00393 } 00394 00395 boost::filesystem::path p( paths.at(0) ); 00396 std::string inputExtension = p.extension().string(); 00397 inputExtension = inputExtension.substr( 1 ); // remove '.' at begining 00398 unsigned int numberOfSupportedExtension = std::numeric_limits<unsigned int>::max(); 00399 BOOST_FOREACH( ttl::ofx::imageEffect::OfxhImageEffectPlugin* node, nodeList ) 00400 { 00401 const std::string pluginName = node->getRawIdentifier(); 00402 if( boost::algorithm::find_first( pluginName, dummyNodeName ) ) 00403 { 00404 tuttle::host::ofx::imageEffect::OfxhImageEffectPlugin* plugin = tuttle::host::core().getImageEffectPluginById( pluginName ); 00405 plugin->loadAndDescribeActions(); 00406 const tuttle::host::ofx::imageEffect::OfxhImageEffectPlugin::ContextSet contexts = plugin->getContexts(); 00407 const tuttle::host::ofx::property::OfxhSet& properties = plugin->getDescriptorInContext( *contexts.begin() ).getProperties(); 00408 if( properties.hasProperty( kTuttleOfxImageEffectPropSupportedExtensions ) ) 00409 { 00410 const tuttle::host::ofx::property::OfxhProperty& prop = properties.fetchProperty( kTuttleOfxImageEffectPropSupportedExtensions ); 00411 00412 for( std::size_t n = 0; n < prop.getDimension(); ++n ) 00413 { 00414 //TUTTLE_TLOG_VAR2( TUTTLE_TRACE, prop.getStringValue( n ), inputExtension ); 00415 if( prop.getStringValue( n ) == inputExtension ) 00416 { 00417 //TUTTLE_TLOG( TUTTLE_TRACE, pluginName << " [" << prop.getDimension() << "] can read " << prop.getStringValue( n ) ); 00418 if( prop.getDimension() < numberOfSupportedExtension ) 00419 { 00420 // Arbitrary solution... 00421 // If we found multiple plugins that support the requested format, 00422 // we select the plugin which supports the lowest number of formats. 00423 // So by defaut, we select specialized plugin before 00424 // plugin using generic libraries with all formats. 00425 numberOfSupportedExtension = prop.getDimension(); 00426 inputNode = pluginName; 00427 } 00428 } 00429 } 00430 } 00431 } 00432 } 00433 if( numberOfSupportedExtension == std::numeric_limits<unsigned int>::max() ) 00434 { 00435 BOOST_THROW_EXCEPTION( tuttle::exception::Value() 00436 << tuttle::exception::user() + "Unsupported extension \"" + inputExtension + "\"." ); 00437 } 00438 TUTTLE_LOG_WARNING( "Replace " << dummyNodeName << " with: " << inputNode ); 00439 } 00440 00441 void Dummy::foundAssociateDummyNode( std::string& inputNode, const std::vector<ttl::ofx::imageEffect::OfxhImageEffectPlugin*>& nodeList, const std::vector<std::string>& nodeArgs ) 00442 { 00443 getFullName( inputNode ); 00444 foundAssociateSpecificDummyNode( inputNode, READER_DUMMY_NAME, nodeList, nodeArgs ); 00445 foundAssociateSpecificDummyNode( inputNode, WRITER_DUMMY_NAME, nodeList, nodeArgs ); 00446 } 00447 00448 } 00449 }