23 #include "pluginloader.h"
25 #include "configuration/doomseekerconfig.h"
26 #include "ini/inisection.h"
27 #include "ini/inivariable.h"
29 #include "plugins/engineplugin.h"
30 #include "serverapi/masterclient.h"
31 #include "strings.hpp"
35 #include <QScopedPointer>
40 DClass<PluginLoader::Plugin>
45 QScopedPointer<QLibrary> library;
50 PluginLoader::Plugin::Plugin(
unsigned int type, QString file)
57 d->library.reset(
new QLibrary(file));
58 if (d->library->load())
60 auto doomSeekerABI = (
unsigned int (*)())(d->library->resolve(
"doomSeekerABI"));
61 if (!doomSeekerABI || doomSeekerABI() != DOOMSEEKER_ABI_VERSION)
65 if (doomSeekerABI !=
nullptr)
68 "plugin ABI version mismatch; plugin: %1, Doomseeker: %2").arg(
69 doomSeekerABI()).arg(DOOMSEEKER_ABI_VERSION);
73 reason = QObject::tr(
"plugin doesn't report its ABI version");
75 gLog << QObject::tr(
"Cannot load plugin %1, reason: %2.").arg(file, reason);
80 auto doomSeekerInit = (
EnginePlugin * (*)())(d->library->resolve(
"doomSeekerInit"));
81 if (doomSeekerInit ==
nullptr)
87 d->info = doomSeekerInit();
88 if (!info()->data()->valid)
94 gLog << QObject::tr(
"Loaded plugin: \"%1\"!").arg(info()->data()->name);
99 gLog << QObject::tr(
"Failed to open plugin: %1").arg(file);
100 gLog << QString(
"Last error was: %1").arg(d->library->errorString());
104 PluginLoader::Plugin::~Plugin()
111 return (
void *) d->library->resolve(func);
119 void PluginLoader::Plugin::initConfig()
123 IniSection cfgSection = gConfig.iniSectionForPlugin(
info()->data()->name);
124 info()->setConfig(cfgSection);
128 bool PluginLoader::Plugin::isValid()
const
130 return d->library !=
nullptr && d->library->isLoaded();
133 void PluginLoader::Plugin::unload()
146 QMap<QString, bool> pluginsEnabled;
147 QString pluginsDirectory;
148 QList<PluginLoader::Plugin *> plugins;
150 bool isForbiddenPlugin(
const QString &file)
const
152 static const QString PREFIX =
"lib";
153 QString name = QFileInfo(file).baseName().toLower();
154 if (name.startsWith(PREFIX))
155 name = name.mid(PREFIX.size());
156 if (pluginsEnabled.contains(name))
157 return !pluginsEnabled[name];
158 return name.contains(
"srb2")
159 || name.contains(
"vavoom");
168 const QMap<QString,
bool> &pluginsEnabled)
171 d->pluginsEnabled = pluginsEnabled;
172 for (
const QString &dir : directories)
174 d->pluginsDirectory = dir;
182 gLog << QObject::tr(
"Failed to locate plugins.");
186 PluginLoader::~PluginLoader()
188 qDeleteAll(d->plugins);
193 qDeleteAll(d->plugins);
199 if (staticInstance !=
nullptr)
201 delete staticInstance;
202 staticInstance =
nullptr;
206 bool PluginLoader::filesInDir()
208 gLog << QString(
"Attempting to load plugins from directory: %1").arg(d->pluginsDirectory);
209 QDir dir(d->pluginsDirectory);
215 QStringList windowsNamesFilter;
216 windowsNamesFilter <<
"*.dll";
217 dir.setNameFilters(windowsNamesFilter);
219 for (
const QString &entry : dir.entryList(QDir::Files))
221 QString pluginFilePath = dir.filePath(entry);
222 if (d->isForbiddenPlugin(pluginFilePath))
224 gLog << QObject::tr(
"Skipping loading of forbidden plugin: %1").arg(pluginFilePath);
228 Plugin *
plugin =
new Plugin(d->type, pluginFilePath);
229 if (plugin->isValid())
230 d->plugins << plugin;
249 if (staticInstance !=
nullptr)
251 qDebug() <<
"Attempting to re-init PluginLoader";
255 staticInstance =
new PluginLoader(MAKEID(
'E',
'N',
'G',
'N'), directories, pluginsEnabled);
262 plugin->initConfig();
268 assert(staticInstance !=
nullptr);
269 return staticInstance;
274 return d->plugins.size();
277 const QList<PluginLoader::Plugin *> &PluginLoader::plugins()
const
284 return d->plugins[index];
297 QString mangledName = QString(name).replace(
" ",
"");
298 for (
int i = 0; i < d->plugins.size(); ++i)
300 QString mangledCandidate = QString(d->plugins[i]->info()->data()->name).replace(
" ",
"");
301 if (mangledName.compare(mangledCandidate) == 0)
312 d->pluginsDirectory = pluginsDirectory;
319 return d->plugins[index];