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 #include "base/plugins.h"
28 #include "common/func.h"
29 #include "common/debug.h"
31 #ifdef DYNAMIC_MODULES
32 #include "common/config-manager.h"
33 #include "common/fs.h"
38 int pluginTypeVersions
[PLUGIN_TYPE_MAX
] = {
39 PLUGIN_TYPE_ENGINE_VERSION
,
40 PLUGIN_TYPE_MUSIC_VERSION
,
46 PluginType
Plugin::getType() const {
50 const char *Plugin::getName() const {
51 return _pluginObject
->getName();
54 class StaticPlugin
: public Plugin
{
56 StaticPlugin(PluginObject
*pluginobject
, PluginType type
) {
58 assert(type
< PLUGIN_TYPE_MAX
);
59 _pluginObject
= pluginobject
;
67 virtual bool loadPlugin() { return true; }
68 virtual void unloadPlugin() {}
71 class StaticPluginProvider
: public PluginProvider
{
73 StaticPluginProvider() {
76 ~StaticPluginProvider() {
79 virtual PluginList
getPlugins() {
82 #define LINK_PLUGIN(ID) \
83 extern PluginType g_##ID##_type; \
84 extern PluginObject *g_##ID##_getObject(); \
85 pl.push_back(new StaticPlugin(g_##ID##_getObject(), g_##ID##_type));
87 // "Loader" for the static plugins.
88 // Iterate over all registered (static) plugins and load them.
91 #if PLUGIN_ENABLED_STATIC(SCUMM)
94 #if PLUGIN_ENABLED_STATIC(AGI)
97 #if PLUGIN_ENABLED_STATIC(AGOS)
100 #if PLUGIN_ENABLED_STATIC(CINE)
103 #if PLUGIN_ENABLED_STATIC(CRUISE)
106 #if PLUGIN_ENABLED_STATIC(DRASCULA)
107 LINK_PLUGIN(DRASCULA
)
109 #if PLUGIN_ENABLED_STATIC(GOB)
112 #if PLUGIN_ENABLED_STATIC(GROOVIE)
115 #if PLUGIN_ENABLED_STATIC(IGOR)
118 #if PLUGIN_ENABLED_STATIC(INNOCENT)
119 LINK_PLUGIN(INNOCENT
)
121 #if PLUGIN_ENABLED_STATIC(KYRA)
124 #if PLUGIN_ENABLED_STATIC(LURE)
127 #if PLUGIN_ENABLED_STATIC(M4)
130 #if PLUGIN_ENABLED_STATIC(MADE)
133 #if PLUGIN_ENABLED_STATIC(PARALLACTION)
134 LINK_PLUGIN(PARALLACTION
)
136 #if PLUGIN_ENABLED_STATIC(QUEEN)
139 #if PLUGIN_ENABLED_STATIC(SAGA)
142 #if PLUGIN_ENABLED_STATIC(SCI)
145 #if PLUGIN_ENABLED_STATIC(SKY)
148 #if PLUGIN_ENABLED_STATIC(SWORD1)
151 #if PLUGIN_ENABLED_STATIC(SWORD2)
154 #if PLUGIN_ENABLED_STATIC(TINSEL)
157 #if PLUGIN_ENABLED_STATIC(TOUCHE)
160 #if PLUGIN_ENABLED_STATIC(TUCKER)
165 // TODO: Use defines to disable or enable each MIDI driver as a
166 // static/dynamic plugin, like it's done for the engines
168 #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
171 #if defined(UNIX) && defined(USE_ALSA)
174 #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
177 #if defined(__MINT__)
183 #if defined(__amigaos4__)
187 LINK_PLUGIN(COREAUDIO
)
188 LINK_PLUGIN(COREMIDI
)
189 LINK_PLUGIN(QUICKTIME
)
191 #if defined(PALMOS_MODE)
192 # if defined(COMPILE_CLIE)
194 # elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM))
198 #ifdef USE_FLUIDSYNTH
199 LINK_PLUGIN(FLUIDSYNTH
)
207 LINK_PLUGIN(TIMIDITY
)
214 #ifdef DYNAMIC_MODULES
216 PluginList
FilePluginProvider::getPlugins() {
219 // Prepare the list of directories to search
220 Common::FSList pluginDirs
;
222 // Add the default directories
223 pluginDirs
.push_back(Common::FSNode("."));
224 pluginDirs
.push_back(Common::FSNode("plugins"));
226 // Add the provider's custom directories
227 addCustomDirectories(pluginDirs
);
229 // Add the user specified directory
230 Common::String
pluginsPath(ConfMan
.get("pluginspath"));
231 if (!pluginsPath
.empty())
232 pluginDirs
.push_back(Common::FSNode(pluginsPath
));
234 Common::FSList::const_iterator dir
;
235 for (dir
= pluginDirs
.begin(); dir
!= pluginDirs
.end(); dir
++) {
237 // Scan for all plugins in this directory
238 Common::FSList files
;
239 if (!dir
->getChildren(files
, Common::FSNode::kListFilesOnly
)) {
240 debug(1, "Couldn't open plugin directory '%s'", dir
->getPath().c_str());
243 debug(1, "Reading plugins from plugin directory '%s'", dir
->getPath().c_str());
246 for (Common::FSList::const_iterator i
= files
.begin(); i
!= files
.end(); ++i
) {
247 if (isPluginFilename(*i
)) {
248 pl
.push_back(createPlugin(*i
));
256 bool FilePluginProvider::isPluginFilename(const Common::FSNode
&node
) const {
257 Common::String filename
= node
.getName();
260 // Check the plugin prefix
261 if (!filename
.hasPrefix(PLUGIN_PREFIX
))
266 // Check the plugin suffix
267 if (!filename
.hasSuffix(PLUGIN_SUFFIX
))
274 void FilePluginProvider::addCustomDirectories(Common::FSList
&dirs
) const {
275 #ifdef PLUGIN_DIRECTORY
276 dirs
.push_back(Common::FSNode(PLUGIN_DIRECTORY
));
280 #endif // DYNAMIC_MODULES
284 DECLARE_SINGLETON(PluginManager
);
286 PluginManager::PluginManager() {
287 // Always add the static plugin provider.
288 addPluginProvider(new StaticPluginProvider());
291 PluginManager::~PluginManager() {
292 // Explicitly unload all loaded plugins
295 // Delete the plugin providers
296 for (ProviderList::iterator pp
= _providers
.begin();
297 pp
!= _providers
.end();
303 void PluginManager::addPluginProvider(PluginProvider
*pp
) {
304 _providers
.push_back(pp
);
307 void PluginManager::loadPlugins() {
308 for (ProviderList::iterator pp
= _providers
.begin();
309 pp
!= _providers
.end();
311 PluginList
pl((*pp
)->getPlugins());
312 Common::for_each(pl
.begin(), pl
.end(), Common::bind1st(Common::mem_fun(&PluginManager::tryLoadPlugin
), this));
317 void PluginManager::unloadPlugins() {
318 for (int i
= 0; i
< PLUGIN_TYPE_MAX
; i
++)
319 unloadPluginsExcept((PluginType
)i
, NULL
);
322 void PluginManager::unloadPluginsExcept(PluginType type
, const Plugin
*plugin
) {
323 Plugin
*found
= NULL
;
324 for (PluginList::iterator p
= _plugins
[type
].begin(); p
!= _plugins
[type
].end(); ++p
) {
328 (*p
)->unloadPlugin();
332 _plugins
[type
].clear();
334 _plugins
[type
].push_back(found
);
338 bool PluginManager::tryLoadPlugin(Plugin
*plugin
) {
340 // Try to load the plugin
341 if (plugin
->loadPlugin()) {
342 // The plugin is valid, see if it provides the same module as an
343 // already loaded one and should replace it.
346 PluginList::iterator pl
= _plugins
[plugin
->getType()].begin();
347 while (!found
&& pl
!= _plugins
[plugin
->getType()].end()) {
348 if (!strcmp(plugin
->getName(), (*pl
)->getName())) {
349 // Found a duplicated module. Replace the old one.
353 debug(1, "Replaced the duplicated plugin: '%s'", plugin
->getName());
359 // If it provides a new module, just add it to the list of known plugins.
360 _plugins
[plugin
->getType()].push_back(plugin
);
365 // Failed to load the plugin
374 #include "engines/metaengine.h"
376 DECLARE_SINGLETON(EngineManager
);
378 GameDescriptor
EngineManager::findGame(const Common::String
&gameName
, const EnginePlugin
**plugin
) const {
379 // Find the GameDescriptor for this target
380 const EnginePlugin::List
&plugins
= getPlugins();
381 GameDescriptor result
;
386 EnginePlugin::List::const_iterator iter
= plugins
.begin();
387 for (iter
= plugins
.begin(); iter
!= plugins
.end(); ++iter
) {
388 result
= (**iter
)->findGame(gameName
.c_str());
389 if (!result
.gameid().empty()) {
398 GameList
EngineManager::detectGames(const Common::FSList
&fslist
) const {
401 const EnginePlugin::List
&plugins
= getPlugins();
403 // Iterate over all known games and for each check if it might be
404 // the game in the presented directory.
405 EnginePlugin::List::const_iterator iter
;
406 for (iter
= plugins
.begin(); iter
!= plugins
.end(); ++iter
) {
407 candidates
.push_back((**iter
)->detectGames(fslist
));
413 const EnginePlugin::List
&EngineManager::getPlugins() const {
414 return (const EnginePlugin::List
&)PluginManager::instance().getPlugins(PLUGIN_TYPE_ENGINE
);
420 #include "sound/musicplugin.h"
422 DECLARE_SINGLETON(MusicManager
);
424 const MusicPlugin::List
&MusicManager::getPlugins() const {
425 return (const MusicPlugin::List
&)PluginManager::instance().getPlugins(PLUGIN_TYPE_MUSIC
);