Skip to content
Snippets Groups Projects
Commit f6d2fbf1 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

Make the plugins registering against the plugin manager

parent 4f509b09
No related branches found
No related tags found
No related merge requests found
...@@ -5,5 +5,6 @@ noinst_LTLIBRARIES = libplugin.la ...@@ -5,5 +5,6 @@ noinst_LTLIBRARIES = libplugin.la
SUBDIRS=test SUBDIRS=test
libplugin_la_SOURCES = \ libplugin_la_SOURCES = \
pluginmanager.cpp pluginmanager.cpp \
plugin.cpp
#include "plugin.h"
::sflphone::Plugin::Plugin (void *handle, PluginInterface *interface)
:_handlePtr(handle), _interface(interface)
{
}
::sflphone::Plugin::Plugin (PluginInterface *interface)
:_interface(interface)
{
}
::sflphone::Plugin::~Plugin ()
{
}
#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
#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
#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
...@@ -3,7 +3,19 @@ ...@@ -3,7 +3,19 @@
#include "pluginmanager.h" #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; _instance = this;
} }
...@@ -13,13 +25,16 @@ ...@@ -13,13 +25,16 @@
_instance = 0; _instance = 0;
} }
int ::sflphone::PluginManager::loadPlugins( const std::string &path ) int
::sflphone::PluginManager::loadPlugins (const std::string &path)
{ {
std::string pluginDir, current; std::string pluginDir, current;
::sflphone::Plugin *plugin; ::sflphone::PluginInterface *interface;
DIR *dir; DIR *dir;
dirent *dirStruct; dirent *dirStruct;
int result=0; int result=0;
void *handle;
createFunc* createPlugin;
const std::string pDir = ".."; const std::string pDir = "..";
const std::string cDir = "."; const std::string cDir = ".";
...@@ -37,18 +52,31 @@ int ::sflphone::PluginManager::loadPlugins( const std::string &path ) ...@@ -37,18 +52,31 @@ int ::sflphone::PluginManager::loadPlugins( const std::string &path )
current = dirStruct->d_name; current = dirStruct->d_name;
/* Test if the current item is not the parent or the current directory */ /* Test if the current item is not the parent or the current directory */
if( current != pDir && current != cDir ){ if( current != pDir && current != cDir ){
loadDynamicLibrary( current ); handle = loadDynamicLibrary( pluginDir + current );
result++;
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 */ /* Close the directory */
closedir( dir ); 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; if(_loadedPlugins.empty()) return NULL;
...@@ -68,31 +96,68 @@ int ::sflphone::PluginManager::loadPlugins( const std::string &path ) ...@@ -68,31 +96,68 @@ int ::sflphone::PluginManager::loadPlugins( const std::string &path )
return NULL; return NULL;
} }
void* ::sflphone::PluginManager::loadDynamicLibrary( const std::string& filename ) {
void*
::sflphone::PluginManager::loadDynamicLibrary (const std::string& filename)
{
void *pluginHandlePtr = NULL; void *pluginHandlePtr = NULL;
const char *error; const char *error;
_debug("Loading dynamic library %s\n", filename.c_str()); _debug("Loading dynamic library %s\n", filename.c_str());
#if defined(Q_OS_UNIX)
/* Load the library */ /* Load the library */
pluginHandlePtr = dlopen( filename.c_str(), RTLD_LAZY ); pluginHandlePtr = dlopen( filename.c_str(), RTLD_LAZY );
if( !pluginHandlePtr ) { if( !pluginHandlePtr ) {
error = dlerror(); error = dlerror();
_debug("Error while opening plug-in: %s\n", error); _debug("Error while opening plug-in: %s\n", error);
return NULL;
} }
dlerror(); dlerror();
#endif
return pluginHandlePtr; return 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;
} }
void ::sflphone::PluginManager::unloadDynamicLibrary( void * pluginHandlePtr ) { 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 ); dlclose( pluginHandlePtr );
dlerror(); dlerror();
} }
::sflphone::PluginManager* ::sflphone::PluginManager::_instance = 0;
...@@ -6,31 +6,18 @@ ...@@ -6,31 +6,18 @@
* @brief Base class of the plugin manager * @brief Base class of the plugin manager
*/ */
#include "plugin_api.h" #include "plugininterface.h"
#include "global.h" #include "global.h"
#include <map> #include <map>
#include <string> #include <string>
namespace sflphone { namespace sflphone {
typedef struct {
Plugin *plugin;
createFunc *create_func;
destroyFunc *destroy_func;
std::string name;
} PluginWrap;
class PluginManager { class PluginManager {
public:
/**
* Default constructor
*/
PluginManager();
public:
/** /**
* Destructor * Destructor
*/ */
...@@ -48,16 +35,23 @@ namespace sflphone { ...@@ -48,16 +35,23 @@ namespace sflphone {
*/ */
int loadPlugins( const std::string &path = "" ); int loadPlugins( const std::string &path = "" );
int instanciatePlugin( void *handlePtr, PluginInterface** plugin );
/** /**
* Check if a plugin has been already loaded * Check if a plugin has been already loaded
* @param name The name of the plugin looked for * @param name The name of the plugin looked for
* @return Plugin* The pointer on the plugin or NULL if not found * @return Plugin* The pointer on the plugin or NULL if not found
*/ */
PluginWrap* isPluginLoaded( const std::string &name ); Plugin* isPluginLoaded( const std::string &name );
int initPlugins( void ); int registerPlugin (void *handle, PluginInterface *interface);
private: private:
/**
* Default constructor
*/
PluginManager();
/** /**
* Load a unix dynamic/shared library * Load a unix dynamic/shared library
* @param filename The path to the dynamic/shared library * @param filename The path to the dynamic/shared library
...@@ -72,7 +66,7 @@ namespace sflphone { ...@@ -72,7 +66,7 @@ namespace sflphone {
void unloadDynamicLibrary( void * pluginHandlePtr ); void unloadDynamicLibrary( void * pluginHandlePtr );
/* Map of plugins associated by their string name */ /* Map of plugins associated by their string name */
typedef std::map<std::string, ::sflphone::PluginWrap*> pluginMap; typedef std::map<std::string, Plugin*> pluginMap;
pluginMap _loadedPlugins; pluginMap _loadedPlugins;
/* The unique static instance */ /* The unique static instance */
......
#include "../plugin_api.h" #include "../plugininterface.h"
namespace sflphone { namespace sflphone {
class PluginTest : public Plugin { class PluginTest : public PluginInterface {
public: public:
PluginTest( const std::string &name ):Plugin( name ){ PluginTest( const std::string &name ):PluginInterface( name ){
}
virtual int initFunc (void)
{
return 0;
} }
virtual int getCoreVersion() const{ virtual int registerFunc (Plugin **plugin)
return 1; {
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"); return new ::sflphone::PluginTest("test");
} }
extern "C" void* destroy_t( ::sflphone::Plugin *p ){ extern "C" void* destroy( ::sflphone::PluginInterface *p ){
delete p; delete p;
} }
...@@ -15,7 +15,6 @@ OBJECT_FILES= \ ...@@ -15,7 +15,6 @@ OBJECT_FILES= \
../src/sflphoned-sipaccount.o \ ../src/sflphoned-sipaccount.o \
../src/sflphoned-iaxaccount.o \ ../src/sflphoned-iaxaccount.o \
../src/sflphoned-eventthread.o \ ../src/sflphoned-eventthread.o \
../src/sflphoned-useragent.o \
../src/plug-in/pluginmanager.o \ ../src/plug-in/pluginmanager.o \
../src/sflphoned-samplerateconverter.o ../src/sflphoned-samplerateconverter.o
......
...@@ -26,19 +26,26 @@ using std::cout; ...@@ -26,19 +26,26 @@ using std::cout;
using std::endl; using std::endl;
void PluginManagerTest::setUp(){ void PluginManagerTest::setUp(){
// Instanciate the plugin manager object // Instanciate the plugin manager singleton
_pm = new ::sflphone::PluginManager(); _pm = ::sflphone::PluginManager::instance();
} }
void PluginManagerTest::testLoadPluginDirectory(){ 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(){ void PluginManagerTest::testRegisterPlugin(){
CPPUNIT_ASSERT( _pm->isPluginLoaded("test") == NULL ); // First load the default directory
_pm->loadPlugins();
// Resolve the symbol
} }
void PluginManagerTest::tearDown(){ void PluginManagerTest::tearDown(){
// Delete the plugin manager object // Delete the plugin manager object
delete _pm; _pm=NULL; delete _pm; _pm=0;
} }
...@@ -43,7 +43,8 @@ class PluginManagerTest : public CppUnit::TestCase { ...@@ -43,7 +43,8 @@ class PluginManagerTest : public CppUnit::TestCase {
*/ */
CPPUNIT_TEST_SUITE( PluginManagerTest ); CPPUNIT_TEST_SUITE( PluginManagerTest );
CPPUNIT_TEST( testLoadPluginDirectory ); CPPUNIT_TEST( testLoadPluginDirectory );
CPPUNIT_TEST( testNonloadedPlugin ); CPPUNIT_TEST( testLoadPlugin );
CPPUNIT_TEST( testRegisterPlugin );
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
public: public:
...@@ -63,7 +64,9 @@ class PluginManagerTest : public CppUnit::TestCase { ...@@ -63,7 +64,9 @@ class PluginManagerTest : public CppUnit::TestCase {
void testLoadPluginDirectory(); void testLoadPluginDirectory();
void testNonloadedPlugin(); void testLoadPlugin();
void testRegisterPlugin();
private: private:
::sflphone::PluginManager *_pm; ::sflphone::PluginManager *_pm;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment