TuttleOFX  1
main.cpp
Go to the documentation of this file.
00001 #include <sam/common/options.hpp>
00002 #include <sam/common/utility.hpp>
00003 
00004 #include <tuttle/host/Core.hpp>
00005 #include <tuttle/host/ofx/OfxhImageEffectPlugin.hpp>
00006 
00007 #include <boost/filesystem/operations.hpp>
00008 #include <boost/filesystem/exception.hpp>
00009 #include <boost/exception/diagnostic_information.hpp>
00010 #include <boost/foreach.hpp>
00011 #include <boost/program_options.hpp>
00012 #include <boost/regex.hpp>
00013 #include <boost/algorithm/string.hpp>
00014 #include <boost/algorithm/string/split.hpp>
00015 
00016 
00017 namespace           bpo         = boost::program_options;
00018 namespace           bal         = boost::algorithm;
00019 namespace           tth         = tuttle::host;
00020 
00021 bool                properties  = false;
00022 bool                clips       = false;
00023 bool                parameters  = false;
00024 
00025 /// get defaults values of plugin properties
00026 std::string getDefaultValues(const tth::ofx::property::OfxhProperty& prop)
00027 {
00028         std::string s;
00029         if( !(prop.getType() == 3) ) // if Pointer, we don't have _value and _defaultValue properties
00030         {
00031                 int n = 0;
00032                 for( ; n < (int)( prop.getDimension() ) - 1; ++n )
00033                 {
00034                         s += prop.getStringValue( n );
00035                         s += ", ";
00036                 }
00037                 if( prop.getDimension() > 0 )
00038                 {
00039                         s += prop.getStringValue( n );
00040                 }
00041         }
00042         return s;
00043 }
00044 
00045 void printProperties( const tth::ofx::property::OfxhSet properties, std::string context="" )
00046 {
00047         signal(SIGINT, signal_callback_handler);
00048 
00049         using namespace tuttle::common;
00050         boost::shared_ptr<Color> color( Color::get() );
00051         if( context.size() == 0 )
00052         {
00053                 TUTTLE_LOG_INFO( color->_red << "Number of properties : " << properties.getSize() << color->_std );
00054         }
00055         else
00056         {
00057                 TUTTLE_LOG_INFO( color->_red << "Number of properties for \"" << context << "\": " << properties.getSize() << color->_std );
00058         }
00059 
00060         std::string propertyId = "Property Name";
00061         propertyId.resize( 50, ' ' );
00062         TUTTLE_LOG_INFO( 
00063                                 color->_red << "RW" << color->_std << " " <<
00064                                 color->_red << "ModifiedBy" << color->_std << "\t" <<
00065                                 color->_red << "Type" << color->_std << "\t" <<
00066                                 color->_red << "Size" << color->_std << "\t" <<
00067                                 color->_red << propertyId << color->_std << "\t" <<
00068                                 color->_red << "Default Values" << color->_std );
00069         
00070         tth::ofx::property::PropertyMap propMap = properties.getMap();
00071         for( tth::ofx::property::PropertyMap::const_iterator itProperty = propMap.begin(); itProperty != propMap.end(); ++itProperty )
00072         {
00073                 const tth::ofx::property::OfxhProperty& prop = *( itProperty->second );
00074                 std::string propertyLabel = itProperty->first;
00075                 propertyLabel.resize( 50, ' ' );
00076                 
00077                 TUTTLE_LOG_INFO(
00078                         color->_green <<
00079                         ( prop.getPluginReadOnly() ? (color->_green + "r-" + color->_std + " ") : (color->_green + "rw" + color->_std + " " ) ) <<
00080                         ( prop.getModifiedBy() == tth::ofx::property::eModifiedByHost ? ( color->_green + "host" + color->_std + "  \t" ) : ( color->_green + "plugin" + color->_std + "\t" ) ) <<
00081                         color->_green << ( tth::ofx::property::mapTypeEnumToString( prop.getType() ) ) << color->_std << "\t" << color->_green << "[" <<
00082                         prop.getDimension() << "]" << color->_std << "\t" <<
00083                         color->_blue << propertyLabel << color->_std << "\t" << color->_green << "{ " <<
00084                         getDefaultValues(prop) << " }" << color->_std
00085                 );
00086         }
00087 }
00088 
00089 
00090 void getPluginProperties( const std::string& plugName )
00091 {
00092         using namespace tuttle::common;
00093         boost::shared_ptr<Color> color( Color::get() );
00094         tth::ofx::imageEffect::OfxhImageEffectPlugin* plug = tth::core().getImageEffectPluginById( plugName );
00095         
00096         if( !plug )
00097         {
00098                 TUTTLE_LOG_ERROR( color->_red << "no plugin match to: " << plugName << color->_std );
00099                 return;
00100         }
00101 
00102         plug->loadAndDescribeActions();
00103         TUTTLE_LOG_INFO("Identifier:\t\t"               << plug->getIdentifier() );
00104         TUTTLE_LOG_INFO("Raw identifier:\t\t"   << plug->getRawIdentifier() );
00105         TUTTLE_LOG_INFO("Minor version:\t\t"    << plug->getVersionMinor() );
00106         TUTTLE_LOG_INFO("Major version:\t\t"    << plug->getVersionMajor() );
00107         TUTTLE_LOG_INFO("API version:\t\t"              << plug->getApiVersion() );
00108 
00109         // list contexts of plugin
00110         TUTTLE_LOG_INFO( color->_green << "Contexts:" << color->_std );
00111 
00112         tth::ofx::imageEffect::OfxhImageEffectPlugin::ContextSet contexts = plug->getContexts();
00113         tth::ofx::imageEffect::OfxhImageEffectPlugin::ContextSet::iterator itContext;
00114         std::string strContexts;
00115         for( itContext = contexts.begin(); itContext != contexts.end(); ++itContext )
00116         {
00117                 strContexts += *itContext + ", ";
00118         }
00119         strContexts.erase(strContexts.size()-2, 2);
00120         TUTTLE_LOG_INFO( "[ " << strContexts << " ]" );
00121         itContext = contexts.begin();
00122 
00123         // list properties of plugin for the first context
00124         if( properties )
00125         {
00126                 TUTTLE_LOG_INFO( std::endl << color->_red << "Properties" << color->_std );
00127 
00128                 const tth::ofx::property::OfxhSet properties = plug->getDescriptorInContext( *itContext ).getProperties();
00129                 printProperties( properties );
00130         }
00131         tth::ofx::imageEffect::OfxhImageEffectNode* plugInst = NULL;
00132         if( clips | parameters )
00133         {
00134                 if( plug->supportsContext( kOfxImageEffectContextReader ) )
00135                 {
00136                         plugInst = plug->createInstance( kOfxImageEffectContextReader );
00137                 }
00138                 else if( plug->supportsContext( kOfxImageEffectContextWriter ) )
00139                 {
00140                         plugInst = plug->createInstance( kOfxImageEffectContextWriter );
00141                 }
00142                 else if( plug->supportsContext( kOfxImageEffectContextGenerator ) )
00143                 {
00144                         plugInst = plug->createInstance( kOfxImageEffectContextGenerator );
00145                 }
00146                 else if( plug->supportsContext( kOfxImageEffectContextFilter ) )
00147                 {
00148                         plugInst = plug->createInstance( kOfxImageEffectContextFilter );
00149                 }
00150                 else if( plug->supportsContext( kOfxImageEffectContextGeneral ) )
00151                 {
00152                         plugInst = plug->createInstance( kOfxImageEffectContextGeneral );
00153                 }
00154                 else
00155                 {
00156                         TUTTLE_LOG_ERROR( "Plugin contexts not supported by the host. (" + plugName + ")" );
00157                         return;
00158                 }
00159         }
00160         if( clips )
00161         {
00162                 TUTTLE_LOG_INFO( "" );
00163                 TUTTLE_LOG_INFO( std::endl << color->_red << "Clips" << color->_std );
00164 
00165                 typedef std::map<std::string, tth::ofx::attribute::OfxhClipImageDescriptor*> ContextMap;
00166 
00167                 // get contexts
00168                 ContextMap::const_iterator it = plugInst->getDescriptor().getClips().begin();
00169                 std::string strClipContexts;
00170                 for( ; it != plugInst->getDescriptor().getClips().end(); ++it )
00171                 {
00172                         strClipContexts += (*it).first + ", " ;
00173                 }
00174                 strClipContexts.erase( strClipContexts.size()-2, 2 );
00175 
00176                 TUTTLE_LOG_INFO( color->_green << "[ " << strClipContexts << " ]" << color->_std );
00177 
00178 
00179                 // get propeties in each context
00180                 ContextMap::const_iterator it2 = plugInst->getDescriptor().getClips().begin();
00181                 for( ; it2 != plugInst->getDescriptor().getClips().end(); ++it2 )
00182                 {
00183                         printProperties( (*it2).second->getProperties(), (*it2).first );
00184                 }
00185         }
00186         
00187         if( parameters )
00188         {
00189                 TUTTLE_LOG_INFO( "" );
00190                 TUTTLE_LOG_INFO( color->_red << "Parameters" << color->_std );
00191 
00192                 typedef std::map<std::string, tth::ofx::attribute::OfxhParamDescriptor*> ParamDescriptorMap;
00193 
00194                 // get contexts
00195                 ParamDescriptorMap::const_iterator it = plugInst->getDescriptor().getParams().begin();
00196                 std::string strParamsContexts;
00197                 for( ; it != plugInst->getDescriptor().getParams().end(); ++it )
00198                 {
00199                         strParamsContexts += (*it).first + ", ";
00200                 }
00201                 strParamsContexts.erase( strParamsContexts.size()-2, 2 );
00202 
00203                 TUTTLE_LOG_INFO( color->_green << "[ " << strParamsContexts << " ]" << color->_std );
00204 
00205                 // get propeties in each context
00206                 ParamDescriptorMap::const_iterator it2 = plugInst->getDescriptor().getParams().begin();
00207                 for( ; it2 != plugInst->getDescriptor().getParams().end(); it2++ )
00208                 {
00209                         printProperties( (*it2).second->getProperties(), (*it2).first );
00210                 }
00211                 /*
00212                 const tth::ofx::property::OfxhSet paramProperties = plugInst->getDescriptor().getParamList().front().getProperties();
00213                 printProperties( paramProperties, "" );
00214                 */
00215         }
00216 }
00217 
00218 bool isNotFiltered( std::string plugName, std::vector<std::string>& filters)
00219 {
00220         if( filters.size() == 0 )
00221                 return true;
00222         
00223         for( std::size_t i = 0; i < filters.size(); ++i )
00224         {
00225                 std::string filter(filters.at(i));
00226                 filter = boost::regex_replace( filter, boost::regex( "\\*" ), "(.*)"  );
00227                 filter = boost::regex_replace( filter, boost::regex( "\\?" ), "(.)"  );
00228 
00229                 if( regex_match( plugName, boost::regex(filter) ) )
00230                         return true;
00231         }
00232         return false;
00233 }
00234 
00235 int main( int argc, char** argv )
00236 {
00237         using namespace tuttle::common;
00238         using namespace sam;
00239         
00240         boost::shared_ptr<formatters::Formatter> formatter( formatters::Formatter::get() );
00241         boost::shared_ptr<Color>                 color( Color::get() );
00242         
00243         std::vector<std::string> plugins;
00244         std::vector<std::string> foundPlugins;
00245         std::vector<std::string> filters;
00246         
00247         formatter->init_logging();
00248         
00249         // Declare the supported options.
00250         bpo::options_description mainOptions;
00251         mainOptions.add_options()
00252                 ( kHelpOptionString       , kHelpOptionMessage )
00253                 ( kAllOptionString        , kAllOptionMessage )
00254                 ( kFilterOptionString     , bpo::value<std::string>(), kFilterOptionMessage )
00255                 ( kColorOptionString      , kColorOptionMessage )
00256                 ( kPropertiesOptionString , kPropertiesOptionMessage )
00257                 ( kClipsOptionString      , kClipsOptionMessage )
00258                 ( kParametersOptionString , kParametersOptionMessage )
00259                 ( kBriefOptionString      , kBriefOptionMessage )
00260         ;
00261         
00262         // describe hidden options
00263         bpo::options_description hidden;
00264         hidden.add_options()
00265                 ( kInputDirOptionString, bpo::value< std::vector<std::string> >(), kInputDirOptionMessage )
00266                 ( kEnableColorOptionString, bpo::value<std::string>(), kEnableColorOptionMessage );
00267         
00268         // define default options 
00269         bpo::positional_options_description pod;
00270         pod.add(kInputDirOptionLongName, -1);
00271         
00272         bpo::options_description cmdline_options;
00273         cmdline_options.add(mainOptions).add(hidden);
00274 
00275         //parse the command line, and put the result in vm
00276         bpo::variables_map vm;
00277         try
00278         {
00279                 bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(pod).run(), vm);
00280 
00281                 // get environnement options and parse them
00282                 if( const char* env_plugins_options = std::getenv("SAM_PLUGINS_OPTIONS") )
00283                 {
00284                         const std::vector<std::string> vecOptions = bpo::split_unix( env_plugins_options, " " );
00285                         bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm);
00286                 }
00287                 if( const char* env_options = std::getenv("SAM_OPTIONS") )
00288                 {
00289                         const std::vector<std::string> vecOptions = bpo::split_unix( env_options, " " );
00290                         bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm);
00291                 }
00292                 bpo::notify(vm);
00293         }
00294         catch( const bpo::error& e)
00295         {
00296                 TUTTLE_LOG_ERROR( "sam-plugins: command line error: " << e.what() );
00297                 exit( 254 );
00298         }
00299         catch(...)
00300         {
00301                 TUTTLE_LOG_ERROR( "sam-plugins: unknown error in command line.");
00302                 exit( 254 );
00303         }
00304 
00305         if( vm.count( kColorOptionLongName ) )
00306         {
00307                 color->enable();
00308         }
00309         
00310         if( vm.count( kEnableColorOptionLongName ) )
00311         {
00312                 const std::string str = vm[kEnableColorOptionLongName].as<std::string>();
00313                 if( string_to_boolean(str) )
00314                 {
00315                         color->enable();
00316                 }
00317                 else
00318                 {
00319                         color->disable();
00320                 }
00321         }
00322 
00323         if( vm.count(kHelpOptionLongName) )
00324         {
00325                 TUTTLE_LOG_INFO( color->_blue  << "TuttleOFX project [" << kUrlTuttleofxProject << "]" << color->_std );
00326                 TUTTLE_LOG_INFO( "" );
00327                 TUTTLE_LOG_INFO( color->_blue  << "NAME" << color->_std );
00328                 TUTTLE_LOG_INFO( color->_green << "\tsam-plugins - show informations about OpenFX plugins" << color->_std );
00329                 TUTTLE_LOG_INFO( "" );
00330                 TUTTLE_LOG_INFO( color->_blue  << "SYNOPSIS" << color->_std );
00331                 TUTTLE_LOG_INFO( color->_green << "\tsam-plugins [options] [specific_OpenFX_plugin]" << color->_std );
00332                 TUTTLE_LOG_INFO( "" );
00333                 TUTTLE_LOG_INFO( color->_blue  << "DESCRIPTION" << color->_std );
00334                 TUTTLE_LOG_INFO( "List OpenFX in OFX_PLUGIN_PATH by default.");
00335                 TUTTLE_LOG_INFO( "And could print properties, parameters and clips for each plugins" );
00336                 TUTTLE_LOG_INFO( "" );
00337                 TUTTLE_LOG_INFO( color->_blue  << "OPTIONS" << color->_std );
00338                 TUTTLE_LOG_INFO( mainOptions );
00339                 return 0;
00340         }
00341         
00342         if ( vm.count(kBriefOptionLongName) )
00343         {
00344                 TUTTLE_LOG_INFO( color->_green << "show informations about OpenFX plugins" << color->_std );
00345                 return 0;
00346         }
00347 
00348         // defines plugins
00349         if( vm.count(kInputDirOptionLongName) )
00350         {
00351                 plugins = vm[kInputDirOptionLongName].as< std::vector<std::string> >();
00352         }
00353         
00354         if( vm.count(kFilterOptionLongName) )
00355         {
00356                 bal::split( filters, vm[kFilterOptionLongName].as<std::string>(), bal::is_any_of(","));
00357         }
00358         
00359         if( vm.count(kAllOptionLongName) | (plugins.size() == 0) )
00360         {
00361                 tth::core().preload();
00362                 const std::vector<tth::ofx::imageEffect::OfxhImageEffectPlugin*> plugs = tth::core().getImageEffectPluginCache().getPlugins();
00363                 
00364                 for( std::size_t i = 0; i < plugs.size(); ++i )
00365                 {
00366                         const std::string plugName = plugs.at(i)->getRawIdentifier();
00367                         if( isNotFiltered( plugName, filters) )
00368                         {
00369                                 TUTTLE_LOG_INFO( plugName );
00370                         }
00371                 }
00372                 return 0;
00373         }
00374 
00375 
00376         if (vm.count(kPropertiesOptionLongName))
00377         {
00378                 properties = true;
00379         }
00380 
00381         if (vm.count(kClipsOptionLongName))
00382         {
00383                 clips = true;
00384         }
00385 
00386         if (vm.count(kParametersOptionLongName))
00387         {
00388                 parameters = true;
00389         }
00390 //      for(unsigned int i=0; i< plugins.size(); i++)
00391 //              TUTTLE_LOG_TRACE( plugins.at(i) );
00392         
00393         try
00394         {
00395                 tth::core().preload();
00396                 // get the plugins names for research partials names (rawreader need to make reference to the plug tuttle.reader)
00397                 const std::vector<tth::ofx::imageEffect::OfxhImageEffectPlugin*> plugs = tth::core().getImageEffectPluginCache().getPlugins();
00398 
00399                 unsigned int founded;
00400                 BOOST_FOREACH( const std::string& plugin, plugins )
00401                 {
00402                         std::vector< std::string > termsPlugin;
00403                         bal::split( termsPlugin, plugin, bal::is_any_of("."));
00404 
00405                         for( std::size_t i=0; i<plugs.size(); i++ )
00406                         {
00407                                 founded = 0;
00408                                 for( std::size_t t=0; t<termsPlugin.size(); t++ )
00409                                 {
00410                                         std::size_t found1 = plugs.at(i)->getRawIdentifier().find( "."+termsPlugin.at(t) );
00411                                         std::size_t found2 = plugs.at(i)->getRawIdentifier().find( termsPlugin.at(t)+"." );
00412                                         if( ( found1 == std::string::npos ) && ( found2 == std::string::npos ) )
00413                                         {
00414                                                 break;
00415                                         }
00416                                         ++founded;
00417                                         if( founded == termsPlugin.size() )
00418                                         {
00419                                                 /*TUTTLE_LOG_TRACE("plug is " << plugs.at(i)->getRawIdentifier() );*/
00420                                                 foundPlugins.push_back( plugs.at(i)->getRawIdentifier() );
00421                                         }
00422                                 }
00423                         }
00424                 }
00425 
00426                 TUTTLE_LOG_INFO( color->_red << "################################################################################" << color->_std );
00427 
00428                 BOOST_FOREACH( const std::string& plugin, foundPlugins )
00429                 {
00430                         TUTTLE_LOG_INFO(color->_blue << "PLUGIN DESCRIPTION" << color->_std );
00431                         getPluginProperties( plugin );
00432                         TUTTLE_LOG_INFO( color->_red << "################################################################################" << color->_std );
00433                 }
00434         }
00435         catch( ... )
00436         {
00437                 TUTTLE_LOG_ERROR( color->_red << boost::current_exception_diagnostic_information() << color->_std );
00438         }
00439 
00440         return 0;
00441 }
00442