mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-24 07:55:35 +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
@@ -44,16 +44,43 @@ namespace BlackCore
|
||||
disconnectFromSimulator();
|
||||
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 simulatorPlugins;
|
||||
foreach(ISimulatorFactory * factory, m_simulatorFactories)
|
||||
{
|
||||
simulatorPlugins.push_back(factory->getSimulatorInfo());
|
||||
}
|
||||
simulatorPlugins.sortBy(&CSimulatorInfo::getShortName);
|
||||
return simulatorPlugins;
|
||||
CSimulatorInfoList list;
|
||||
auto keys = m_simulatorDrivers.keys();
|
||||
|
||||
std::for_each(keys.begin(), keys.end(), [&list](const CSimulatorInfo& driver) {
|
||||
list.push_back(driver);
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
bool CContextSimulator::isConnected() const
|
||||
@@ -249,31 +276,18 @@ namespace BlackCore
|
||||
return true;
|
||||
} // already loaded
|
||||
|
||||
/* TODO Specify behaviour below */
|
||||
/* TODO Specify behaviour below (maybe assert?) */
|
||||
if (simulatorInfo.isUnspecified()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// warning if we do not have any plugins
|
||||
if (m_simulatorFactories.isEmpty()) {
|
||||
if (m_simulatorDrivers.isEmpty()) {
|
||||
CLogMessage(this).error("No simulator plugins");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto factoryIterator = std::find_if(m_simulatorFactories.begin(), m_simulatorFactories.end(), [ = ](const ISimulatorFactory * factory)
|
||||
{
|
||||
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;
|
||||
|
||||
ISimulatorFactory *factory = getSimulatorFactory(simulatorInfo);
|
||||
Q_ASSERT(factory);
|
||||
|
||||
// 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()->isUsingImplementingObject());
|
||||
Q_ASSERT(!simulatorInfo.isUnspecified());
|
||||
|
||||
if (this->m_simulator && this->m_simulator->getSimulatorInfo() == simulatorInfo) { // already loaded
|
||||
qWarning("Cannot listen for simulator while still plugin is loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
if (simulatorInfo.isUnspecified()) {
|
||||
if (this->m_simulator) { // already loaded
|
||||
qWarning("Cannot listen for simulator while the driver is still loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// warning if we do not have any plugins
|
||||
if (m_simulatorListeners.isEmpty()) {
|
||||
CLogMessage(this).error("No simulator listeners");
|
||||
if (m_simulatorDrivers.isEmpty()) {
|
||||
CLogMessage(this).error("No simulator drivers");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_simulatorListeners.contains(simulatorInfo)) {
|
||||
CLogMessage(this).error("Listener not found for '%1'") << simulatorInfo.toQString(true);
|
||||
if (!m_simulatorDrivers.contains(simulatorInfo)) {
|
||||
CLogMessage(this).error("Driver not found for '%1'") << simulatorInfo.toQString(true);
|
||||
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()
|
||||
@@ -559,54 +579,38 @@ namespace BlackCore
|
||||
{
|
||||
const QString path = qApp->applicationDirPath().append("/plugins/simulator");
|
||||
m_pluginsDir = QDir(path);
|
||||
if (!m_pluginsDir.exists())
|
||||
{
|
||||
if (!m_pluginsDir.exists()) {
|
||||
CLogMessage(this).error("No plugin directory: %1") << m_pluginsDir.currentPath();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QStringList fileNames = m_pluginsDir.entryList(QDir::Files);
|
||||
fileNames.sort(Qt::CaseInsensitive); // give a certain order, rather than random file order
|
||||
foreach(QString fileName, fileNames)
|
||||
{
|
||||
if (!QLibrary::isLibrary(fileName)) { continue; }
|
||||
for (const auto& fileName: fileNames) {
|
||||
if (!QLibrary::isLibrary(fileName)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
CLogMessage(this).info("Try to load plugin: %1") << fileName;
|
||||
QString pluginPath = m_pluginsDir.absoluteFilePath(fileName);
|
||||
QPluginLoader loader(pluginPath);
|
||||
QJsonObject json = loader.metaData();
|
||||
QObject *plugin = loader.instance();
|
||||
if (plugin)
|
||||
{
|
||||
ISimulatorFactory *factory = qobject_cast<ISimulatorFactory *>(plugin);
|
||||
if (factory)
|
||||
{
|
||||
// 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);
|
||||
CSimulatorInfo simulatorInfo(json);
|
||||
if (!simulatorInfo.isUnspecified()) {
|
||||
m_simulatorDrivers.insert(simulatorInfo, { nullptr, nullptr, pluginPath} );
|
||||
CLogMessage(this).info("Found simulator driver: %1") << simulatorInfo.toQString();
|
||||
} else {
|
||||
CLogMessage(this).warning("Simulator driver in %1 is invalid") << pluginPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CContextSimulator::stopSimulatorListeners()
|
||||
{
|
||||
std::for_each(m_simulatorListeners.begin(), m_simulatorListeners.end(), [](ISimulatorListener* l) {
|
||||
l->stop();
|
||||
std::for_each(m_simulatorDrivers.begin(), m_simulatorDrivers.end(), [](DriverInfo& driver) {
|
||||
if (driver.listener)
|
||||
driver.listener->stop();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@ namespace BlackCore
|
||||
public:
|
||||
//! Destructor
|
||||
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:
|
||||
|
||||
@@ -193,11 +197,20 @@ namespace BlackCore
|
||||
|
||||
//! \brief call stop() on all loaded listeners
|
||||
void stopSimulatorListeners();
|
||||
|
||||
/*!
|
||||
* 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; //!< simulator plugin
|
||||
BlackCore::ISimulator *m_simulator = nullptr; //!< Actually loaded simulator driver
|
||||
QTimer *m_updateTimer = nullptr;
|
||||
QDir m_pluginsDir;
|
||||
QSet<ISimulatorFactory *> m_simulatorFactories;
|
||||
QMap<BlackSim::CSimulatorInfo, ISimulatorListener *> m_simulatorListeners;
|
||||
QMap<BlackSim::CSimulatorInfo, DriverInfo> m_simulatorDrivers;
|
||||
QFuture<bool> m_canConnectResult;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user