diff --git a/src/plug-in/Makefile.am b/src/plug-in/Makefile.am index 9f31ec25aec6b78929e9710cd0bdd2711331b299..bd27f29a4ca093adb9eab042381127341503f2b3 100644 --- a/src/plug-in/Makefile.am +++ b/src/plug-in/Makefile.am @@ -5,5 +5,6 @@ noinst_LTLIBRARIES = libplugin.la SUBDIRS=test libplugin_la_SOURCES = \ - pluginmanager.cpp + pluginmanager.cpp \ + plugin.cpp diff --git a/src/plug-in/plugin.cpp b/src/plug-in/plugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..deaf1a4818fbe8a01a720b0b856c36f1ac33a277 --- /dev/null +++ b/src/plug-in/plugin.cpp @@ -0,0 +1,15 @@ +#include "plugin.h" + +::sflphone::Plugin::Plugin (void *handle, PluginInterface *interface) + :_handlePtr(handle), _interface(interface) +{ +} + +::sflphone::Plugin::Plugin (PluginInterface *interface) + :_interface(interface) +{ +} + +::sflphone::Plugin::~Plugin () +{ +} diff --git a/src/plug-in/plugin.h b/src/plug-in/plugin.h new file mode 100644 index 0000000000000000000000000000000000000000..fe548361eb1098e566ffacf00cb58d61ba31a236 --- /dev/null +++ b/src/plug-in/plugin.h @@ -0,0 +1,32 @@ +#ifndef PLUGIN_H +#define PLUGIN_H + +#include "plugininterface.h" + +namespace sflphone { + + class PluginInterface; + + class Plugin { + + public: + + Plugin (void*, PluginInterface *interface); + Plugin (PluginInterface *interface); + + ~Plugin (); + + void setName (std::string name); + private: + std::string _name; + int _version_major; + int _version_minor; + int _required; + void *_handlePtr; + PluginInterface *_interface; + + friend class PluginTest; + friend class PluginManager; + }; +} +#endif //PLUGIN_H diff --git a/src/plug-in/plugin_api.h b/src/plug-in/plugin_api.h deleted file mode 100644 index 72221545920fea833a7480b3427ccc080016681c..0000000000000000000000000000000000000000 --- a/src/plug-in/plugin_api.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef PLUGIN_H -#define PLUGIN_H - -#include <string> - -#include "global.h" - -/* - * @file plugin.h - * @brief Define a plugin object - */ - -#ifdef __cplusplus -extern "C" { -#endif - - namespace sflphone { - - class PluginManager; - - class Plugin { - - public: - Plugin( const std::string &name ){ - _name = name; - } - - virtual ~Plugin() {} - - public: - /** - * Return the minimal core version required so that the plugin could work - * @return int The version required - */ - virtual int getCoreVersion() const = 0; - - private: - Plugin &operator =(const Plugin &plugin); - - std::string _name; - }; - - typedef Plugin* createFunc( void* ); - - typedef void destroyFunc( Plugin* ); - - } - -#ifdef __cplusplus -} -#endif - -#endif //PLUGIN_H - diff --git a/src/plug-in/plugininterface.h b/src/plug-in/plugininterface.h new file mode 100644 index 0000000000000000000000000000000000000000..1bfad23e2fc2219a5a8211b03b52a2a51bad9742 --- /dev/null +++ b/src/plug-in/plugininterface.h @@ -0,0 +1,51 @@ +#ifndef PLUGIN_INTERFACE_H +#define PLUGIN_INTERFACE_H + +#include <string> +#include "global.h" + +#include "plugin.h" + +/* + * @file plugininterface.h + * @brief Define a plugin object + */ + +namespace sflphone { + + class PluginManager; + class Plugin; + + class PluginInterface { + + public: + PluginInterface( const std::string &name ){ + _name = name; + } + + virtual ~PluginInterface() {} + + inline std::string getInterfaceName (void) { return _name; } + + /** + * Return the minimal core version required so that the plugin could work + * @return int The version required + */ + virtual int initFunc () = 0; + + virtual int registerFunc (Plugin **plugin) = 0; + + private: + PluginInterface &operator =(const PluginInterface &plugin); + + std::string _name; + }; + + typedef PluginInterface* createFunc (void); + + typedef void destroyFunc( PluginInterface* ); + +} + +#endif //PLUGIN_INTERFACE_H + diff --git a/src/plug-in/pluginmanager.cpp b/src/plug-in/pluginmanager.cpp index 54f757216e12a79c356ab8464259a3b837a12541..f8135f57806590ea3c32f5c304f3de3be8814896 100644 --- a/src/plug-in/pluginmanager.cpp +++ b/src/plug-in/pluginmanager.cpp @@ -3,7 +3,19 @@ #include "pluginmanager.h" -::sflphone::PluginManager::PluginManager():_loadedPlugins() +::sflphone::PluginManager* ::sflphone::PluginManager::_instance = 0; + + ::sflphone::PluginManager* +::sflphone::PluginManager::instance() +{ + if(!_instance){ + return new PluginManager(); + } + return _instance; +} + +::sflphone::PluginManager::PluginManager() + :_loadedPlugins() { _instance = this; } @@ -13,13 +25,16 @@ _instance = 0; } -int ::sflphone::PluginManager::loadPlugins( const std::string &path ) + int +::sflphone::PluginManager::loadPlugins (const std::string &path) { std::string pluginDir, current; - ::sflphone::Plugin *plugin; + ::sflphone::PluginInterface *interface; DIR *dir; dirent *dirStruct; int result=0; + void *handle; + createFunc* createPlugin; const std::string pDir = ".."; const std::string cDir = "."; @@ -37,18 +52,31 @@ int ::sflphone::PluginManager::loadPlugins( const std::string &path ) current = dirStruct->d_name; /* Test if the current item is not the parent or the current directory */ if( current != pDir && current != cDir ){ - loadDynamicLibrary( current ); - result++; - } + handle = loadDynamicLibrary( pluginDir + current ); + + if(instanciatePlugin (handle, &interface) != 0) + { + _debug("Error instanciating the plugin ...\n"); + return 1; + } + + if(registerPlugin (handle, interface) != 0) + _debug("Error registering the plugin ...\n"); + return 1; + } } } + else + return 1; + /* Close the directory */ closedir( dir ); - return result; + return 0; } -::sflphone::PluginWrap* ::sflphone::PluginManager::isPluginLoaded( const std::string &name ) + ::sflphone::Plugin* +::sflphone::PluginManager::isPluginLoaded (const std::string &name) { if(_loadedPlugins.empty()) return NULL; @@ -68,31 +96,68 @@ int ::sflphone::PluginManager::loadPlugins( const std::string &path ) return NULL; } -void* ::sflphone::PluginManager::loadDynamicLibrary( const std::string& filename ) { + + void* +::sflphone::PluginManager::loadDynamicLibrary (const std::string& filename) +{ void *pluginHandlePtr = NULL; const char *error; _debug("Loading dynamic library %s\n", filename.c_str()); -#if defined(Q_OS_UNIX) /* Load the library */ pluginHandlePtr = dlopen( filename.c_str(), RTLD_LAZY ); if( !pluginHandlePtr ) { error = dlerror(); _debug("Error while opening plug-in: %s\n", error); + return NULL; } dlerror(); -#endif - return pluginHandlePtr; + } -void ::sflphone::PluginManager::unloadDynamicLibrary( void * pluginHandlePtr ) { + int +::sflphone::PluginManager::instanciatePlugin (void *handlePtr, ::sflphone::PluginInterface **plugin) +{ + createFunc *createPlugin; + + createPlugin = (createFunc*)dlsym(handlePtr, "create"); + if( dlerror() ) + { + _debug("Error creating the plugin: %s\n", dlerror()); + return 1; + } + *plugin = createPlugin(); + return 0; +} + + int +::sflphone::PluginManager::registerPlugin (void *handlePtr, PluginInterface *interface) +{ + Plugin *myplugin; + std::string name; + + if( !( handlePtr && interface!=0 ) ) + return 1; + /* Fetch information from the loaded plugin interface */ + if(interface->registerFunc (&myplugin) != 0) + return 1; + /* Creation of the plugin wrapper */ + myplugin = new Plugin (handlePtr, interface); + + /* Add the data in the loaded plugin map */ + _loadedPlugins[ myplugin->_name ] = myplugin; + return 0; +} + + void +::sflphone::PluginManager::unloadDynamicLibrary (void * pluginHandlePtr) +{ dlclose( pluginHandlePtr ); dlerror(); } -::sflphone::PluginManager* ::sflphone::PluginManager::_instance = 0; diff --git a/src/plug-in/pluginmanager.h b/src/plug-in/pluginmanager.h index 5330b8764fd0cb080e13937d69a7041d247074f8..671834369da67dc151cd24e8ab9ca62a0261d6c1 100644 --- a/src/plug-in/pluginmanager.h +++ b/src/plug-in/pluginmanager.h @@ -6,77 +6,71 @@ * @brief Base class of the plugin manager */ -#include "plugin_api.h" +#include "plugininterface.h" #include "global.h" #include <map> #include <string> - namespace sflphone { - typedef struct { - Plugin *plugin; - createFunc *create_func; - destroyFunc *destroy_func; - std::string name; - } PluginWrap; - - class PluginManager { + public: - /** - * Default constructor - */ - PluginManager(); - - /** - * Destructor - */ - ~PluginManager(); - - /** - * Returns the unique instance of the plugin manager - */ - static PluginManager* instance(); - - /** - * Load all the plugins found in a specific directory - * @param path The absolute path to the directory - * @return int The number of items loaded - */ - int loadPlugins( const std::string &path = "" ); - - /** - * Check if a plugin has been already loaded - * @param name The name of the plugin looked for - * @return Plugin* The pointer on the plugin or NULL if not found - */ - PluginWrap* isPluginLoaded( const std::string &name ); - - int initPlugins( void ); + /** + * Destructor + */ + ~PluginManager(); + + /** + * Returns the unique instance of the plugin manager + */ + static PluginManager* instance(); + + /** + * Load all the plugins found in a specific directory + * @param path The absolute path to the directory + * @return int The number of items loaded + */ + int loadPlugins( const std::string &path = "" ); + + int instanciatePlugin( void *handlePtr, PluginInterface** plugin ); + + /** + * Check if a plugin has been already loaded + * @param name The name of the plugin looked for + * @return Plugin* The pointer on the plugin or NULL if not found + */ + Plugin* isPluginLoaded( const std::string &name ); + + int registerPlugin (void *handle, PluginInterface *interface); private: - /** - * Load a unix dynamic/shared library - * @param filename The path to the dynamic/shared library - * @return void* A pointer on it - */ - void * loadDynamicLibrary( const std::string &filename ); - - /** - * Unload a unix dynamic/shared library - * @param pluginHandleptr The pointer on the loaded plugin - */ - void unloadDynamicLibrary( void * pluginHandlePtr ); - - /* Map of plugins associated by their string name */ - typedef std::map<std::string, ::sflphone::PluginWrap*> pluginMap; - pluginMap _loadedPlugins; - - /* The unique static instance */ - static PluginManager* _instance; + /** + * Default constructor + */ + PluginManager(); + + /** + * Load a unix dynamic/shared library + * @param filename The path to the dynamic/shared library + * @return void* A pointer on it + */ + void * loadDynamicLibrary( const std::string &filename ); + + /** + * Unload a unix dynamic/shared library + * @param pluginHandleptr The pointer on the loaded plugin + */ + void unloadDynamicLibrary( void * pluginHandlePtr ); + + /* Map of plugins associated by their string name */ + typedef std::map<std::string, Plugin*> pluginMap; + pluginMap _loadedPlugins; + + /* The unique static instance */ + static PluginManager* _instance; }; } diff --git a/src/plug-in/test/pluginTest.cpp b/src/plug-in/test/pluginTest.cpp index 6249a886fae85e2028f3f105b32c6fbfd95d59e8..5e5f7cff111582bf0d88a31c624c32ee17d27027 100644 --- a/src/plug-in/test/pluginTest.cpp +++ b/src/plug-in/test/pluginTest.cpp @@ -1,22 +1,39 @@ -#include "../plugin_api.h" +#include "../plugininterface.h" namespace sflphone { - class PluginTest : public Plugin { + class PluginTest : public PluginInterface { + public: - PluginTest( const std::string &name ):Plugin( name ){ + PluginTest( const std::string &name ):PluginInterface( name ){ } - virtual int getCoreVersion() const{ - return 1; + virtual int initFunc (void) + { + return 0; + } + + virtual int registerFunc (Plugin **plugin) + { + Plugin *ret; + + ret = new Plugin(this); + + ret->_name = getInterfaceName(); + ret->_required = 1; + ret->_version_major=1; + ret->_version_minor=0; + + *plugin = ret; + return 0; } }; } -extern "C" ::sflphone::Plugin* create_t( void * ){ +extern "C" ::sflphone::PluginInterface* create (void){ return new ::sflphone::PluginTest("test"); } -extern "C" void* destroy_t( ::sflphone::Plugin *p ){ +extern "C" void* destroy( ::sflphone::PluginInterface *p ){ delete p; } diff --git a/test/Makefile.am b/test/Makefile.am index 86e70dbc38e76a6fda92b43be969afd51e260781..652556ffb56c2d9e1fb10cc8548099a9bcd78436 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -15,7 +15,6 @@ OBJECT_FILES= \ ../src/sflphoned-sipaccount.o \ ../src/sflphoned-iaxaccount.o \ ../src/sflphoned-eventthread.o \ - ../src/sflphoned-useragent.o \ ../src/plug-in/pluginmanager.o \ ../src/sflphoned-samplerateconverter.o diff --git a/test/pluginmanagerTest.cpp b/test/pluginmanagerTest.cpp index b9a3d413a400d422a7510963d36124ba1d026e14..ed3f4d7e281634803ac1c506c286899eb839214f 100644 --- a/test/pluginmanagerTest.cpp +++ b/test/pluginmanagerTest.cpp @@ -26,19 +26,26 @@ using std::cout; using std::endl; void PluginManagerTest::setUp(){ - // Instanciate the plugin manager object - _pm = new ::sflphone::PluginManager(); + // Instanciate the plugin manager singleton + _pm = ::sflphone::PluginManager::instance(); } void PluginManagerTest::testLoadPluginDirectory(){ - _pm->loadPlugins(); + CPPUNIT_ASSERT(_pm->loadPlugins() == 0); +} + +void PluginManagerTest::testLoadPlugin(){ + CPPUNIT_ASSERT(_pm->loadPlugins() == 0); + //CPPUNIT_ASSERT( _pm->isPluginLoaded("test") == NULL ); } -void PluginManagerTest::testNonloadedPlugin(){ - CPPUNIT_ASSERT( _pm->isPluginLoaded("test") == NULL ); +void PluginManagerTest::testRegisterPlugin(){ + // First load the default directory + _pm->loadPlugins(); + // Resolve the symbol } void PluginManagerTest::tearDown(){ // Delete the plugin manager object - delete _pm; _pm=NULL; + delete _pm; _pm=0; } diff --git a/test/pluginmanagerTest.h b/test/pluginmanagerTest.h index e43ba8f7ab09262243fddd3edc21130ddca5dd80..0cd92da42ce87ff50b2eb399975a68da9abd2f4f 100644 --- a/test/pluginmanagerTest.h +++ b/test/pluginmanagerTest.h @@ -43,7 +43,8 @@ class PluginManagerTest : public CppUnit::TestCase { */ CPPUNIT_TEST_SUITE( PluginManagerTest ); CPPUNIT_TEST( testLoadPluginDirectory ); - CPPUNIT_TEST( testNonloadedPlugin ); + CPPUNIT_TEST( testLoadPlugin ); + CPPUNIT_TEST( testRegisterPlugin ); CPPUNIT_TEST_SUITE_END(); public: @@ -63,7 +64,9 @@ class PluginManagerTest : public CppUnit::TestCase { void testLoadPluginDirectory(); - void testNonloadedPlugin(); + void testLoadPlugin(); + + void testRegisterPlugin(); private: ::sflphone::PluginManager *_pm;