diff options
Diffstat (limited to 'base/plugins.h')
-rw-r--r-- | base/plugins.h | 240 |
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 |