TuttleOFX
1
|
00001 #include "io.hpp" 00002 00003 #include <tuttle/host/Graph.hpp> 00004 #include <tuttle/host/Core.hpp> 00005 #include <tuttle/host/ofx/OfxhImageEffectPlugin.hpp> 00006 #include <tuttle/host/ofx/OfxhImageEffectPluginCache.hpp> 00007 #include <tuttle/host/ofx/OfxhImageEffectNode.hpp> 00008 00009 #include <boost/algorithm/string.hpp> 00010 #include <boost/algorithm/string/predicate.hpp> 00011 #include <boost/algorithm/string/join.hpp> 00012 #include <boost/foreach.hpp> 00013 #include <boost/filesystem.hpp> 00014 #include <boost/tuple/tuple.hpp> 00015 #include <boost/tuple/tuple_comparison.hpp> 00016 00017 #include <algorithm> 00018 #include <exception> 00019 #include <stdexcept> 00020 00021 namespace tuttle { 00022 namespace host { 00023 namespace io { 00024 00025 typedef boost::tuples::tuple< double, int, std::string > Tuple; 00026 00027 std::vector< std::string > getIOPluginsForExtension( const std::string& extension, const std::string& context ) 00028 { 00029 std::vector< Tuple > tupleArray; 00030 00031 // Normalize the input extension, so the searchExtension should be something like "jpg". 00032 std::string searchExtension; 00033 if( ! boost::starts_with( extension, "." ) ) 00034 { 00035 searchExtension = extension; 00036 } 00037 else 00038 { 00039 searchExtension = extension.substr( 1, extension.size() - 1 ); 00040 } 00041 boost::algorithm::to_lower(searchExtension); 00042 00043 // get array of tuple( evaluation, supportedExtensions, nodeIdentifier ) 00044 ofx::imageEffect::OfxhImageEffectPluginCache::MapPluginsByID nodeMap = core().getImageEffectPluginCache().getPluginsByID(); 00045 BOOST_FOREACH( const ofx::imageEffect::OfxhImageEffectPluginCache::MapPluginsByID::value_type& node, nodeMap ) 00046 { 00047 try 00048 { 00049 node.second->loadAndDescribeActions(); 00050 const ofx::imageEffect::OfxhImageEffectNodeDescriptor& desc = node.second->getDescriptor(); 00051 if( node.second->supportsContext( context ) ) 00052 { 00053 double evaluation = desc.getProperties().getDoubleProperty( "TuttleOfxImageEffectPropEvaluation" ); 00054 int supportedExtensionsSize = desc.getProperties().fetchStringProperty( "TuttleOfxImageEffectPropSupportedExtensions" ).getDimension(); 00055 const std::vector< std::string > supportedExtensions = desc.getProperties().fetchStringProperty( "TuttleOfxImageEffectPropSupportedExtensions" ).getValues(); 00056 00057 for( size_t indexExtension = 0; indexExtension < supportedExtensions.size(); ++indexExtension ) 00058 { 00059 if( supportedExtensions.at( indexExtension ) == searchExtension ) 00060 { 00061 Tuple tuple( -evaluation, supportedExtensionsSize, node.second->getRawIdentifier() ); 00062 tupleArray.push_back( tuple ); 00063 break; 00064 } 00065 } 00066 } 00067 } 00068 catch( std::exception& e ) 00069 { 00070 // Ignore the exception. 00071 } 00072 } 00073 00074 // get nodeIdentifier of the plugin with the best evaluation 00075 std::sort( tupleArray.begin(), tupleArray.end() ); 00076 00077 std::vector< std::string > results; 00078 for( size_t indexTuple = 0; indexTuple < tupleArray.size(); ++indexTuple ) 00079 { 00080 results.push_back( tupleArray.at( indexTuple ).get<2>() ); 00081 } 00082 return results; 00083 } 00084 00085 std::string getFileExtension( const std::string& filename ) 00086 { 00087 size_t pos = filename.find_last_of( "." ); 00088 if( pos == std::string::npos ) 00089 { 00090 #ifdef _WIN32 00091 const std::string os_pathsep( ";" ); 00092 #else 00093 const std::string os_pathsep( ":" ); 00094 #endif 00095 if( filename.find( os_pathsep ) != std::string::npos ) 00096 { 00097 BOOST_THROW_EXCEPTION( exception::File( filename ) 00098 << exception::user() + "Filename has no extension \"" + filename + "\"." 00099 << exception::dev() + "Filename has no extension \"" + filename + "\"." ); 00100 } 00101 return filename; 00102 } 00103 return filename.substr( pos ); 00104 } 00105 00106 std::vector< std::string > _getReaders( const std::string& extension ) 00107 { 00108 const char* context = "OfxImageEffectContextReader"; 00109 return getIOPluginsForExtension( extension, std::string( context ) ); 00110 } 00111 00112 std::vector< std::string > getReaders( const std::string& filename ) 00113 { 00114 return _getReaders( getFileExtension( filename ) ); 00115 } 00116 00117 std::string getBestReader( const std::string& filename ) 00118 { 00119 const std::string extension = getFileExtension( filename ); 00120 00121 if( ! boost::filesystem::exists( filename ) ) 00122 { 00123 std::vector< std::string > results = _getReaders( extension ); 00124 if( results.size() == 0 ) 00125 { 00126 BOOST_THROW_EXCEPTION( exception::File( filename ) 00127 << exception::user() + "Unknown file extension \"" + extension + "\"." 00128 << exception::dev() + "Unknown file extension \"" + extension + "\"." ); 00129 } 00130 return results[0]; 00131 } 00132 else 00133 { 00134 std::vector< std::string > results = _getReaders( extension ); 00135 BOOST_FOREACH( const std::string readerId, results ) 00136 { 00137 try 00138 { 00139 Graph graph; 00140 ImageEffectNode& readerIn = graph.createNode(readerId).asImageEffectNode(); 00141 readerIn.getParam("filename").setValue( filename ); 00142 graph.setup(); 00143 OfxRangeD timeRange = readerIn.getTimeDomain(); 00144 graph.setupAtTime( timeRange.min ); 00145 readerIn.getRegionOfDefinition( timeRange.min ); 00146 return readerId; 00147 } 00148 catch( std::exception& e ) 00149 { 00150 // Ignore the exception, if we can't load this file with this reader plugin, 00151 // we will try with the other ones. 00152 } 00153 } 00154 BOOST_THROW_EXCEPTION( exception::File( filename ) 00155 << exception::user() + "Can't read image \"" + filename + "\"." 00156 << exception::dev() + "File is not supported. We have tried to load it with: " + boost::algorithm::join(results, ", ") ); 00157 } 00158 BOOST_THROW_EXCEPTION( exception::Bug() ); 00159 } 00160 00161 std::vector< std::string > _getWriters( const std::string& extension ) 00162 { 00163 const char* context = "OfxImageEffectContextWriter"; 00164 return getIOPluginsForExtension( extension, std::string( context ) ); 00165 } 00166 00167 std::vector< std::string > getWriters( const std::string& filename ) 00168 { 00169 return _getWriters( getFileExtension( filename ) ); 00170 } 00171 00172 std::string getBestWriter( const std::string& filename ) 00173 { 00174 std::string extension = getFileExtension( filename ); 00175 00176 std::vector< std::string > results = _getWriters( extension ); 00177 if( results.size() == 0 ) 00178 { 00179 BOOST_THROW_EXCEPTION( exception::File( filename ) 00180 << exception::user() + "Unknown file extension \"" + extension + "\"." 00181 << exception::dev() + "Unknown file extension \"" + extension + "\"." ); 00182 } 00183 return results[0]; 00184 } 00185 00186 } 00187 } 00188 }