aboutsummaryrefslogtreecommitdiff
path: root/base/plugins.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'base/plugins.cpp')
-rw-r--r--base/plugins.cpp231
1 files changed, 159 insertions, 72 deletions
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 9e2c2599ce..dcd394495f 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -24,12 +24,23 @@
*/
#include "base/plugins.h"
-#include "common/util.h"
+
+#include "common/func.h"
+
+#ifdef DYNAMIC_MODULES
+#include "common/config-manager.h"
+#endif
+
+// Plugin versioning
int pluginTypeVersions[PLUGIN_TYPE_MAX] = {
PLUGIN_TYPE_ENGINE_VERSION,
+ PLUGIN_TYPE_MUSIC_VERSION,
};
+
+// Abstract plugins
+
PluginType Plugin::getType() const {
return _type;
}
@@ -38,31 +49,6 @@ const char *Plugin::getName() const {
return _pluginObject->getName();
}
-const char *Plugin::getCopyright() const {
- return ((MetaEngine*)_pluginObject)->getCopyright();
-}
-
-PluginError Plugin::createInstance(OSystem *syst, Engine **engine) const {
- return ((MetaEngine*)_pluginObject)->createInstance(syst, engine);
-}
-
-GameList Plugin::getSupportedGames() const {
- return ((MetaEngine*)_pluginObject)->getSupportedGames();
-}
-
-GameDescriptor Plugin::findGame(const char *gameid) const {
- return ((MetaEngine*)_pluginObject)->findGame(gameid);
-}
-
-GameList Plugin::detectGames(const FSList &fslist) const {
- return ((MetaEngine*)_pluginObject)->detectGames(fslist);
-}
-
-SaveStateList Plugin::listSaves(const char *target) const {
- return ((MetaEngine*)_pluginObject)->listSaves(target);
-}
-
-
class StaticPlugin : public Plugin {
public:
StaticPlugin(PluginObject *pluginobject, PluginType type) {
@@ -99,6 +85,7 @@ public:
// "Loader" for the static plugins.
// Iterate over all registered (static) plugins and load them.
+ // Engine plugins
#if PLUGIN_ENABLED_STATIC(SCUMM)
LINK_PLUGIN(SCUMM)
#endif
@@ -157,6 +144,49 @@ public:
LINK_PLUGIN(TOUCHE)
#endif
+ // Music plugins
+ // TODO: Use defines to disable or enable each MIDI driver as a
+ // static/dynamic plugin, like it's done for the engines
+ LINK_PLUGIN(NULL)
+ #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
+ LINK_PLUGIN(WINDOWS)
+ #endif
+ #if defined(UNIX) && defined(USE_ALSA)
+ LINK_PLUGIN(ALSA)
+ #endif
+ #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__)
+ LINK_PLUGIN(SEQ)
+ #endif
+ #if defined(IRIX)
+ LINK_PLUGIN(DMEDIA)
+ #endif
+ #if defined(__amigaos4__)
+ LINK_PLUGIN(CAMD)
+ #endif
+ #if defined(MACOSX)
+ LINK_PLUGIN(COREAUDIO)
+ LINK_PLUGIN(COREMIDI)
+ LINK_PLUGIN(QUICKTIME)
+ #endif
+ #if defined(PALMOS_MODE)
+ # if defined(COMPILE_CLIE)
+ LINK_PLUGIN(YPA1)
+ # elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM))
+ LINK_PLUGIN(ZODIAC)
+ # endif
+ #endif
+ #ifdef USE_FLUIDSYNTH
+ LINK_PLUGIN(FLUIDSYNTH)
+ #endif
+ #ifdef USE_MT32EMU
+ LINK_PLUGIN(MT32)
+ #endif
+ LINK_PLUGIN(ADLIB)
+ LINK_PLUGIN(TOWNS)
+ #if defined (UNIX)
+ LINK_PLUGIN(TIMIDITY)
+ #endif
+
return pl;
}
};
@@ -167,30 +197,34 @@ PluginList FilePluginProvider::getPlugins() {
PluginList pl;
// Prepare the list of directories to search
- Common::StringList pluginDirs;
- // TODO: Add the user specified directory (via config file)
- pluginDirs.push_back(".");
- pluginDirs.push_back("plugins");
+ FSList pluginDirs;
+
+ // Add the default directories
+ pluginDirs.push_back(FilesystemNode("."));
+ pluginDirs.push_back(FilesystemNode("plugins"));
// Add the provider's custom directories
addCustomDirectories(pluginDirs);
- Common::StringList::const_iterator d;
- for (d = pluginDirs.begin(); d != pluginDirs.end(); d++) {
+ // Add the user specified directory
+ Common::String pluginsPath(ConfMan.get("pluginspath"));
+ if (!pluginsPath.empty())
+ pluginDirs.push_back(FilesystemNode(pluginsPath));
+
+ FSList::const_iterator dir;
+ for (dir = pluginDirs.begin(); dir != pluginDirs.end(); dir++) {
// Load all plugins.
// Scan for all plugins in this directory
- FilesystemNode dir(*d);
FSList files;
- if (!dir.getChildren(files, FilesystemNode::kListFilesOnly)) {
- debug(1, "Couldn't open plugin directory '%s'", d->c_str());
+ if (!dir->getChildren(files, FilesystemNode::kListFilesOnly)) {
+ debug(1, "Couldn't open plugin directory '%s'", dir->getPath().c_str());
continue;
} else {
- debug(1, "Reading plugins from plugin directory '%s'", d->c_str());
+ debug(1, "Reading plugins from plugin directory '%s'", dir->getPath().c_str());
}
for (FSList::const_iterator i = files.begin(); i != files.end(); ++i) {
- Common::String name(i->getName());
- if (name.hasPrefix(getPrefix()) && name.hasSuffix(getSuffix())) {
+ if (isPluginFilename(i->getName())) {
pl.push_back(createPlugin(i->getPath()));
}
}
@@ -199,25 +233,25 @@ PluginList FilePluginProvider::getPlugins() {
return pl;
}
-const char* FilePluginProvider::getPrefix() const {
+bool FilePluginProvider::isPluginFilename(const Common::String &filename) const {
#ifdef PLUGIN_PREFIX
- return PLUGIN_PREFIX;
-#else
- return "";
+ // Check the plugin prefix
+ if (!filename.hasPrefix(PLUGIN_PREFIX))
+ return false;
#endif
-}
-const char* FilePluginProvider::getSuffix() const {
#ifdef PLUGIN_SUFFIX
- return PLUGIN_SUFFIX;
-#else
- return "";
+ // Check the plugin suffix
+ if (!filename.hasSuffix(PLUGIN_SUFFIX))
+ return false;
#endif
+
+ return true;
}
-void FilePluginProvider::addCustomDirectories(Common::StringList &dirs) const {
+void FilePluginProvider::addCustomDirectories(FSList &dirs) const {
#ifdef PLUGIN_DIRECTORY
- dirs.push_back(PLUGIN_DIRECTORY);
+ dirs.push_back(FilesystemNode(PLUGIN_DIRECTORY));
#endif
}
@@ -252,31 +286,30 @@ void PluginManager::loadPlugins() {
for (ProviderList::iterator pp = _providers.begin();
pp != _providers.end();
++pp) {
- PluginList pl((**pp).getPlugins());
- for (PluginList::iterator plugin = pl.begin(); plugin != pl.end(); ++plugin) {
- tryLoadPlugin(*plugin);
- }
+ PluginList pl((*pp)->getPlugins());
+ Common::for_each(pl.begin(), pl.end(), Common::bind1st(Common::mem_fun(&PluginManager::tryLoadPlugin), this));
}
}
void PluginManager::unloadPlugins() {
- unloadPluginsExcept(NULL);
+ for (int i = 0; i < PLUGIN_TYPE_MAX; i++)
+ unloadPluginsExcept((PluginType)i, NULL);
}
-void PluginManager::unloadPluginsExcept(const Plugin *plugin) {
+void PluginManager::unloadPluginsExcept(PluginType type, const Plugin *plugin) {
Plugin *found = NULL;
- for (PluginList::iterator p = _plugins.begin(); p != _plugins.end(); ++p) {
+ for (PluginList::iterator p = _plugins[type].begin(); p != _plugins[type].end(); ++p) {
if (*p == plugin) {
found = *p;
} else {
- (**p).unloadPlugin();
+ (*p)->unloadPlugin();
delete *p;
}
}
- _plugins.clear();
+ _plugins[type].clear();
if (found != NULL) {
- _plugins.push_back(found);
+ _plugins[type].push_back(found);
}
}
@@ -284,16 +317,26 @@ bool PluginManager::tryLoadPlugin(Plugin *plugin) {
assert(plugin);
// Try to load the plugin
if (plugin->loadPlugin()) {
- // If successful, add it to the list of known plugins and return.
- _plugins.push_back(plugin);
+ // The plugin is valid, see if it provides the same module as an
+ // already loaded one and should replace it.
+ bool found = false;
+
+ PluginList::iterator pl = _plugins[plugin->getType()].begin();
+ while (!found && pl != _plugins[plugin->getType()].end()) {
+ if (!strcmp(plugin->getName(), (*pl)->getName())) {
+ // Found a duplicated module. Replace the old one.
+ found = true;
+ delete *pl;
+ *pl = plugin;
+ debug(1, "Replaced the duplicated plugin: '%s'", plugin->getName());
+ }
+ pl++;
+ }
- // TODO/FIXME: We should perform some additional checks here:
- // * Check for some kind of "API version" (possibly derived from the
- // SVN tree revision?)
- // * If two plugins provide the same engine, we should only load one.
- // To detect this situation, we could just compare the plugin name.
- // To handle it, simply prefer modules loaded earlier to those coming.
- // Or vice versa... to be determined... :-)
+ if (!found) {
+ // If it provides a new module, just add it to the list of known plugins.
+ _plugins[plugin->getType()].push_back(plugin);
+ }
return true;
} else {
@@ -303,15 +346,59 @@ bool PluginManager::tryLoadPlugin(Plugin *plugin) {
}
}
-GameList PluginManager::detectGames(const FSList &fslist) const {
+
+// Engine plugins
+
+#include "engines/metaengine.h"
+
+DECLARE_SINGLETON(EngineManager);
+
+GameDescriptor EngineManager::findGame(const Common::String &gameName, const EnginePlugin **plugin) const {
+ // Find the GameDescriptor for this target
+ const EnginePlugin::List &plugins = getPlugins();
+ GameDescriptor result;
+
+ if (plugin)
+ *plugin = 0;
+
+ EnginePlugin::List::const_iterator iter = plugins.begin();
+ for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
+ result = (**iter)->findGame(gameName.c_str());
+ if (!result.gameid().empty()) {
+ if (plugin)
+ *plugin = *iter;
+ break;
+ }
+ }
+ return result;
+}
+
+GameList EngineManager::detectGames(const FSList &fslist) const {
GameList candidates;
+ const EnginePlugin::List &plugins = getPlugins();
+
// Iterate over all known games and for each check if it might be
// the game in the presented directory.
- PluginList::const_iterator iter;
- for (iter = _plugins.begin(); iter != _plugins.end(); ++iter) {
- candidates.push_back((*iter)->detectGames(fslist));
+ EnginePlugin::List::const_iterator iter;
+ for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
+ candidates.push_back((**iter)->detectGames(fslist));
}
return candidates;
}
+
+const EnginePlugin::List &EngineManager::getPlugins() const {
+ return (const EnginePlugin::List &)PluginManager::instance().getPlugins(PLUGIN_TYPE_ENGINE);
+}
+
+
+// Music plugins
+
+#include "sound/musicplugin.h"
+
+DECLARE_SINGLETON(MusicManager);
+
+const MusicPlugin::List &MusicManager::getPlugins() const {
+ return (const MusicPlugin::List &)PluginManager::instance().getPlugins(PLUGIN_TYPE_MUSIC);
+}