Revised Engine plugin API to only provide a single func which returns a MetaEngine instance. Used this to simplify the rest of the plugin system

svn-id: r30780
This commit is contained in:
Max Horn 2008-02-03 18:56:47 +00:00
parent 15975bdf73
commit 8a73356a2d
21 changed files with 76 additions and 222 deletions

View File

@ -27,95 +27,59 @@
#define BACKENDS_PLUGINS_DYNAMICPLUGIN_H
#include "base/plugins.h"
/** Type of factory functions which make new Engine objects. */
typedef PluginError (*EngineFactory)(OSystem *syst, Engine **engine);
typedef const char *(*NameFunc)();
typedef GameDescriptor (*GameIDQueryFunc)(const char *gameid);
typedef GameList (*GameIDListFunc)();
typedef GameList (*DetectFunc)(const FSList &fslist);
#include "engines/metaengine.h"
class DynamicPlugin : public Plugin {
protected:
typedef void (*VoidFunc)();
Common::String _name;
Common::String _copyright;
GameIDQueryFunc _qf;
EngineFactory _ef;
DetectFunc _df;
GameList _games;
typedef MetaEngine *(*MetaAllocFunc)();
MetaEngine *_metaengine;
virtual VoidFunc findSymbol(const char *symbol) = 0;
public:
DynamicPlugin() : _qf(0), _ef(0), _df(0), _games() {}
const char *getName() const { return _name.c_str(); }
const char *getCopyright() const { return _copyright.c_str(); }
PluginError createInstance(OSystem *syst, Engine **engine) const {
assert(_ef);
return (*_ef)(syst, engine);
DynamicPlugin() : _metaengine(0) {}
~DynamicPlugin() {
delete _metaengine;
}
GameList getSupportedGames() const { return _games; }
const char *getName() const {
return _metaengine->getName();
}
const char *getCopyright() const {
return _metaengine->getCopyright();
}
PluginError createInstance(OSystem *syst, Engine **engine) const {
return _metaengine->createInstance(syst, engine);
}
GameList getSupportedGames() const {
return _metaengine->getSupportedGames();
}
GameDescriptor findGame(const char *gameid) const {
assert(_qf);
return (*_qf)(gameid);
return _metaengine->findGame(gameid);
}
GameList detectGames(const FSList &fslist) const {
assert(_df);
return (*_df)(fslist);
return _metaengine->detectGames(fslist);
}
virtual bool loadPlugin() {
// Query the plugin's name
NameFunc nameFunc = (NameFunc)findSymbol("PLUGIN_name");
if (!nameFunc) {
unloadPlugin();
return false;
}
_name = nameFunc();
// Query the plugin's copyright
nameFunc = (NameFunc)findSymbol("PLUGIN_copyright");
if (!nameFunc) {
unloadPlugin();
return false;
}
_copyright = nameFunc();
// Query the plugin for the game ids it supports
GameIDListFunc gameListFunc = (GameIDListFunc)findSymbol("PLUGIN_gameIDList");
if (!gameListFunc) {
unloadPlugin();
return false;
}
_games = gameListFunc();
// Retrieve the gameid query function
_qf = (GameIDQueryFunc)findSymbol("PLUGIN_findGameID");
if (!_qf) {
MetaAllocFunc metaAlloc = (MetaAllocFunc)findSymbol("PLUGIN_MetaEngine_alloc");
if (!metaAlloc) {
unloadPlugin();
return false;
}
// Retrieve the factory function
_ef = (EngineFactory)findSymbol("PLUGIN_createEngine");
if (!_ef) {
unloadPlugin();
return false;
}
// Retrieve the detector function
_df = (DetectFunc)findSymbol("PLUGIN_detectGames");
if (!_df) {
_metaengine = metaAlloc();
if (!_metaengine) {
unloadPlugin();
return false;
}

View File

@ -25,42 +25,47 @@
#include "base/plugins.h"
#include "common/util.h"
#include "engines/metaengine.h"
#ifndef DYNAMIC_MODULES
class StaticPlugin : public Plugin {
PluginRegistrator *_plugin;
MetaEngine *_metaengine;
public:
StaticPlugin(PluginRegistrator *plugin)
: _plugin(plugin) {
assert(_plugin);
StaticPlugin(MetaEngine *metaengine)
: _metaengine(metaengine) {
assert(_metaengine);
}
~StaticPlugin() {
delete _plugin;
delete _metaengine;
}
virtual bool loadPlugin() { return true; }
virtual void unloadPlugin() {}
const char *getName() const { return _plugin->_name; }
const char *getCopyright() const { return _plugin->_copyright; }
PluginError createInstance(OSystem *syst, Engine **engine) const {
assert(_plugin->_ef);
return (*_plugin->_ef)(syst, engine);
const char *getName() const {
return _metaengine->getName();
}
GameList getSupportedGames() const { return _plugin->_games; }
const char *getCopyright() const {
return _metaengine->getCopyright();
}
PluginError createInstance(OSystem *syst, Engine **engine) const {
return _metaengine->createInstance(syst, engine);
}
GameList getSupportedGames() const {
return _metaengine->getSupportedGames();
}
GameDescriptor findGame(const char *gameid) const {
assert(_plugin->_qf);
return (*_plugin->_qf)(gameid);
return _metaengine->findGame(gameid);
}
GameList detectGames(const FSList &fslist) const {
assert(_plugin->_df);
return (*_plugin->_df)(fslist);
return _metaengine->detectGames(fslist);
}
};
@ -76,15 +81,11 @@ public:
PluginList pl;
#define LINK_PLUGIN(ID) \
extern PluginRegistrator *g_##ID##_PluginReg; \
extern void g_##ID##_PluginReg_alloc(); \
g_##ID##_PluginReg_alloc(); \
plugin = g_##ID##_PluginReg; \
pl.push_back(new StaticPlugin(plugin));
extern MetaEngine *g_##ID##_MetaEngine_alloc(); \
pl.push_back(new StaticPlugin(g_##ID##_MetaEngine_alloc()));
// "Loader" for the static plugins.
// Iterate over all registered (static) plugins and load them.
PluginRegistrator *plugin;
#ifndef DISABLE_SCUMM
LINK_PLUGIN(SCUMM)

View File

@ -35,6 +35,7 @@
class Engine;
class FSList;
class MetaEngine;
class OSystem;
/**
@ -67,75 +68,25 @@ public:
* makes it possible to compile the very same code in a module
* both as a static and a dynamic plugin.
*
* Each plugin has to define the following functions:
* - GameList Engine_##ID##_gameIDList()
* -> returns a list of gameid/desc pairs. Only used to implement '--list-games'.
* - GameDescriptor Engine_##ID##_findGameID(const char *gameid)
* -> asks the Engine for a GameDescriptor matching the gameid. If that is not
* possible, the engine MUST set the gameid of the returned value to 0.
* Note: This MUST succeed for every gameID on the list returned by
* gameIDList(), but MAY also work for additional gameids (e.g. to support
* obsolete targets).
* - GameList Engine_##ID##_detectGames(const FSList &fslist)
* -> scans through the given file list (usually the contents of a directory),
* and attempts to detects games present in that location.
* - PluginError Engine_##ID##_create(OSystem *syst, Engine **engine)
* -> factory function, create an instance of the Engine class.
*
* @todo add some means to query the plugin API version etc.
*/
#ifndef DYNAMIC_MODULES
#define REGISTER_PLUGIN(ID,name,copyright) \
PluginRegistrator *g_##ID##_PluginReg; \
void g_##ID##_PluginReg_alloc() { \
g_##ID##_PluginReg = new PluginRegistrator(name, copyright, \
Engine_##ID##_gameIDList(), \
Engine_##ID##_findGameID, \
Engine_##ID##_create, \
Engine_##ID##_detectGames \
);\
#define REGISTER_PLUGIN(ID,METAENGINE) \
MetaEngine *g_##ID##_MetaEngine_alloc() { \
return new METAENGINE(); \
} \
void dummyFuncToAllowTrailingSemicolon()
#else
#define REGISTER_PLUGIN(ID,name,copyright) \
#define REGISTER_PLUGIN(ID,METAENGINE) \
extern "C" { \
PLUGIN_EXPORT const char *PLUGIN_name() { return name; } \
PLUGIN_EXPORT const char *PLUGIN_copyright() { return copyright; } \
PLUGIN_EXPORT GameList PLUGIN_gameIDList() { return Engine_##ID##_gameIDList(); } \
PLUGIN_EXPORT GameDescriptor PLUGIN_findGameID(const char *gameid) { return Engine_##ID##_findGameID(gameid); } \
PLUGIN_EXPORT PluginError PLUGIN_createEngine(OSystem *syst, Engine **engine) { return Engine_##ID##_create(syst, engine); } \
PLUGIN_EXPORT GameList PLUGIN_detectGames(const FSList &fslist) { return Engine_##ID##_detectGames(fslist); } \
PLUGIN_EXPORT MetaEngine *PLUGIN_MetaEngine_alloc() { \
return new METAENGINE(); \
} \
} \
void dummyFuncToAllowTrailingSemicolon()
#endif
#ifndef DYNAMIC_MODULES
/**
* The PluginRegistrator class is used by the static version of REGISTER_PLUGIN
* to allow static 'plugins' to register with the PluginManager.
*/
class PluginRegistrator {
friend class StaticPlugin;
public:
typedef GameDescriptor (*GameIDQueryFunc)(const char *gameid);
typedef PluginError (*EngineFactory)(OSystem *syst, Engine **engine);
typedef GameList (*DetectFunc)(const FSList &fslist);
protected:
const char *_name;
const char *_copyright;
GameIDQueryFunc _qf;
EngineFactory _ef;
DetectFunc _df;
GameList _games;
public:
PluginRegistrator(const char *name, const char *copyright, GameList games, GameIDQueryFunc qf, EngineFactory ef, DetectFunc df)
: _name(name), _copyright(copyright), _qf(qf), _ef(ef), _df(df), _games(games) {}
};
#endif
/** List of plugins. */
typedef Common::Array<Plugin *> PluginList;
@ -154,13 +105,9 @@ public:
virtual PluginList getPlugins() = 0;
};
//class PluginManager;
/**
* Instances of this class manage all plugins, including loading them,
* making wrapper objects of class Plugin available, and unloading them.
*
* @todo Add support for dynamic plugins (this may need additional API, e.g. for a plugin path)
*/
class PluginManager : public Common::Singleton<PluginManager> {
typedef Common::List<PluginProvider *> ProviderList;

View File

@ -2284,7 +2284,5 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common:
return res;
}
META_COMPATIBILITY_WRAPPER(AGI, AgiMetaEngine);
REGISTER_PLUGIN(AGI, "AGI preAGI + v2 + v3 Engine", "Sierra AGI Engine (C) Sierra On-Line Software");
REGISTER_PLUGIN(AGI, AgiMetaEngine);

View File

@ -151,9 +151,7 @@ bool AgosMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return res;
}
META_COMPATIBILITY_WRAPPER(AGOS, AgosMetaEngine);
REGISTER_PLUGIN(AGOS, "AGOS", "AGOS (C) Adventure Soft");
REGISTER_PLUGIN(AGOS, AgosMetaEngine);
namespace AGOS {

View File

@ -511,6 +511,4 @@ bool CineMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return gd != 0;
}
META_COMPATIBILITY_WRAPPER(CINE, CineMetaEngine);
REGISTER_PLUGIN(CINE, "Cinematique evo 1 engine", "Future Wars & Operation Stealth (C) Delphine Software");
REGISTER_PLUGIN(CINE, CineMetaEngine);

View File

@ -146,6 +146,4 @@ bool CruiseMetaEngine::createInstance(OSystem *syst, Engine **engine, const Comm
return gd != 0;
}
META_COMPATIBILITY_WRAPPER(CRUISE, CruiseMetaEngine);
REGISTER_PLUGIN(CRUISE, "Cinematique evo 2 engine", "Cruise for a Corpse (C) Delphine Software");
REGISTER_PLUGIN(CRUISE, CruiseMetaEngine);

View File

@ -186,6 +186,4 @@ bool DrasculaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Co
return gd != 0;
}
META_COMPATIBILITY_WRAPPER(DRASCULA, DrasculaMetaEngine);
REGISTER_PLUGIN(DRASCULA, "Drascula Engine", "Drascula Engine (C) 2000 Alcachofa Soft, 1996 (C) Digital Dreams Multimedia, 1994 (C) Emilio de Paz");
REGISTER_PLUGIN(DRASCULA, DrasculaMetaEngine);

View File

@ -1779,9 +1779,7 @@ bool GobMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common:
return gd != 0;
}
META_COMPATIBILITY_WRAPPER(GOB, GobMetaEngine);
REGISTER_PLUGIN(GOB, "Gob Engine", "Goblins Games (C) Coktel Vision");
REGISTER_PLUGIN(GOB, GobMetaEngine);
namespace Gob {

View File

@ -134,6 +134,4 @@ bool IgorMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return gd != 0;
}
META_COMPATIBILITY_WRAPPER(IGOR, IgorMetaEngine);
REGISTER_PLUGIN(IGOR, "Igor: Objective Uikokahonia", "Igor: Objective Uikokahonia (C) Pendulo Studios");
REGISTER_PLUGIN(IGOR, IgorMetaEngine);

View File

@ -484,6 +484,4 @@ bool KyraMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return res;
}
META_COMPATIBILITY_WRAPPER(KYRA, KyraMetaEngine);
REGISTER_PLUGIN(KYRA, "Legend of Kyrandia Engine", "The Legend of Kyrandia (C) Westwood Studios");
REGISTER_PLUGIN(KYRA, KyraMetaEngine);

View File

@ -197,6 +197,4 @@ bool LureMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return gd != 0;
}
META_COMPATIBILITY_WRAPPER(LURE, LureMetaEngine);
REGISTER_PLUGIN(LURE, "Lure of the Temptress Engine", "Lure of the Temptress (C) Revolution");
REGISTER_PLUGIN(LURE, LureMetaEngine);

View File

@ -57,25 +57,4 @@ public:
virtual PluginError createInstance(OSystem *syst, Engine **engine) const = 0;
};
/**
* The META_COMPATIBILITY_WRAPPER macro is there to ease the transition from the
* old plugin API to the new MetaEngine class. Ultimately, this macro will go
* and REGISTER_PLUGIN will be changed to simply take an ID and a METACLASS.
* Until then, use META_COMPATIBILITY_WRAPPER + REGISTER_PLUGIN.
*/
#define META_COMPATIBILITY_WRAPPER(ID,METACLASS) \
static MetaEngine &getMetaEngine() { \
static MetaEngine *meta = 0; \
if (!meta) meta = new METACLASS(); \
return *meta; \
} \
GameList Engine_##ID##_gameIDList() { return getMetaEngine().getSupportedGames(); } \
GameDescriptor Engine_##ID##_findGameID(const char *gameid) { return getMetaEngine().findGame(gameid); } \
PluginError Engine_##ID##_create(OSystem *syst, Engine **engine) { return getMetaEngine().createInstance(syst, engine); } \
GameList Engine_##ID##_detectGames(const FSList &fslist) { return getMetaEngine().detectGames(fslist); } \
void dummyFuncToAllowTrailingSemicolon()
#endif

View File

@ -218,6 +218,4 @@ bool ParallactionMetaEngine::createInstance(OSystem *syst, Engine **engine, cons
return res;
}
META_COMPATIBILITY_WRAPPER(PARALLACTION, ParallactionMetaEngine);
REGISTER_PLUGIN(PARALLACTION, "Parallaction engine", "Nippon Safes Inc. (C) Dynabyte");
REGISTER_PLUGIN(PARALLACTION, ParallactionMetaEngine);

View File

@ -127,9 +127,7 @@ PluginError QueenMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
return kNoError;
}
META_COMPATIBILITY_WRAPPER(QUEEN, QueenMetaEngine);
REGISTER_PLUGIN(QUEEN, "Flight of the Amazon Queen", "Flight of the Amazon Queen (C) John Passfield and Steve Stamatiadis");
REGISTER_PLUGIN(QUEEN, QueenMetaEngine);
namespace Queen {

View File

@ -164,9 +164,7 @@ bool SagaMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common
return gd != 0;
}
META_COMPATIBILITY_WRAPPER(SAGA, SagaMetaEngine);
REGISTER_PLUGIN(SAGA, "SAGA Engine", "Inherit the Earth (C) Wyrmkeep Entertainment");
REGISTER_PLUGIN(SAGA, SagaMetaEngine);
namespace Saga {

View File

@ -928,8 +928,4 @@ const char *ScummMetaEngine::getCopyright() const {
"Humongous SCUMM Games (C) Humongous";
}
META_COMPATIBILITY_WRAPPER(SCUMM, ScummMetaEngine);
REGISTER_PLUGIN(SCUMM, "Scumm Engine",
"LucasArts SCUMM Games (C) LucasArts\n"
"Humongous SCUMM Games (C) Humongous" );
REGISTER_PLUGIN(SCUMM, ScummMetaEngine);

View File

@ -194,10 +194,7 @@ PluginError SkyMetaEngine::createInstance(OSystem *syst, Engine **engine) const
return kNoError;
}
META_COMPATIBILITY_WRAPPER(SKY, SkyMetaEngine);
REGISTER_PLUGIN(SKY, "Beneath a Steel Sky", "Beneath a Steel Sky (C) Revolution");
REGISTER_PLUGIN(SKY, SkyMetaEngine);
namespace Sky {

View File

@ -187,9 +187,7 @@ PluginError SwordMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
return kNoError;
}
META_COMPATIBILITY_WRAPPER(SWORD1, SwordMetaEngine);
REGISTER_PLUGIN(SWORD1, "Broken Sword", "Broken Sword Games (C) Revolution");
REGISTER_PLUGIN(SWORD1, SwordMetaEngine);
namespace Sword1 {

View File

@ -180,9 +180,7 @@ PluginError Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) con
return kNoGameDataFoundError;
}
META_COMPATIBILITY_WRAPPER(SWORD2, Sword2MetaEngine);
REGISTER_PLUGIN(SWORD2, "Broken Sword 2", "Broken Sword Games (C) Revolution");
REGISTER_PLUGIN(SWORD2, Sword2MetaEngine);
namespace Sword2 {

View File

@ -147,6 +147,4 @@ bool ToucheMetaEngine::createInstance(OSystem *syst, Engine **engine, const Comm
return gd != 0;
}
META_COMPATIBILITY_WRAPPER(TOUCHE, ToucheMetaEngine);
REGISTER_PLUGIN(TOUCHE, "Touche Engine", "Touche: The Adventures of the 5th Musketeer (C) Clipper Software");
REGISTER_PLUGIN(TOUCHE, ToucheMetaEngine);