00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <snx/snxConfig.h>
00043
00044 #include <iostream>
00045 #include <fstream>
00046 #include <string>
00047
00048 #include <boost/filesystem/exception.hpp>
00049 #include <boost/filesystem/operations.hpp>
00050
00051 #include <vpr/vpr.h>
00052 #include <vpr/System.h>
00053 #include <vpr/Util/FileUtils.h>
00054 #include <vpr/DynLoad/LibraryFinder.h>
00055
00056 #include <snx/Util/Debug.h>
00057 #include "snx/ISoundImplementation.h"
00058 #include "snx/StubSoundImplementation.h"
00059
00060 #include "snx/SoundFactory.h"
00061
00062
00063 namespace snx
00064 {
00065
00070 typedef snx::ISoundImplementation* (*newPluginFunc)(void);
00071
00076 typedef char* (*getNameFunc)(void);
00077
00082 typedef char* (*getVersionFunc)(void);
00083
00084 vprSingletonImp(SoundFactory);
00085
00086 SoundFactory::SoundFactory()
00087 {
00088 std::vector<std::string> search_paths;
00089
00090 const std::string envvar("SNX_BASE_DIR");
00091 std::string dummy_result;
00092
00093 if ( vpr::System::getenv(envvar, dummy_result).failure() )
00094 {
00095 vprDEBUG(snxDBG, vprDBG_WARNING_LVL)
00096 << clrOutBOLD(clrYELLOW, "WARNING:")
00097 << " SNX_BASE_DIR environment variable not set!\n" << vprDEBUG_FLUSH;
00098 vprDEBUG_NEXT(snxDBG, vprDBG_WARNING_LVL)
00099 << "Sonix plug-in loading may fail.\n" << vprDEBUG_FLUSH;
00100 }
00101
00102 #if defined(_ABIN32)
00103 std::string snx_lib_dir("${SNX_BASE_DIR}/lib32/snx/plugins");
00104 #elif defined(_ABI64)
00105 std::string snx_lib_dir("${SNX_BASE_DIR}/lib64/snx/plugins");
00106 #else
00107 std::string snx_lib_dir("${SNX_BASE_DIR}/lib/snx/plugins");
00108 #endif
00109
00110 #ifdef SNX_DEBUG
00111 snx_lib_dir += std::string("/dbg");
00112 #else
00113 snx_lib_dir += std::string("/opt");
00114 #endif
00115
00116 #if defined(VPR_OS_Win32)
00117 const std::string driver_ext("dll");
00118 #elif defined(VPR_OS_Darwin)
00119 const std::string driver_ext("dylib");
00120 #else
00121 const std::string driver_ext("so");
00122 #endif
00123
00124 search_paths.push_back(snx_lib_dir);
00125 search_paths.push_back( "${HOME}/.sonix/plugins" );
00126
00127 for (unsigned int x = 0; x < search_paths.size(); ++x)
00128 {
00129 search_paths[x] = vpr::replaceEnvVars(search_paths[x]);
00130 vprDEBUG(snxDBG, vprDBG_CONFIG_LVL) << "Finding plugins in "
00131 << search_paths[x] << std::endl
00132 << vprDEBUG_FLUSH;
00133
00134 try
00135 {
00136 boost::filesystem::path dirPath(search_paths[x], boost::filesystem::native);
00137 if (boost::filesystem::exists(dirPath))
00138 {
00139 vpr::LibraryFinder finder(search_paths[x], driver_ext);
00140 vpr::LibraryFinder::LibraryList libs = finder.getLibraries();
00141 this->loadPlugins( libs );
00142
00143 #ifdef SNX_DEBUG
00144 vprDEBUG(snxDBG, vprDBG_CONFIG_LVL) << "filelist:\n"
00145 << vprDEBUG_FLUSH;
00146 for ( unsigned int i = 0; i < libs.size(); ++i )
00147 {
00148 vprDEBUG(snxDBG, vprDBG_CONFIG_LVL) << "\t" << libs[i]
00149 << std::endl
00150 << vprDEBUG_FLUSH;
00151 }
00152 #endif
00153 }
00154 else
00155 {
00156 vprDEBUG(snxDBG, vprDBG_STATE_LVL)
00157 << "The directory does not exist: '" << search_paths[x] << "'\n"
00158 << vprDEBUG_FLUSH;
00159 }
00160 }
00161 catch (boost::filesystem::filesystem_error& fsEx)
00162 {
00163 vprDEBUG(snxDBG, vprDBG_CRITICAL_LVL)
00164 << clrOutNORM(clrRED, "ERROR:")
00165 << " File system exception caught: " << fsEx.what() << std::endl
00166 << vprDEBUG_FLUSH;
00167 }
00168 }
00169 }
00170
00171 void SoundFactory::errorOutput(vpr::LibraryPtr lib, const char* test)
00172 {
00173 vprDEBUG(snxDBG, vprDBG_WARNING_LVL)
00174 << "ERROR: Plugin '" << lib->getName() << "' does not export symbol '"
00175 << test << "'\n" << vprDEBUG_FLUSH;
00176 }
00177
00178 bool SoundFactory::isPlugin(vpr::LibraryPtr lib)
00179 {
00180 if (lib->findSymbol( "newPlugin" ) == NULL)
00181 {
00182 errorOutput(lib, "newPlugin");
00183 return false;
00184 }
00185 if (lib->findSymbol( "getVersion" ) == NULL)
00186 {
00187 errorOutput(lib, "getVersion");
00188 return false;
00189 }
00190 if (lib->findSymbol( "getName" ) == NULL)
00191 {
00192 errorOutput(lib, "getName");
00193 return false;
00194 }
00195
00196
00197
00198
00199 vprDEBUG(snxDBG, vprDBG_CONFIG_STATUS_LVL) << "Plugin '" << lib->getName()
00200 << "' is a valid Sonix plugin.\n"
00201 << vprDEBUG_FLUSH;
00202 return true;
00203 }
00204
00205 void SoundFactory::loadPlugins( vpr::LibraryFinder::LibraryList libs )
00206 {
00207 for (unsigned int x = 0; x < libs.size(); ++x)
00208 {
00209
00210 vpr::ReturnStatus didLoad = libs[x]->load();
00211
00212 if (didLoad == vpr::ReturnStatus::Succeed)
00213 {
00214
00215 if ( this->isPlugin(libs[x]) )
00216 {
00217
00218 getNameFunc getName = (getNameFunc)libs[x]->findSymbol( "getName" );
00219 std::string name;
00220 if (getName != NULL)
00221 {
00222 name = getName();
00223
00224
00225 int pluginsWithName = mRegisteredImplementations.count(name);
00226 if ( pluginsWithName < 1 )
00227 {
00228
00229 mPlugins.push_back(libs[x]);
00230
00231 vprDEBUG(snxDBG, vprDBG_STATE_LVL)
00232 << "Got plug-in '" << name << "'--registering\n"
00233 << vprDEBUG_FLUSH;
00234
00235
00236 newPluginFunc newPlugin = (newPluginFunc)libs[x]->findSymbol( "newPlugin" );
00237 ISoundImplementation* si = NULL;
00238 if (newPlugin != NULL)
00239 {
00240 si = newPlugin();
00241 if (NULL != si)
00242 {
00243 this->reg( name, si );
00244 }
00245 }
00246 }
00247 else
00248 {
00249
00250 libs[x]->unload();
00251 }
00252 }
00253 }
00254 }
00255 else
00256 {
00257
00258 vprDEBUG(snxDBG, vprDBG_WARNING_LVL)
00259 << "ERROR: Plugin '" << libs[x]->getName() << "' Failed to load\n" << vprDEBUG_FLUSH;
00260 }
00261 }
00262 }
00263
00264 void SoundFactory::unloadPlugins()
00265 {
00266 for (unsigned int x = 0; x < mPlugins.size(); ++x)
00267 {
00268
00269 getNameFunc getName = (getNameFunc)mPlugins[x]->findSymbol( "getName" );
00270 std::string name;
00271 ISoundImplementation* impl = NULL;
00272 if (getName != NULL)
00273 {
00274 name = getName();
00275 impl = mRegisteredImplementations[name];
00276
00277
00278 this->reg( name, NULL );
00279 }
00280
00281
00282 if ( NULL != impl )
00283 {
00284 delete impl;
00285 }
00286
00287
00288 mPlugins[x]->unload();
00289 }
00290 mPlugins.clear();
00291 }
00292
00293 void SoundFactory::reg(const std::string& apiName,
00294 snx::ISoundImplementation* impl)
00295 {
00296 if (impl != NULL)
00297 {
00298 vprDEBUG(snxDBG, vprDBG_CONFIG_LVL)
00299 << "NOTICE: Registering sound API '" << apiName << "'\n"
00300 << vprDEBUG_FLUSH;
00301
00302 impl->setName( apiName );
00303 mRegisteredImplementations[apiName] = impl;
00304 }
00305 else
00306 {
00307 mRegisteredImplementations.erase( apiName );
00308
00309 vprDEBUG(snxDBG, vprDBG_CONFIG_LVL)
00310 << "NOTICE: Unregistered sound API '" << apiName << "'\n"
00311 << vprDEBUG_FLUSH;
00312 }
00313 }
00314
00321 void SoundFactory::createImplementation( const std::string& apiName,
00322 snx::ISoundImplementation* &mImplementation )
00323 {
00324 if (mRegisteredImplementations.count( apiName ) > 0)
00325 {
00326 mRegisteredImplementations[apiName]->clone( mImplementation );
00327 }
00328
00329 else
00330 {
00331 mImplementation = new snx::StubSoundImplementation;
00332 }
00333
00334
00335 }
00336
00337 }