1 /* ScummVM - Graphic Adventure Engine
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #ifndef BASE_PLUGINS_H
27 #define BASE_PLUGINS_H
29 #include "common/error.h"
30 #include "common/singleton.h"
31 #include "common/util.h"
40 * @page pagePlugins An overview of the ScummVM plugin system
41 * This is a brief overview of how plugins (dynamically loadable code modules)
42 * work in ScummVM. We will explain how to write plugins, how they work internally,
43 * and sketch how porters can add support for them in their ports.
45 * \section secPluginImpl Implementing a plugin
48 * \section secPluginUse Using plugins
51 * \section secPluginInternals How plugins work internally
54 * \section secPluginBackend How to add support for dynamic plugins to a port
62 /** Global Plugin API version */
63 #define PLUGIN_VERSION 1
66 PLUGIN_TYPE_ENGINE
= 0,
68 /* PLUGIN_TYPE_SCALER, */ // TODO: Add graphics scaler plugins
73 // TODO: Make the engine API version depend on ScummVM's version
74 // because of the backlinking (posibly from the SVN revision)
75 #define PLUGIN_TYPE_ENGINE_VERSION 1
76 #define PLUGIN_TYPE_MUSIC_VERSION 1
78 extern int pluginTypeVersions
[PLUGIN_TYPE_MAX
];
83 #define STATIC_PLUGIN 1
84 #define DYNAMIC_PLUGIN 2
86 #define PLUGIN_ENABLED_STATIC(ID) \
87 (ENABLE_##ID && !PLUGIN_ENABLED_DYNAMIC(ID))
89 #define PLUGIN_ENABLED_DYNAMIC(ID) \
90 (ENABLE_##ID && (ENABLE_##ID == DYNAMIC_PLUGIN) && DYNAMIC_MODULES)
93 * REGISTER_PLUGIN_STATIC is a convenience macro which is used to declare
94 * the plugin interface for static plugins. Code (such as game engines)
95 * which needs to implement a static plugin can simply invoke this macro
96 * with a plugin ID, plugin type and PluginObject subclass, and the correct
97 * wrapper code will be inserted.
99 * @see REGISTER_PLUGIN_DYNAMIC
101 #define REGISTER_PLUGIN_STATIC(ID,TYPE,PLUGINCLASS) \
102 PluginType g_##ID##_type = TYPE; \
103 PluginObject *g_##ID##_getObject() { \
104 return new PLUGINCLASS(); \
106 void dummyFuncToAllowTrailingSemicolon()
108 #ifdef DYNAMIC_MODULES
111 * REGISTER_PLUGIN_DYNAMIC is a convenience macro which is used to declare
112 * the plugin interface for dynamically loadable plugins. Code (such as game engines)
113 * which needs to implement a dynamic plugin can simply invoke this macro
114 * with a plugin ID, plugin type and PluginObject subclass, and the correct
115 * wrapper code will be inserted.
117 * @see REGISTER_PLUGIN_STATIC
119 #define REGISTER_PLUGIN_DYNAMIC(ID,TYPE,PLUGINCLASS) \
121 PLUGIN_EXPORT int32 PLUGIN_getVersion() { return PLUGIN_VERSION; } \
122 PLUGIN_EXPORT int32 PLUGIN_getType() { return TYPE; } \
123 PLUGIN_EXPORT int32 PLUGIN_getTypeVersion() { return TYPE##_VERSION; } \
124 PLUGIN_EXPORT PluginObject *PLUGIN_getObject() { \
125 return new PLUGINCLASS(); \
128 void dummyFuncToAllowTrailingSemicolon()
130 #endif // DYNAMIC_MODULES
136 * Abstract base class for the plugin objects which handle plugins
137 * instantiation. Subclasses for this may be used for engine plugins
138 * and other types of plugins.
140 * FIXME: This class needs better documentation, esp. how it differs from class Plugin
144 virtual ~PluginObject() {}
146 /** Returns the name of the plugin. */
147 virtual const char *getName() const = 0;
151 * Abstract base class for the plugin system.
152 * Subclasses for this can be used to wrap both static and dynamic
155 * FIXME: This class needs better documentation, esp. how it differs from class PluginObject
159 PluginObject
*_pluginObject
;
163 Plugin() : _pluginObject(0) {}
169 // virtual bool isLoaded() const = 0; // TODO
170 virtual bool loadPlugin() = 0; // TODO: Rename to load() ?
171 virtual void unloadPlugin() = 0; // TODO: Rename to unload() ?
173 PluginType
getType() const;
174 const char *getName() const;
177 /** List of Plugin instances. */
178 typedef Common::Array
<Plugin
*> PluginList
;
181 * Convenience template to make it easier defining normal Plugin
182 * subclasses. Namely, the PluginSubclass will manage PluginObjects
183 * of a type specified via the PO_t template parameter.
186 class PluginSubclass
: public Plugin
{
188 PO_t
*operator->() const {
189 return (PO_t
*)_pluginObject
;
192 typedef Common::Array
<PluginSubclass
*> List
;
196 * Abstract base class for Plugin factories. Subclasses of this
197 * are responsible for creating plugin objects, e.g. by loading
198 * loadable modules from storage media; by creating "fake" plugins
199 * from static code; or whatever other means.
201 class PluginProvider
{
203 virtual ~PluginProvider() {}
206 * Return a list of Plugin objects. The caller is responsible for actually
207 * loading/unloading them (by invoking the appropriate Plugin methods).
208 * Furthermore, the caller is responsible for deleting these objects
211 * @return a list of Plugin instances
213 virtual PluginList
getPlugins() = 0;
216 #ifdef DYNAMIC_MODULES
219 * Abstract base class for Plugin factories which load binary code from files.
220 * Subclasses only have to implement the createPlugin() method, and optionally
221 * can overload the other protected methods to achieve custom behavior.
223 class FilePluginProvider
: public PluginProvider
{
226 * Return a list of Plugin objects loaded via createPlugin from disk.
227 * For this, a list of directories is searched for plugin objects:
228 * The current dir and its "plugins" subdirectory (if present), a list
229 * of custom search dirs (see addCustomDirectories) and finally the
230 * directory specified via the "pluginspath" config variable (if any).
232 * @return a list of Plugin instances
234 virtual PluginList
getPlugins();
238 * Create a Plugin instance from a loadable code module with the specified name.
239 * Subclasses of FilePluginProvider have to at least overload this method.
240 * If the file is not found, or does not contain loadable code, 0 is returned instead.
242 * @param node the FSNode of the loadable code module
243 * @return a pointer to a Plugin instance, or 0 if an error occurred.
245 virtual Plugin
*createPlugin(const Common::FSNode
&node
) const = 0;
248 * Check if the supplied file corresponds to a loadable plugin file in
249 * the current platform. Usually, this will just check the file name.
251 * @param node the FSNode of the file to check
252 * @return true if the filename corresponds to a plugin, false otherwise
254 virtual bool isPluginFilename(const Common::FSNode
&node
) const;
257 * Optionally add to the list of directories to be searched for
258 * plugins by getPlugins().
260 * @param dirs the reference to the list of directories to be used when
261 * searching for plugins.
263 virtual void addCustomDirectories(Common::FSList
&dirs
) const;
266 #endif // DYNAMIC_MODULES
269 * Singleton class which manages all plugins, including loading them,
270 * managing all Plugin class instances, and unloading them.
272 class PluginManager
: public Common::Singleton
<PluginManager
> {
273 typedef Common::Array
<PluginProvider
*> ProviderList
;
275 PluginList _plugins
[PLUGIN_TYPE_MAX
];
276 ProviderList _providers
;
278 bool tryLoadPlugin(Plugin
*plugin
);
280 friend class Common::Singleton
<SingletonBaseType
>;
286 void addPluginProvider(PluginProvider
*pp
);
289 void unloadPlugins();
290 void unloadPluginsExcept(PluginType type
, const Plugin
*plugin
);
292 const PluginList
&getPlugins(PluginType t
) { return _plugins
[t
]; }