From f6d2fbf1147f5d23772f29e86368028e300f9141 Mon Sep 17 00:00:00 2001
From: Emmanuel Milou <manu@manu-eeepc.(none)>
Date: Thu, 29 Jan 2009 00:48:31 -0500
Subject: [PATCH] Make the plugins registering against the plugin manager

---
 src/plug-in/Makefile.am         |   3 +-
 src/plug-in/plugin.cpp          |  15 +++++
 src/plug-in/plugin.h            |  32 +++++++++
 src/plug-in/plugin_api.h        |  54 ---------------
 src/plug-in/plugininterface.h   |  51 +++++++++++++++
 src/plug-in/pluginmanager.cpp   |  93 ++++++++++++++++++++++----
 src/plug-in/pluginmanager.h     | 112 +++++++++++++++-----------------
 src/plug-in/test/pluginTest.cpp |  31 +++++++--
 test/Makefile.am                |   1 -
 test/pluginmanagerTest.cpp      |  19 ++++--
 test/pluginmanagerTest.h        |   7 +-
 11 files changed, 274 insertions(+), 144 deletions(-)
 create mode 100644 src/plug-in/plugin.cpp
 create mode 100644 src/plug-in/plugin.h
 delete mode 100644 src/plug-in/plugin_api.h
 create mode 100644 src/plug-in/plugininterface.h

diff --git a/src/plug-in/Makefile.am b/src/plug-in/Makefile.am
index 9f31ec25ae..bd27f29a4c 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 0000000000..deaf1a4818
--- /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 0000000000..fe548361eb
--- /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 7222154592..0000000000
--- 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 0000000000..1bfad23e2f
--- /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 54f757216e..f8135f5780 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 5330b8764f..671834369d 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 6249a886fa..5e5f7cff11 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 86e70dbc38..652556ffb5 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 b9a3d413a4..ed3f4d7e28 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 e43ba8f7ab..0cd92da42c 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;
-- 
GitLab