Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

SoundFactory.cpp

Go to the documentation of this file.
00001 /****************** <SNX heading BEGIN do not edit this line> *****************
00002  *
00003  * sonix
00004  *
00005  * Original Authors:
00006  *   Kevin Meinert
00007  *
00008  * -----------------------------------------------------------------
00009  * File:          $RCSfile: SoundFactory.cpp,v $
00010  * Date modified: $Date: 2004/03/15 17:31:16 $
00011  * Version:       $Revision: 1.24 $
00012  * -----------------------------------------------------------------
00013  *
00014  ****************** <SNX heading END do not edit this line> ******************/
00015 
00016 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00017  *
00018  * VR Juggler is (C) Copyright 1998-2003 by Iowa State University
00019  *
00020  * Original Authors:
00021  *   Allen Bierbaum, Christopher Just,
00022  *   Patrick Hartling, Kevin Meinert,
00023  *   Carolina Cruz-Neira, Albert Baker
00024  *
00025  * This library is free software; you can redistribute it and/or
00026  * modify it under the terms of the GNU Library General Public
00027  * License as published by the Free Software Foundation; either
00028  * version 2 of the License, or (at your option) any later version.
00029  *
00030  * This library is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00033  * Library General Public License for more details.
00034  *
00035  * You should have received a copy of the GNU Library General Public
00036  * License along with this library; if not, write to the
00037  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00038  * Boston, MA 02111-1307, USA.
00039  *
00040  *************** <auto-copyright.pl END do not edit this line> ***************/
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" // in case lookup fails...
00059 
00060 #include "snx/SoundFactory.h" // my header.
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    // @todo give sonix an internal version number string!
00197    //getVersionFunc getVersion = (getVersionFunc)lib.lookup( "getVersion" );
00198    //if (getVersion != NULL && getVersion() != snx::version) return false;
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       // open the library
00210       vpr::ReturnStatus didLoad = libs[x]->load();
00211 
00212       if (didLoad == vpr::ReturnStatus::Succeed)
00213       {
00214         //If the plug-in implements the nessiasry interface
00215         if ( this->isPlugin(libs[x]) )
00216         {
00217             // get the name..
00218             getNameFunc getName = (getNameFunc)libs[x]->findSymbol( "getName" );
00219             std::string name;
00220             if (getName != NULL)
00221             {
00222                 name = getName();
00223 
00224                 // Check to see it plug-in is already registered
00225                 int pluginsWithName =  mRegisteredImplementations.count(name);
00226                 if ( pluginsWithName < 1 )
00227                 {
00228                     // Keep track of the plug-ins we actual use
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                     // create the implementation
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                     //Plug in was already registered so we can unload it
00250                     libs[x]->unload();
00251                 }
00252             }
00253         }
00254       }
00255       else
00256       {
00257         //Lib failed to load
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       // get the name..
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          // unreg it.
00278          this->reg( name, NULL );
00279       }
00280 
00281       // delete the memory using the delete func that comes with the library...
00282       if ( NULL != impl )
00283       {
00284          delete impl;
00285       }
00286 
00287       // close the library
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    //mImplementation->setName( apiName );
00335 }
00336 
00337 } // end namespace

Generated on Sun May 2 14:39:26 2004 for Juggler Sonix by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002