TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/io.cpp
Go to the documentation of this file.
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 }