From 62b545128f37746c343760e464872655b5523c6f Mon Sep 17 00:00:00 2001 From: erihel Date: Sun, 12 Aug 2012 18:37:11 +0200 Subject: [PATCH] * Final changes to plugin interface * Added doxygen comments to plugin manager and plugin loader --- src/plugins/plugininterface.h | 34 +++++++++++++++++++-- src/plugins/pluginloader.cpp | 17 +++++++++-- src/plugins/pluginloader.h | 42 +++++++++++++++++++++++++- src/plugins/pluginmanager.cpp | 22 ++++++++++---- src/plugins/pluginmanager.h | 33 ++++++++++++++++++++ src/plugins/test/manager_test.cpp | 7 +++++ src/sound/plugins/oalsound/alsound.cpp | 9 +++--- src/sound/plugins/oalsound/alsound.h | 4 +-- src/sound/sound.h | 8 ++--- 9 files changed, 153 insertions(+), 23 deletions(-) diff --git a/src/plugins/plugininterface.h b/src/plugins/plugininterface.h index bf4e040c..b8adddc8 100644 --- a/src/plugins/plugininterface.h +++ b/src/plugins/plugininterface.h @@ -16,22 +16,50 @@ // plugininterface.h +/** + * @file plugin/plugininterface.h + * @brief Generic plugin interface + */ #pragma once +#include #define PLUGIN_INTERFACE(class_type) \ static class_type* Plugin##class_type; \ extern "C" void InstallPluginEntry() { Plugin##class_type = new class_type(); Plugin##class_type->InstallPlugin(); } \ - extern "C" void UninstallPluginEntry() { Plugin##class_type->UninstallPlugin(); delete Plugin##class_type; } \ + extern "C" bool UninstallPluginEntry(std::string &reason) { bool result = Plugin##class_type->UninstallPlugin(reason); \ + if (!result) \ + return false; \ + delete Plugin##class_type; \ + return true; } \ extern "C" CPluginInterface* GetPluginInterfaceEntry() { return static_cast(Plugin##class_type); } +/** +* @class CPluginInterface +* +* @brief Generic plugin interface. All plugins that will be managed by plugin manager have to derive from this class. +* +*/ class CPluginInterface { public: - virtual char* PluginName() = 0; + /** Function to get plugin name or description + * @return returns plugin name + */ + virtual std::string PluginName() = 0; + + /** Function to get plugin version. 1 means version 0.01, 2 means 0.02 etc. + * @return number indicating plugin version + */ virtual int PluginVersion() = 0; + + /** Function to initialize plugin + */ virtual void InstallPlugin() = 0; - virtual void UninstallPlugin() = 0; + + /** Function called before removing plugin + */ + virtual bool UninstallPlugin(std::string &) = 0; }; diff --git a/src/plugins/pluginloader.cpp b/src/plugins/pluginloader.cpp index 8893b562..fd8ce746 100644 --- a/src/plugins/pluginloader.cpp +++ b/src/plugins/pluginloader.cpp @@ -28,11 +28,11 @@ CPluginLoader::CPluginLoader(std::string filename) } -char* CPluginLoader::GetName() +std::string CPluginLoader::GetName() { if (mLoaded) return mInterface->PluginName(); - return nullptr; + return "(not loaded)"; } @@ -57,12 +57,18 @@ bool CPluginLoader::UnloadPlugin() return true; } - void (*uninstall)() = (void (*)()) lt_dlsym(mHandle, "UninstallPluginEntry"); + bool (*uninstall)(std::string &) = (bool (*)(std::string &)) lt_dlsym(mHandle, "UninstallPluginEntry"); if (!uninstall) { GetLogger()->Error("Error getting UninstallPluginEntry for plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); return false; } + std::string reason; + if (!uninstall(reason)) { + GetLogger()->Error("Could not unload plugin %s: %s\n", mFilename.c_str(), reason.c_str()); + return false; + } + lt_dlclose(mHandle); mLoaded = false; return true; @@ -71,6 +77,11 @@ bool CPluginLoader::UnloadPlugin() bool CPluginLoader::LoadPlugin() { + if (mFilename.length() == 0) { + GetLogger()->Warn("No plugin filename specified.\n"); + return false; + } + mHandle = lt_dlopenext(mFilename.c_str()); if (!mHandle) { GetLogger()->Error("Error loading plugin %s: %s\n", mFilename.c_str(), lt_dlerror()); diff --git a/src/plugins/pluginloader.h b/src/plugins/pluginloader.h index 873d30ac..40b19dac 100644 --- a/src/plugins/pluginloader.h +++ b/src/plugins/pluginloader.h @@ -16,6 +16,10 @@ // pluginloader.h +/** + * @file plugin/pluginloader.h + * @brief Plugin loader interface + */ #pragma once @@ -27,16 +31,52 @@ #include "plugininterface.h" +/** +* @class CPluginLoader +* +* @brief Plugin loader interface. Plugin manager uses this class to load plugins. +* +*/ class CPluginLoader { public: + /** Class contructor + * @param std::string plugin filename + */ CPluginLoader(std::string); - char* GetName(); + /** Function to get plugin name or description + * @return returns plugin name + */ + std::string GetName(); + + /** Function to get plugin version + * @return returns plugin version + */ int GetVersion(); + + /** Function to unload plugin + * @return returns true on success + */ bool UnloadPlugin(); + + /** Function to load plugin + * @return returns true on success + */ bool LoadPlugin(); + + /** Function to check if plugin is loaded + * @return returns true if plugin is loaded + */ bool IsLoaded(); + + /** Function to set plugin filename + * @return returns true on success. Action can fail if plugin was loaded and cannot be unloaded + */ bool SetFilename(std::string); + + /** Function to get plugin filename + * @return returns plugin filename + */ std::string GetFilename(); diff --git a/src/plugins/pluginmanager.cpp b/src/plugins/pluginmanager.cpp index ab9d8adb..470ac2f7 100644 --- a/src/plugins/pluginmanager.cpp +++ b/src/plugins/pluginmanager.cpp @@ -60,7 +60,7 @@ bool CPluginManager::LoadPlugin(std::string filename) loader->SetFilename(dir + "/" + filename); result = loader->LoadPlugin(); if (result) { - GetLogger()->Info("Plugin %s (%s) version %0.2f loaded!\n", filename.c_str(), loader->GetName(), loader->GetVersion() / 100.0f); + GetLogger()->Info("Plugin %s (%s) version %0.2f loaded!\n", filename.c_str(), loader->GetName().c_str(), loader->GetVersion() / 100.0f); m_plugins.push_back(loader); break; } @@ -102,13 +102,23 @@ bool CPluginManager::RemoveSearchDirectory(std::string dir) bool CPluginManager::UnloadAllPlugins() { - for (CPluginLoader *plugin : m_plugins) { - GetLogger()->Info("Trying to unload plugin %s (%s)...\n", plugin->GetFilename().c_str(), plugin->GetName()); - plugin->UnloadPlugin(); + bool allOk = true; + std::vector::iterator it; + for (it = m_plugins.begin(); it != m_plugins.end(); it++) { + CPluginLoader *plugin = *it; + bool result; + + GetLogger()->Info("Trying to unload plugin %s (%s)...\n", plugin->GetFilename().c_str(), plugin->GetName().c_str()); + result = plugin->UnloadPlugin(); + if (!result) { + allOk = false; + continue; + } delete plugin; + m_plugins.erase(it); } - m_plugins.clear(); - return true; + + return allOk; } diff --git a/src/plugins/pluginmanager.h b/src/plugins/pluginmanager.h index d2672388..e425c62e 100644 --- a/src/plugins/pluginmanager.h +++ b/src/plugins/pluginmanager.h @@ -16,6 +16,10 @@ // pluginmanager.h +/** + * @file plugin/pluginmanager.h + * @brief Plugin manager class. + */ #pragma once @@ -31,19 +35,48 @@ #include "pluginloader.h" +/** +* @class CPluginManager +* +* @brief Plugin manager class. Plugin manager can load plugins from colobot.ini or manually specified files. +* +*/ class CPluginManager : public CSingleton { public: CPluginManager(); ~CPluginManager(); + /** Function loads plugin list and path list from profile file + */ void LoadFromProfile(); + /** Function loads specified plugin + * @param std::string plugin filename + * @return returns true on success + */ bool LoadPlugin(std::string); + + /** Function unloads specified plugin + * @param std::string plugin filename + * @return returns true on success + */ bool UnloadPlugin(std::string); + /** Function adds path to be checked when searching for plugin file. If path was already added it will be ignored + * @param std::string plugin search path + * @return returns true on success + */ bool AddSearchDirectory(std::string); + + /** Function removes path from list + * @param std::string plugin search path + * @return returns true on success + */ bool RemoveSearchDirectory(std::string); + /** Function tries to unload all plugins + * @return returns true on success + */ bool UnloadAllPlugins(); private: diff --git a/src/plugins/test/manager_test.cpp b/src/plugins/test/manager_test.cpp index 9b3f4720..d921c1d3 100644 --- a/src/plugins/test/manager_test.cpp +++ b/src/plugins/test/manager_test.cpp @@ -15,8 +15,15 @@ int main() { GetLogger()->Error("Config not found!\n"); return 1; } + mgr->LoadFromProfile(); CSoundInterface *sound = static_cast(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_SOUND)); + + if (!sound) { + GetLogger()->Error("Sound not loaded!\n"); + return 2; + } + sound->Create(true); mgr->UnloadAllPlugins(); diff --git a/src/sound/plugins/oalsound/alsound.cpp b/src/sound/plugins/oalsound/alsound.cpp index a1d4801b..8cd82210 100644 --- a/src/sound/plugins/oalsound/alsound.cpp +++ b/src/sound/plugins/oalsound/alsound.cpp @@ -27,15 +27,15 @@ PLUGIN_INTERFACE(ALSound) -char* ALSound::PluginName() +std::string ALSound::PluginName() { - return const_cast("Sound plugin using OpenAL library to play sounds."); + return "Sound plugin using OpenAL library to play sounds."; } int ALSound::PluginVersion() { - return 1; + return 2; } @@ -47,12 +47,13 @@ void ALSound::InstallPlugin() } -void ALSound::UninstallPlugin() +bool ALSound::UninstallPlugin(std::string &reason) { auto pointer = CInstanceManager::GetInstancePointer(); if (pointer != nullptr) CInstanceManager::GetInstancePointer()->DeleteInstance(CLASS_SOUND, this); CleanUp(); + return true; } diff --git a/src/sound/plugins/oalsound/alsound.h b/src/sound/plugins/oalsound/alsound.h index 9265e2cc..c1cdb818 100644 --- a/src/sound/plugins/oalsound/alsound.h +++ b/src/sound/plugins/oalsound/alsound.h @@ -74,10 +74,10 @@ class ALSound : public CSoundInterface bool IsPlayingMusic(); // plugin interface - char* PluginName(); + std::string PluginName(); int PluginVersion(); void InstallPlugin(); - void UninstallPlugin(); + bool UninstallPlugin(std::string &); private: void CleanUp(); diff --git a/src/sound/sound.h b/src/sound/sound.h index f18a76ac..45ec7e1e 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -15,10 +15,10 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// soundinterface.h +// sound.h /** - * @file sound/soundinterface.h + * @file sound/sound.h * @brief Sound plugin interface */ @@ -39,7 +39,7 @@ /** * \public - * \enum Sound sound/soundinterface.h + * \enum Sound sound/sound.h * \brief Sound enum representing sound file **/ enum Sound @@ -131,7 +131,7 @@ enum Sound /** * \public - * \enum SoundNext sound/soundinterface.h + * \enum SoundNext sound/sound.h * \brief Enum representing operation that will be performend on a sound at given time **/ enum SoundNext