aboutsummaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorYotam Barnoy2010-11-03 22:01:01 +0000
committerYotam Barnoy2010-11-03 22:01:01 +0000
commit13b904d282ea607db94069b927d6cb1b19aa0d0b (patch)
treecbc8efcc281f735beb9f45117e82a30872995ac7 /base
parent0ac1eb82c65e7f20f51f6337df5aa64e02a1af29 (diff)
parent27182f266f48a6d55dd5d830ed19e2c4285ac1ba (diff)
downloadscummvm-rg350-13b904d282ea607db94069b927d6cb1b19aa0d0b.tar.gz
scummvm-rg350-13b904d282ea607db94069b927d6cb1b19aa0d0b.tar.bz2
scummvm-rg350-13b904d282ea607db94069b927d6cb1b19aa0d0b.zip
Merge from gsoc2010-plugins
This merge was extremely difficult to carry out. It wasn't entirely SVN's fault -- there were several merges to the branch that were done by hand. Please check for any issues and regressions. Also note that the DS makefile was not copied over since the "one at a time" plugin mode currently has too much fragmentation ie. it doesn't work. svn-id: r54051
Diffstat (limited to 'base')
-rw-r--r--base/main.cpp21
-rw-r--r--base/plugins.cpp109
-rw-r--r--base/plugins.h40
3 files changed, 146 insertions, 24 deletions
diff --git a/base/main.cpp b/base/main.cpp
index d2da09fa2f..8928396642 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -105,7 +105,12 @@ static const EnginePlugin *detectPlugin() {
// Query the plugins and find one that will handle the specified gameid
printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str());
printf("%s", " Looking for a plugin supporting this gameid... ");
- GameDescriptor game = EngineMan.findGame(gameid, &plugin);
+
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ GameDescriptor game = EngineMan.findGameOnePlugAtATime(gameid, &plugin);
+#else
+ GameDescriptor game = EngineMan.findGame(gameid, &plugin);
+#endif
if (plugin == 0) {
printf("failed\n");
@@ -336,8 +341,13 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
settings.erase("debugflags");
}
- // Load the plugins.
- PluginManager::instance().loadPlugins();
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ // Only load non-engine plugins and first engine plugin initially in this case.
+ PluginManager::instance().loadFirstPlugin();
+#else
+ // Load the plugins.
+ PluginManager::instance().loadPlugins();
+#endif
// If we received an invalid music parameter via command line we check this here.
// We can't check this before loading the music plugins.
@@ -420,7 +430,12 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
ConfMan.setActiveDomain("");
// PluginManager::instance().unloadPlugins();
+
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ PluginManager::instance().loadFirstPlugin();
+#else
PluginManager::instance().loadPlugins();
+#endif
} else {
GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game"));
}
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 7102462173..d2fad34579 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -305,6 +305,7 @@ DECLARE_SINGLETON(PluginManager)
PluginManager::PluginManager() {
// Always add the static plugin provider.
addPluginProvider(new StaticPluginProvider());
+ _skipStaticPlugs = false;
}
PluginManager::~PluginManager() {
@@ -323,6 +324,60 @@ void PluginManager::addPluginProvider(PluginProvider *pp) {
_providers.push_back(pp);
}
+void PluginManager::loadFirstPlugin() { //TODO: rename? It's not quite clear that this loads all non-engine plugins and first engine plugin.
+ unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL);
+ _allPlugs.clear();
+ for (ProviderList::iterator pp = _providers.begin();
+ pp != _providers.end();
+ ++pp) {
+ if ((_skipStaticPlugs && (*pp)->isFilePluginProvider()) || !_skipStaticPlugs) {
+ PluginList pl((*pp)->getPlugins());
+ for (PluginList::iterator p = pl.begin(); p != pl.end(); ++p) {
+ _allPlugs.push_back(*p);
+ }
+ }
+ }
+
+ _nonEnginePlugs = 0;
+ _skipStaticPlugs = true; //Only need to load static plugins once.
+
+ _currentPlugin = _allPlugs.begin();
+
+ if (_allPlugs.empty()) {
+ return; //return here if somehow there are no plugins to load.
+ }
+
+ //this loop is for loading all non-engine plugins and the first engine plugin.
+ for (; _currentPlugin != _allPlugs.end(); ++_currentPlugin) {
+ if (!tryLoadPlugin(*_currentPlugin))
+ continue;
+
+ // TODO: This assumes all non-engine plugins will precede the first engine plugin!
+ if ((*_currentPlugin)->getType() == PLUGIN_TYPE_ENGINE)
+ break;
+
+ _nonEnginePlugs++;
+ }
+
+ return;
+}
+
+bool PluginManager::loadNextPlugin() {
+ if (_nonEnginePlugs == _allPlugs.size())
+ return false; //There are no Engine Plugins in this case.
+
+ // To ensure only one engine plugin is loaded at a time, we unload all engine plugins before trying to load a new one.
+ unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL);
+
+ ++_currentPlugin;
+ for (; _currentPlugin != _allPlugs.end(); ++_currentPlugin)
+ if (tryLoadPlugin(*_currentPlugin))
+ return true;
+
+ loadFirstPlugin();
+ return false;
+}
+
void PluginManager::loadPlugins() {
for (ProviderList::iterator pp = _providers.begin();
pp != _providers.end();
@@ -330,7 +385,6 @@ void PluginManager::loadPlugins() {
PluginList pl((*pp)->getPlugins());
Common::for_each(pl.begin(), pl.end(), Common::bind1st(Common::mem_fun(&PluginManager::tryLoadPlugin), this));
}
-
}
void PluginManager::unloadPlugins() {
@@ -361,7 +415,6 @@ bool PluginManager::tryLoadPlugin(Plugin *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())) {
@@ -387,13 +440,24 @@ bool PluginManager::tryLoadPlugin(Plugin *plugin) {
}
}
-
// Engine plugins
#include "engines/metaengine.h"
DECLARE_SINGLETON(EngineManager)
+GameDescriptor EngineManager::findGameOnePlugAtATime(const Common::String &gameName, const EnginePlugin **plugin) const {
+ GameDescriptor result;
+ //PluginManager::instance().loadFirstPlugin();
+ do {
+ result = findGame(gameName, plugin);
+ if (!result.gameid().empty()) {
+ break;
+ }
+ } while (PluginManager::instance().loadNextPlugin());
+ return result;
+}
+
GameDescriptor EngineManager::findGame(const Common::String &gameName, const EnginePlugin **plugin) const {
// Find the GameDescriptor for this target
const EnginePlugin::List &plugins = getPlugins();
@@ -402,30 +466,35 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Eng
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;
+ EnginePlugin::List::const_iterator iter;
+
+ for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
+ result = (**iter)->findGame(gameName.c_str());
+ if (!result.gameid().empty()) {
+ if (plugin)
+ *plugin = *iter;
+ return result;
+ }
}
- }
return result;
}
GameList EngineManager::detectGames(const Common::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.
+ EnginePlugin::List plugins;
EnginePlugin::List::const_iterator iter;
- for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
- candidates.push_back((**iter)->detectGames(fslist));
- }
-
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ do {
+#endif
+ plugins = getPlugins();
+ // Iterate over all known games and for each check if it might be
+ // the game in the presented directory.
+ for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
+ candidates.push_back((**iter)->detectGames(fslist));
+ }
+#if defined(ONE_PLUGIN_AT_A_TIME) && defined(DYNAMIC_MODULES)
+ } while (PluginManager::instance().loadNextPlugin());
+#endif
return candidates;
}
diff --git a/base/plugins.h b/base/plugins.h
index a4c7f114f9..5472ab2fce 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -30,6 +30,7 @@
#include "common/error.h"
#include "common/singleton.h"
#include "common/util.h"
+#include "backends/plugins/elf/version.h"
namespace Common {
class FSList;
@@ -90,6 +91,21 @@ extern int pluginTypeVersions[PLUGIN_TYPE_MAX];
#define PLUGIN_ENABLED_DYNAMIC(ID) \
(ENABLE_##ID && (ENABLE_##ID == DYNAMIC_PLUGIN) && DYNAMIC_MODULES)
+// see comments in backends/plugins/elf/elf-provider.cpp
+#if defined(USE_ELF_LOADER) && defined(ELF_LOADER_CXA_ATEXIT)
+#define PLUGIN_DYNAMIC_DSO_HANDLE \
+ uint32 __dso_handle __attribute__((visibility("hidden"))) = 0;
+#else
+#define PLUGIN_DYNAMIC_DSO_HANDLE
+#endif
+
+#ifdef USE_ELF_LOADER
+#define PLUGIN_DYNAMIC_BUILD_DATE \
+ PLUGIN_EXPORT const char *PLUGIN_getBuildDate() { return gScummVMPluginBuildDate; }
+#else
+#define PLUGIN_DYNAMIC_BUILD_DATE
+#endif
+
/**
* REGISTER_PLUGIN_STATIC is a convenience macro which is used to declare
* the plugin interface for static plugins. Code (such as game engines)
@@ -119,6 +135,8 @@ extern int pluginTypeVersions[PLUGIN_TYPE_MAX];
*/
#define REGISTER_PLUGIN_DYNAMIC(ID,TYPE,PLUGINCLASS) \
extern "C" { \
+ PLUGIN_DYNAMIC_DSO_HANDLE \
+ PLUGIN_DYNAMIC_BUILD_DATE \
PLUGIN_EXPORT int32 PLUGIN_getVersion() { return PLUGIN_VERSION; } \
PLUGIN_EXPORT int32 PLUGIN_getType() { return TYPE; } \
PLUGIN_EXPORT int32 PLUGIN_getTypeVersion() { return TYPE##_VERSION; } \
@@ -212,6 +230,11 @@ public:
* @return a list of Plugin instances
*/
virtual PluginList getPlugins() = 0;
+
+ /**
+ * @return whether or not object is a FilePluginProvider.
+ */
+ virtual bool isFilePluginProvider() { return false; }
};
#ifdef DYNAMIC_MODULES
@@ -234,6 +257,11 @@ public:
*/
virtual PluginList getPlugins();
+ /**
+ * @return whether or not object is a FilePluginProvider.
+ */
+ bool isFilePluginProvider() { return true; }
+
protected:
/**
* Create a Plugin instance from a loadable code module with the specified name.
@@ -276,8 +304,15 @@ private:
PluginList _plugins[PLUGIN_TYPE_MAX];
ProviderList _providers;
- bool tryLoadPlugin(Plugin *plugin);
+ PluginList _allPlugs;
+ PluginList::iterator _currentPlugin;
+ bool _skipStaticPlugs;
+
+ uint _nonEnginePlugs;
+
+ bool tryLoadPlugin(Plugin *plugin);
+
friend class Common::Singleton<SingletonBaseType>;
PluginManager();
@@ -286,6 +321,9 @@ public:
void addPluginProvider(PluginProvider *pp);
+ void loadFirstPlugin();
+ bool loadNextPlugin();
+
void loadPlugins();
void unloadPlugins();
void unloadPluginsExcept(PluginType type, const Plugin *plugin);