mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-13 15:45:42 +08:00
Lazy-load drivers when necessary
* Use JSON to get driver/simulator information * Load driver plugin only when ISimulatorFactory is needed
This commit is contained in:
committed by
Roland Winklmeier
parent
afc22397bb
commit
a0033bee02
@@ -45,15 +45,42 @@ namespace BlackCore
|
|||||||
unloadSimulatorPlugin();
|
unloadSimulatorPlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ISimulatorFactory *CContextSimulator::getSimulatorFactory(const CSimulatorInfo &simulator)
|
||||||
|
{
|
||||||
|
if (!m_simulatorDrivers.contains(simulator))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
DriverInfo& driver = m_simulatorDrivers[simulator];
|
||||||
|
if (!driver.factory) {
|
||||||
|
QPluginLoader loader(driver.fileName);
|
||||||
|
QObject *plugin = loader.instance();
|
||||||
|
if (plugin)
|
||||||
|
{
|
||||||
|
ISimulatorFactory *factory = qobject_cast<ISimulatorFactory *>(plugin);
|
||||||
|
if (factory)
|
||||||
|
{
|
||||||
|
driver.factory = factory;
|
||||||
|
CLogMessage(this).info("Loaded plugin: %1") << factory->getSimulatorInfo().toQString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QString errorMsg = loader.errorString().append(" ").append("Also check if required dll/libs of plugin exists");
|
||||||
|
CLogMessage(this).error(errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return driver.factory;
|
||||||
|
}
|
||||||
|
|
||||||
CSimulatorInfoList CContextSimulator::getAvailableSimulatorPlugins() const
|
CSimulatorInfoList CContextSimulator::getAvailableSimulatorPlugins() const
|
||||||
{
|
{
|
||||||
CSimulatorInfoList simulatorPlugins;
|
CSimulatorInfoList list;
|
||||||
foreach(ISimulatorFactory * factory, m_simulatorFactories)
|
auto keys = m_simulatorDrivers.keys();
|
||||||
{
|
|
||||||
simulatorPlugins.push_back(factory->getSimulatorInfo());
|
std::for_each(keys.begin(), keys.end(), [&list](const CSimulatorInfo& driver) {
|
||||||
}
|
list.push_back(driver);
|
||||||
simulatorPlugins.sortBy(&CSimulatorInfo::getShortName);
|
});
|
||||||
return simulatorPlugins;
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CContextSimulator::isConnected() const
|
bool CContextSimulator::isConnected() const
|
||||||
@@ -249,31 +276,18 @@ namespace BlackCore
|
|||||||
return true;
|
return true;
|
||||||
} // already loaded
|
} // already loaded
|
||||||
|
|
||||||
/* TODO Specify behaviour below */
|
/* TODO Specify behaviour below (maybe assert?) */
|
||||||
if (simulatorInfo.isUnspecified()) {
|
if (simulatorInfo.isUnspecified()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// warning if we do not have any plugins
|
// warning if we do not have any plugins
|
||||||
if (m_simulatorFactories.isEmpty()) {
|
if (m_simulatorDrivers.isEmpty()) {
|
||||||
CLogMessage(this).error("No simulator plugins");
|
CLogMessage(this).error("No simulator plugins");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto factoryIterator = std::find_if(m_simulatorFactories.begin(), m_simulatorFactories.end(), [ = ](const ISimulatorFactory * factory)
|
ISimulatorFactory *factory = getSimulatorFactory(simulatorInfo);
|
||||||
{
|
|
||||||
return factory->getSimulatorInfo() == simulatorInfo;
|
|
||||||
});
|
|
||||||
|
|
||||||
// no plugin found
|
|
||||||
if (factoryIterator == m_simulatorFactories.end())
|
|
||||||
{
|
|
||||||
CLogMessage(this).error("Plugin not found: '%1'") << simulatorInfo.toQString(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Factory for driver
|
|
||||||
ISimulatorFactory *factory = *factoryIterator;
|
|
||||||
Q_ASSERT(factory);
|
Q_ASSERT(factory);
|
||||||
|
|
||||||
// We assume we run in the same process as the own aircraft context
|
// We assume we run in the same process as the own aircraft context
|
||||||
@@ -365,32 +379,38 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
Q_ASSERT(this->getIContextApplication());
|
Q_ASSERT(this->getIContextApplication());
|
||||||
Q_ASSERT(this->getIContextApplication()->isUsingImplementingObject());
|
Q_ASSERT(this->getIContextApplication()->isUsingImplementingObject());
|
||||||
|
Q_ASSERT(!simulatorInfo.isUnspecified());
|
||||||
|
|
||||||
if (this->m_simulator && this->m_simulator->getSimulatorInfo() == simulatorInfo) { // already loaded
|
if (this->m_simulator) { // already loaded
|
||||||
qWarning("Cannot listen for simulator while still plugin is loaded");
|
qWarning("Cannot listen for simulator while the driver is still loaded");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (simulatorInfo.isUnspecified()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// warning if we do not have any plugins
|
// warning if we do not have any plugins
|
||||||
if (m_simulatorListeners.isEmpty()) {
|
if (m_simulatorDrivers.isEmpty()) {
|
||||||
CLogMessage(this).error("No simulator listeners");
|
CLogMessage(this).error("No simulator drivers");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_simulatorListeners.contains(simulatorInfo)) {
|
if (!m_simulatorDrivers.contains(simulatorInfo)) {
|
||||||
CLogMessage(this).error("Listener not found for '%1'") << simulatorInfo.toQString(true);
|
CLogMessage(this).error("Driver not found for '%1'") << simulatorInfo.toQString(true);
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
ISimulatorListener *listener = m_simulatorListeners[simulatorInfo];
|
|
||||||
Q_ASSERT(listener);
|
|
||||||
listener->start();
|
|
||||||
CLogMessage(this).info("Listening for simulator: '%1'") << simulatorInfo.toQString(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DriverInfo& driver = m_simulatorDrivers[simulatorInfo];
|
||||||
|
if (!driver.listener) {
|
||||||
|
ISimulatorFactory* factory = getSimulatorFactory(simulatorInfo);
|
||||||
|
Q_ASSERT(factory);
|
||||||
|
|
||||||
|
driver.listener = factory->createListener();
|
||||||
|
connect(driver.listener, &ISimulatorListener::simulatorStarted, this, &CContextSimulator::ps_simulatorStarted);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISimulatorListener *listener = m_simulatorDrivers[simulatorInfo].listener;
|
||||||
|
Q_ASSERT(listener);
|
||||||
|
listener->start();
|
||||||
|
CLogMessage(this).info("Listening for simulator: '%1'") << simulatorInfo.toQString(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CContextSimulator::listenForSimulatorFromSettings()
|
void CContextSimulator::listenForSimulatorFromSettings()
|
||||||
@@ -559,54 +579,38 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
const QString path = qApp->applicationDirPath().append("/plugins/simulator");
|
const QString path = qApp->applicationDirPath().append("/plugins/simulator");
|
||||||
m_pluginsDir = QDir(path);
|
m_pluginsDir = QDir(path);
|
||||||
if (!m_pluginsDir.exists())
|
if (!m_pluginsDir.exists()) {
|
||||||
{
|
|
||||||
CLogMessage(this).error("No plugin directory: %1") << m_pluginsDir.currentPath();
|
CLogMessage(this).error("No plugin directory: %1") << m_pluginsDir.currentPath();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList fileNames = m_pluginsDir.entryList(QDir::Files);
|
QStringList fileNames = m_pluginsDir.entryList(QDir::Files);
|
||||||
fileNames.sort(Qt::CaseInsensitive); // give a certain order, rather than random file order
|
fileNames.sort(Qt::CaseInsensitive); // give a certain order, rather than random file order
|
||||||
foreach(QString fileName, fileNames)
|
for (const auto& fileName: fileNames) {
|
||||||
{
|
if (!QLibrary::isLibrary(fileName)) {
|
||||||
if (!QLibrary::isLibrary(fileName)) { continue; }
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
CLogMessage(this).info("Try to load plugin: %1") << fileName;
|
CLogMessage(this).info("Try to load plugin: %1") << fileName;
|
||||||
QString pluginPath = m_pluginsDir.absoluteFilePath(fileName);
|
QString pluginPath = m_pluginsDir.absoluteFilePath(fileName);
|
||||||
QPluginLoader loader(pluginPath);
|
QPluginLoader loader(pluginPath);
|
||||||
QJsonObject json = loader.metaData();
|
QJsonObject json = loader.metaData();
|
||||||
QObject *plugin = loader.instance();
|
CSimulatorInfo simulatorInfo(json);
|
||||||
if (plugin)
|
if (!simulatorInfo.isUnspecified()) {
|
||||||
{
|
m_simulatorDrivers.insert(simulatorInfo, { nullptr, nullptr, pluginPath} );
|
||||||
ISimulatorFactory *factory = qobject_cast<ISimulatorFactory *>(plugin);
|
CLogMessage(this).info("Found simulator driver: %1") << simulatorInfo.toQString();
|
||||||
if (factory)
|
} else {
|
||||||
{
|
CLogMessage(this).warning("Simulator driver in %1 is invalid") << pluginPath;
|
||||||
// CSimulatorInfo simulatorInfo = factory->getSimulatorInfo();
|
|
||||||
CSimulatorInfo simulatorInfo(json);
|
|
||||||
m_simulatorFactories.insert(factory);
|
|
||||||
|
|
||||||
ISimulatorListener *listener = factory->createListener(this);
|
|
||||||
Q_ASSERT(listener);
|
|
||||||
Q_ASSERT(listener->parent() == this); // requirement
|
|
||||||
m_simulatorListeners.insert(simulatorInfo, listener);
|
|
||||||
|
|
||||||
/* Will not happen unless start() is called */
|
|
||||||
connect(listener, &ISimulatorListener::simulatorStarted, this, &CContextSimulator::ps_simulatorStarted);
|
|
||||||
|
|
||||||
CLogMessage(this).info("Loaded plugin: %1") << simulatorInfo.toQString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QString errorMsg = loader.errorString().append(" ").append("Also check if required dll/libs of plugin exists");
|
|
||||||
CLogMessage(this).error(errorMsg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CContextSimulator::stopSimulatorListeners()
|
void CContextSimulator::stopSimulatorListeners()
|
||||||
{
|
{
|
||||||
std::for_each(m_simulatorListeners.begin(), m_simulatorListeners.end(), [](ISimulatorListener* l) {
|
std::for_each(m_simulatorDrivers.begin(), m_simulatorDrivers.end(), [](DriverInfo& driver) {
|
||||||
l->stop();
|
if (driver.listener)
|
||||||
|
driver.listener->stop();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ namespace BlackCore
|
|||||||
//! Destructor
|
//! Destructor
|
||||||
virtual ~CContextSimulator();
|
virtual ~CContextSimulator();
|
||||||
|
|
||||||
|
//! Lazy-loads the driver, instantiates the factory and returns it.
|
||||||
|
//! \return nullptr if no corresponding driver was found or an error occured during loading it.
|
||||||
|
ISimulatorFactory* getSimulatorFactory(const BlackSim::CSimulatorInfo& simulator);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
//! \copydoc IContextSimulator::getSimulatorPluginList()
|
//! \copydoc IContextSimulator::getSimulatorPluginList()
|
||||||
@@ -194,10 +198,19 @@ namespace BlackCore
|
|||||||
//! \brief call stop() on all loaded listeners
|
//! \brief call stop() on all loaded listeners
|
||||||
void stopSimulatorListeners();
|
void stopSimulatorListeners();
|
||||||
|
|
||||||
BlackCore::ISimulator *m_simulator = nullptr; //!< simulator plugin
|
/*!
|
||||||
|
* A simple struct containing all info about the driver we need.
|
||||||
|
*/
|
||||||
|
struct DriverInfo {
|
||||||
|
ISimulatorFactory* factory; //!< Lazy-loaded, nullptr by default
|
||||||
|
ISimulatorListener* listener; //!< Listener instance, nullptr by default
|
||||||
|
QString fileName; //!< Plugin file name (relative to plugins/simulator)
|
||||||
|
};
|
||||||
|
|
||||||
|
BlackCore::ISimulator *m_simulator = nullptr; //!< Actually loaded simulator driver
|
||||||
|
QTimer *m_updateTimer = nullptr;
|
||||||
QDir m_pluginsDir;
|
QDir m_pluginsDir;
|
||||||
QSet<ISimulatorFactory *> m_simulatorFactories;
|
QMap<BlackSim::CSimulatorInfo, DriverInfo> m_simulatorDrivers;
|
||||||
QMap<BlackSim::CSimulatorInfo, ISimulatorListener *> m_simulatorListeners;
|
|
||||||
QFuture<bool> m_canConnectResult;
|
QFuture<bool> m_canConnectResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user