aboutsummaryrefslogtreecommitdiff
path: root/base/plugins.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/plugins.h')
-rw-r--r--base/plugins.h240
1 files changed, 168 insertions, 72 deletions
diff --git a/base/plugins.h b/base/plugins.h
index ca08a0c628..9d3ce97c3b 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -26,98 +26,82 @@
#ifndef BASE_PLUGINS_H
#define BASE_PLUGINS_H
-#include "common/array.h"
#include "common/error.h"
-#include "common/list.h"
#include "common/singleton.h"
#include "common/util.h"
-#include "base/game.h"
+
+#ifdef DYNAMIC_MODULES
+#include "common/fs.h"
+#endif
/**
- * Abstract base class for the plugin objects which handle plugins
- * instantiation. Subclasses for this may be used for engine plugins
- * and other types of plugins.
+ * @page pagePlugins An overview of the ScummVM plugin system
+ * This is a brief overview of how plugins (dynamically loadable code modules)
+ * work in ScummVM. We will explain how to write plugins, how they work internally,
+ * and sketch how porters can add support for them in their ports.
+ *
+ * \section secPluginImpl Implementing a plugin
+ * TODO
+ *
+ * \section secPluginUse Using plugins
+ * TODO
+ *
+ * \section secPluginInternals How plugins work internally
+ * TODO
+ *
+ * \section secPluginBackend How to add support for dynamic plugins to a port
+ * TODO
*/
-class PluginObject {
-public:
- virtual ~PluginObject() {}
- /** Returns the name of the plugin. */
- virtual const char *getName() const = 0;
-};
-#include "engines/metaengine.h"
-// Global Plugin API version
+// Plugin versioning
+
+/** Global Plugin API version */
#define PLUGIN_VERSION 1
enum PluginType {
PLUGIN_TYPE_ENGINE = 0,
+ PLUGIN_TYPE_MUSIC,
+ /* PLUGIN_TYPE_SCALER, */ // TODO: Add graphics scaler plugins
PLUGIN_TYPE_MAX
};
// TODO: Make the engine API version depend on ScummVM's version
-// because of the backlinking
+// because of the backlinking (posibly from the SVN revision)
#define PLUGIN_TYPE_ENGINE_VERSION 1
+#define PLUGIN_TYPE_MUSIC_VERSION 1
extern int pluginTypeVersions[PLUGIN_TYPE_MAX];
-class Engine;
-class FSList;
-class OSystem;
-
-/**
- * Abstract base class for the plugin system.
- * Subclasses for this can be used to wrap both static and dynamic
- * plugins.
- */
-class Plugin {
-protected:
- PluginObject *_pluginObject;
- PluginType _type;
-
-public:
- Plugin() : _pluginObject(0) {}
- virtual ~Plugin() {
- //if (isLoaded())
- //unloadPlugin();
- }
-
-// virtual bool isLoaded() const = 0; // TODO
- virtual bool loadPlugin() = 0; // TODO: Rename to load() ?
- virtual void unloadPlugin() = 0; // TODO: Rename to unload() ?
-
- PluginType getType() const;
- const char *getName() const;
- const char *getCopyright() const;
-
- PluginError createInstance(OSystem *syst, Engine **engine) const;
- GameList getSupportedGames() const;
- GameDescriptor findGame(const char *gameid) const;
- GameList detectGames(const FSList &fslist) const;
- SaveStateList listSaves(const char *target) const;
-};
+// Plugin linking
#define STATIC_PLUGIN 1
#define DYNAMIC_PLUGIN 2
+// Note: The spaces around ENABLE_##ID have been added on purpose for
+// MSVC. For some reason, MSVC tries to add the parenthesis after
+// ENABLE_##ID to the check, thus making it false all the time.
+// Please do NOT remove them, otherwise no engine plugins will be
+// registered under MSVC
+
#define PLUGIN_ENABLED_STATIC(ID) \
- (defined(ENABLE_##ID) && !PLUGIN_ENABLED_DYNAMIC(ID))
+ (defined( ENABLE_##ID ) && !PLUGIN_ENABLED_DYNAMIC(ID))
#define PLUGIN_ENABLED_DYNAMIC(ID) \
- (defined(ENABLE_##ID) && (ENABLE_##ID == DYNAMIC_PLUGIN) && defined(DYNAMIC_MODULES))
+ (defined( ENABLE_##ID ) && (ENABLE_##ID == DYNAMIC_PLUGIN) && defined(DYNAMIC_MODULES))
/**
- * REGISTER_PLUGIN is a convenience macro meant to ease writing
- * the plugin interface for our modules. In particular, using it
- * makes it possible to compile the very same code in a module
- * both as a static and a dynamic plugin.
+ * REGISTER_PLUGIN_STATIC is a convenience macro which is used to declare
+ * the plugin interface for static plugins. Code (such as game engines)
+ * which needs to implement a static plugin can simply invoke this macro
+ * with a plugin ID, plugin type and PluginObject subclass, and the correct
+ * wrapper code will be inserted.
*
- * @todo add some means to query the plugin API version etc.
+ * @see REGISTER_PLUGIN_DYNAMIC
*/
-
#define REGISTER_PLUGIN_STATIC(ID,TYPE,PLUGINCLASS) \
PluginType g_##ID##_type = TYPE; \
PluginObject *g_##ID##_getObject() { \
@@ -127,6 +111,15 @@ public:
#ifdef DYNAMIC_MODULES
+/**
+ * REGISTER_PLUGIN_DYNAMIC is a convenience macro which is used to declare
+ * the plugin interface for dynamically loadable plugins. Code (such as game engines)
+ * which needs to implement a dynamic plugin can simply invoke this macro
+ * with a plugin ID, plugin type and PluginObject subclass, and the correct
+ * wrapper code will be inserted.
+ *
+ * @see REGISTER_PLUGIN_STATIC
+ */
#define REGISTER_PLUGIN_DYNAMIC(ID,TYPE,PLUGINCLASS) \
extern "C" { \
PLUGIN_EXPORT int32 PLUGIN_getVersion() { return PLUGIN_VERSION; } \
@@ -141,44 +134,149 @@ public:
#endif // DYNAMIC_MODULES
-/** List of plugins. */
+// Abstract plugins
+
+/**
+ * Abstract base class for the plugin objects which handle plugins
+ * instantiation. Subclasses for this may be used for engine plugins
+ * and other types of plugins.
+ *
+ * FIXME: This class needs better documentation, esp. how it differs from class Plugin
+ */
+class PluginObject {
+public:
+ virtual ~PluginObject() {}
+
+ /** Returns the name of the plugin. */
+ virtual const char *getName() const = 0;
+};
+
+/**
+ * Abstract base class for the plugin system.
+ * Subclasses for this can be used to wrap both static and dynamic
+ * plugins.
+ *
+ * FIXME: This class needs better documentation, esp. how it differs from class PluginObject
+ */
+class Plugin {
+protected:
+ PluginObject *_pluginObject;
+ PluginType _type;
+
+public:
+ Plugin() : _pluginObject(0) {}
+ virtual ~Plugin() {
+ //if (isLoaded())
+ //unloadPlugin();
+ }
+
+// virtual bool isLoaded() const = 0; // TODO
+ virtual bool loadPlugin() = 0; // TODO: Rename to load() ?
+ virtual void unloadPlugin() = 0; // TODO: Rename to unload() ?
+
+ PluginType getType() const;
+ const char *getName() const;
+};
+
+/** List of Plugin instances. */
typedef Common::Array<Plugin *> PluginList;
+/**
+ * Convenience template to make it easier defining normal Plugin
+ * subclasses. Namely, the PluginSubclass will manage PluginObjects
+ * of a type specified via the PO_t template parameter.
+ */
+template<class PO_t>
+class PluginSubclass : public Plugin {
+public:
+ PO_t *operator->() const {
+ return (PO_t *)_pluginObject;
+ }
+
+ typedef Common::Array<PluginSubclass *> List;
+};
+/**
+ * Abstract base class for Plugin factories. Subclasses of this
+ * are responsible for creating plugin objects, e.g. by loading
+ * loadable modules from storage media; by creating "fake" plugins
+ * from static code; or whatever other means.
+ */
class PluginProvider {
public:
virtual ~PluginProvider() {}
/**
* Return a list of Plugin objects. The caller is responsible for actually
- * loading/unloading them (by invoking the appropriate methods).
+ * loading/unloading them (by invoking the appropriate Plugin methods).
* Furthermore, the caller is responsible for deleting these objects
* eventually.
+ *
+ * @return a list of Plugin instances
*/
virtual PluginList getPlugins() = 0;
};
+#ifdef DYNAMIC_MODULES
+
+/**
+ * Abstract base class for Plugin factories which load binary code from files.
+ * Subclasses only have to implement the createPlugin() method, and optionally
+ * can overload the other protected methods to achieve custom behavior.
+ */
class FilePluginProvider : public PluginProvider {
public:
+ /**
+ * Return a list of Plugin objects loaded via createPlugin from disk.
+ * For this, a list of directories is searched for plugin objects:
+ * The current dir and its "plugins" subdirectory (if present), a list
+ * of custom search dirs (see addCustomDirectories) and finally the
+ * directory specified via the "pluginspath" config variable (if any).
+ *
+ * @return a list of Plugin instances
+ */
virtual PluginList getPlugins();
protected:
- virtual Plugin* createPlugin(const Common::String &filename) const = 0;
+ /**
+ * Create a Plugin instance from a loadable code module with the specified name.
+ * Subclasses of FilePluginProvider have to at least overload this method.
+ * If the file is not found, or does not contain loadable code, 0 is returned instead.
+ *
+ * @param filename the name of the loadable code module
+ * @return a pointer to a Plugin instance, or 0 if an error occurred.
+ */
+ virtual Plugin *createPlugin(const Common::String &filename) const = 0;
- virtual const char* getPrefix() const;
- virtual const char* getSuffix() const;
+ /**
+ * Check if the supplied filename corresponds to a loadable plugin file in
+ * the current platform.
+ *
+ * @param filename the name of the file to check
+ * @return true if the filename corresponds to a plugin, false otherwise
+ */
+ virtual bool isPluginFilename(const Common::String &filename) const;
- virtual void addCustomDirectories(Common::StringList &dirs) const;
+ /**
+ * Optionally add to the list of directories to be searched for
+ * plugins by getPlugins().
+ *
+ * @param dirs the reference to the list of directories to be used when
+ * searching for plugins.
+ */
+ virtual void addCustomDirectories(FSList &dirs) const;
};
+#endif // DYNAMIC_MODULES
+
/**
- * Instances of this class manage all plugins, including loading them,
- * making wrapper objects of class Plugin available, and unloading them.
+ * Singleton class which manages all plugins, including loading them,
+ * managing all Plugin class instances, and unloading them.
*/
class PluginManager : public Common::Singleton<PluginManager> {
- typedef Common::List<PluginProvider *> ProviderList;
+ typedef Common::Array<PluginProvider *> ProviderList;
private:
- PluginList _plugins;
+ PluginList _plugins[PLUGIN_TYPE_MAX];
ProviderList _providers;
bool tryLoadPlugin(Plugin *plugin);
@@ -193,11 +291,9 @@ public:
void loadPlugins();
void unloadPlugins();
- void unloadPluginsExcept(const Plugin *plugin);
-
- const PluginList &getPlugins() { return _plugins; }
+ void unloadPluginsExcept(PluginType type, const Plugin *plugin);
- GameList detectGames(const FSList &fslist) const;
+ const PluginList &getPlugins(PluginType t) { return _plugins[t]; }
};
#endif