From 1186d5765f1940d97d8376085ed33718a3a2b3d6 Mon Sep 17 00:00:00 2001 From: APTX Date: Sun, 26 Feb 2017 21:24:26 +0100 Subject: [PATCH] Extend PluginManager to manage more than one plugin at a time Currently errorString always returns an empty string as there is more than one potential error. This method should be removed in the future. --- core/player.cpp | 5 ++- core/pluginmanager.cpp | 87 ++++++++++++++++++++++++++++++++++-------- core/pluginmanager.h | 26 ++++++++++--- 3 files changed, 95 insertions(+), 23 deletions(-) diff --git a/core/player.cpp b/core/player.cpp index a2b3317..b20b42c 100644 --- a/core/player.cpp +++ b/core/player.cpp @@ -212,8 +212,9 @@ void Player::loadBackend() { #endif m_pluginManager.setPluginDirectories(pluginPaths); m_pluginManager.setPluginPrefix("backend"); - m_pluginManager.loadDefaultPlugin(); - m_plugin = m_pluginManager.instance(); + m_pluginManager.setPreferredPlugins({"mpv"}); + m_pluginManager.loadBestPlugin(); + m_plugin = m_pluginManager.bestInstance(); if (!m_plugin) throw std::runtime_error{std::string("Failed to load backend: ") + qPrintable(m_pluginManager.errorString())}; diff --git a/core/pluginmanager.cpp b/core/pluginmanager.cpp index 34328d7..bc8645d 100644 --- a/core/pluginmanager.cpp +++ b/core/pluginmanager.cpp @@ -4,9 +4,11 @@ Q_LOGGING_CATEGORY(pluginManagerCategory, "PluginManager") -PluginManager::PluginManager() {} +PluginManager::PluginManager(QObject *parent) : QObject{parent} {} -QString PluginManager::errorString() const { return m_loader.errorString(); } +PluginManager::~PluginManager() { qDeleteAll(m_plugins); } + +QString PluginManager::errorString() const { return ""; } QStringList PluginManager::pluginDirectories() const { return m_pluginDirectories; @@ -14,6 +16,10 @@ QStringList PluginManager::pluginDirectories() const { QString PluginManager::pluginPrefix() const { return m_pluginPrefix; } +QStringList PluginManager::preferredPlugins() const { + return m_preferredPlugins; +} + void PluginManager::setPluginDirectories(QStringList pluginDirectories) { if (m_pluginDirectories == pluginDirectories) return; @@ -30,34 +36,85 @@ void PluginManager::setPluginPrefix(QString pluginPrefix) { emit pluginPrefixChanged(pluginPrefix); } +void PluginManager::setPreferredPlugins(QStringList preferredPlugins) { + if (m_preferredPlugins == preferredPlugins) + return; + + m_preferredPlugins = preferredPlugins; + emit preferredPluginsChanged(preferredPlugins); +} + bool PluginManager::load(const QString &plugin) { - if (m_loader.isLoaded()) - if (!m_loader.unload()) - return false; + + const auto it = m_plugins.find(plugin); + + if (it != m_plugins.end()) { + return true; + } + + auto loader = new QPluginLoader{this}; for (const auto &path : m_pluginDirectories) { const QString pluginPath = QString{"%1/%2_%3"}.arg(path).arg(m_pluginPrefix).arg(plugin); qCInfo(pluginManagerCategory) << "Trying to load plugin" << pluginPath; - m_loader.setFileName(pluginPath); + loader->setFileName(pluginPath); - if (m_loader.load()) { - qCInfo(pluginManagerCategory) << "Load successful"; + if (loader->load()) { + qCInfo(pluginManagerCategory) + << "Plugin" << plugin << "successfully loaded from" << pluginPath; break; + } else { + qCDebug(pluginManagerCategory) + << "Failed to load plugin" << plugin << "from path" << pluginPath + << "due to error:" << loader->errorString(); } } - if (!m_loader.isLoaded()) + if (!loader->isLoaded()) { qCCritical(pluginManagerCategory) << "Failed to load plugin" << plugin; - - return m_loader.isLoaded(); + delete loader; + loader = nullptr; + return false; + } + m_plugins.insert(plugin, loader); + return true; } -QObject *PluginManager::qObjectInstance() { - if (!m_loader.isLoaded()) +QObject *PluginManager::qObjectInstance(const QString &plugin) { + const auto it = m_plugins.find(plugin); + + if (it == m_plugins.end()) + return nullptr; + + if (!it.value()->isLoaded()) return nullptr; - return m_loader.instance(); + return it.value()->instance(); } -void PluginManager::loadDefaultPlugin() { load("mpv"); } +bool PluginManager::loadBestPlugin() { + for (const auto &plugin : m_preferredPlugins) { + if (load(plugin)) { + qCInfo(pluginManagerCategory) << "Loaded best plugin:" << plugin; + return true; + } + } + qCWarning(pluginManagerCategory) + << "No plugin could be loaded as best plugin"; + return false; +} + +QObject *PluginManager::bestQObjectInstance() { + for (const auto &plugin : m_preferredPlugins) { + auto instance = qObjectInstance(plugin); + if (instance) { + qCInfo(pluginManagerCategory) + << "Returning instance of best loaded plugin:" << plugin; + return instance; + } + } + qCWarning(pluginManagerCategory) + << "No plugin instance could be created as best plugin instance"; + return nullptr; +} diff --git a/core/pluginmanager.h b/core/pluginmanager.h index 7c65b17..5ba288c 100644 --- a/core/pluginmanager.h +++ b/core/pluginmanager.h @@ -4,6 +4,7 @@ #include #include #include +#include class PluginManager : public QObject { Q_OBJECT @@ -11,35 +12,48 @@ class PluginManager : public QObject { setPluginDirectories NOTIFY pluginDirectoriesChanged) Q_PROPERTY(QString pluginPrefix READ pluginPrefix WRITE setPluginPrefix NOTIFY pluginPrefixChanged) + Q_PROPERTY(QStringList preferredPlugins READ preferredPlugins WRITE + setPreferredPlugins NOTIFY preferredPluginsChanged) public: - PluginManager(); + PluginManager(QObject *parent = nullptr); + ~PluginManager() override; QString errorString() const; QStringList pluginDirectories() const; QString pluginPrefix() const; + QStringList preferredPlugins() const; - template Interface *instance() { - return qobject_cast(qObjectInstance()); + template Interface *instance(const QString &plugin) { + return qobject_cast(qObjectInstance(plugin)); + } + + template Interface *bestInstance() { + return qobject_cast(bestQObjectInstance()); } public slots: void setPluginDirectories(QStringList pluginDirectories); void setPluginPrefix(QString pluginPrefix); + void setPreferredPlugins(QStringList preferredPlugins); bool load(const QString &plugin); - QObject *qObjectInstance(); + QObject *qObjectInstance(const QString &plugin); - void loadDefaultPlugin(); + bool loadBestPlugin(); + QObject *bestQObjectInstance(); signals: void pluginDirectoriesChanged(QStringList pluginDirectories); void pluginPrefixChanged(QString pluginPrefix); + void preferredPluginsChanged(QStringList preferredPlugins); + private: QStringList m_pluginDirectories; QString m_pluginPrefix; - QPluginLoader m_loader; + QStringList m_preferredPlugins; + QMap m_plugins; }; #endif // PLUGINMANAGER_H -- 2.52.0