From e48b1fd07d820ec1164e716048a93cde323287bf Mon Sep 17 00:00:00 2001 From: Max Paperno Date: Tue, 21 Mar 2017 14:48:25 -0400 Subject: [PATCH] {Companion] Unload simulator libraries after each use -- reset all statically initialized firmware variables. (#4655) * [simulatormainwindow] Move sub-window destructors to main destructor. * [simulation] Move SimulatorInterface creation/ownership to SimulatorMainWindow. * [simulation] Add option to unload simulator libraries after each use (eg. from Companion) so as to properly reset all statically initialized firmware variables; Introduce new SimulatorLoader class. --- companion/src/companion.cpp | 4 +- companion/src/customdebug.cpp | 8 +- companion/src/customdebug.h | 5 +- companion/src/eeprominterface.cpp | 10 -- companion/src/eeprominterface.h | 13 +- companion/src/helpers.cpp | 61 +++---- .../src/simulation/simulatorinterface.cpp | 159 +++++++++++++----- companion/src/simulation/simulatorinterface.h | 27 ++- .../src/simulation/simulatormainwindow.cpp | 48 ++++-- .../src/simulation/simulatormainwindow.h | 9 +- .../src/simulation/simulatorstartupdialog.cpp | 13 +- .../src/simulation/simulatorstartupdialog.h | 2 - companion/src/simulator.cpp | 76 ++++----- 13 files changed, 268 insertions(+), 167 deletions(-) diff --git a/companion/src/companion.cpp b/companion/src/companion.cpp index 718ab2b06..297b5613f 100644 --- a/companion/src/companion.cpp +++ b/companion/src/companion.cpp @@ -105,7 +105,7 @@ int main(int argc, char *argv[]) registerStorageFactories(); registerOpenTxFirmwares(); - registerSimulators(); + SimulatorLoader::registerSimulators(); if (g.profile[g.id()].fwType().isEmpty()){ g.profile[g.id()].fwType(default_firmware_variant->getId()); @@ -135,7 +135,7 @@ int main(int argc, char *argv[]) delete splash; delete mainWin; - unregisterSimulators(); + SimulatorLoader::unregisterSimulators(); unregisterOpenTxFirmwares(); unregisterStorageFactories(); diff --git a/companion/src/customdebug.cpp b/companion/src/customdebug.cpp index 3447364e6..d4be03194 100644 --- a/companion/src/customdebug.cpp +++ b/companion/src/customdebug.cpp @@ -22,15 +22,19 @@ Q_LOGGING_CATEGORY(eepromImport, "eeprom.import") +Q_LOGGING_CATEGORY(simulatorInterfaceLoader, "simulator.interface.loader") + void CustomDebug::setFilterRules() { QString rules; rules.append("eeprom.import="); #if defined(DEBUG_STORAGE_IMPORT) - rules.append("true"); + rules.append("true\n"); #else - rules.append("false"); + rules.append("false\n"); #endif + rules.append("simulator.interface.*=true\n"); + QLoggingCategory::setFilterRules(rules); } diff --git a/companion/src/customdebug.h b/companion/src/customdebug.h index 84a68e66e..28e6c2668 100644 --- a/companion/src/customdebug.h +++ b/companion/src/customdebug.h @@ -24,7 +24,10 @@ #include // Controls the generation of debug output for EEPROM import -Q_DECLARE_LOGGING_CATEGORY(eepromImport) +Q_DECLARE_LOGGING_CATEGORY(eepromImport) // "eeprom.import" + +// Controls the generation of debug output of SimulatorLoader class +Q_DECLARE_LOGGING_CATEGORY(simulatorInterfaceLoader) // "simulator.interface.loader" class CustomDebug { diff --git a/companion/src/eeprominterface.cpp b/companion/src/eeprominterface.cpp index 772aecc7b..073c8949f 100644 --- a/companion/src/eeprominterface.cpp +++ b/companion/src/eeprominterface.cpp @@ -1837,16 +1837,6 @@ void Firmware::addOptions(Option options[]) this->opts.push_back(opts); } -SimulatorInterface * getCurrentSimulator() -{ - QString firmwareId = getCurrentFirmware()->getId(); - SimulatorFactory * factory = getSimulatorFactory(firmwareId); - if (factory) - return factory->create(); - else - return NULL; -} - void FlightModeData::clear(const int phase) { memset(this, 0, sizeof(FlightModeData)); diff --git a/companion/src/eeprominterface.h b/companion/src/eeprominterface.h index 1d88094fd..0589e294a 100644 --- a/companion/src/eeprominterface.h +++ b/companion/src/eeprominterface.h @@ -21,6 +21,7 @@ #ifndef _EEPROMINTERFACE_H_ #define _EEPROMINTERFACE_H_ +#include "macros.h" #include "radiodata.h" #include "../../radio/src/definitions.h" #include "simulatorinterface.h" @@ -195,14 +196,8 @@ inline int applyStickMode(int stick, unsigned int mode) return stick; } - const unsigned int stickModes[]= { - 1, 2, 3, 4, - 1, 3, 2, 4, - 4, 2, 3, 1, - 4, 3, 2, 1 }; - if (stick >= 1 && stick <= 4) - return stickModes[(mode-1)*4 + stick - 1]; + return modn12x3[mode-1][stick-1]; else return stick; } @@ -358,8 +353,6 @@ inline Firmware * getCurrentFirmware() return current_firmware_variant; } -SimulatorInterface * getCurrentSimulator(); - inline EEPROMInterface * getCurrentEEpromInterface() { return getCurrentFirmware()->getEEpromInterface(); @@ -375,7 +368,7 @@ inline int divRoundClosest(const int n, const int d) return ((n < 0) ^ (d < 0)) ? ((n - d/2)/d) : ((n + d/2)/d); } -#define CHECK_IN_ARRAY(T, index) ((unsigned int)index < (unsigned int)(sizeof(T)/sizeof(T[0])) ? T[(unsigned int)index] : "???") +#define CHECK_IN_ARRAY(T, index) ((unsigned int)index < DIM(T) ? T[(unsigned int)index] : "???") extern QList eepromInterfaces; diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index 59eda22df..3e3609ce9 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -25,9 +25,6 @@ #elif defined __GNUC__ #include #endif -#if defined(WIN32) && defined(WIN_USE_CONSOLE_STDIO) - #include "windows.h" -#endif #include "appdata.h" #include "helpers.h" @@ -811,39 +808,45 @@ CompanionIcon::CompanionIcon(const QString &baseimage) void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx) { - SimulatorInterface * simulator = getCurrentSimulator(); - if (simulator) { - RadioData * simuData = new RadioData(radioData); - unsigned int flags = 0; + QString fwId = SimulatorLoader::findSimulatorByFirmwareName(getCurrentFirmware()->getId()); + if (fwId.isEmpty()) { + QMessageBox::warning(NULL, + QObject::tr("Warning"), + QObject::tr("Simulator for this firmware is not yet available")); + return; + } - if (modelIdx >= 0) { - flags |= SIMULATOR_FLAGS_NOTX; - simuData->setCurrentModel(modelIdx); - } + RadioData * simuData = new RadioData(radioData); + unsigned int flags = 0; - SimulatorMainWindow * dialog = new SimulatorMainWindow(parent, simulator, flags); - if (!dialog->setRadioData(simuData)) { - QMessageBox::critical(NULL, QObject::tr("Data Load Error"), QObject::tr("Error occurred while starting simulator.")); - delete dialog; - delete simuData; - return; - } + if (modelIdx >= 0) { + flags |= SIMULATOR_FLAGS_NOTX; + simuData->setCurrentModel(modelIdx); + } - dialog->setWindowModality(Qt::ApplicationModal); - dialog->setAttribute(Qt::WA_DeleteOnClose); + SimulatorMainWindow * dialog = new SimulatorMainWindow(parent, fwId, flags); + dialog->setWindowModality(Qt::ApplicationModal); + dialog->setAttribute(Qt::WA_DeleteOnClose); + + QObject::connect(dialog, &SimulatorMainWindow::destroyed, [simuData] (void) { + // TODO simuData and Horus tmp directory is deleted on simulator close OR we could use it to get back data from the simulation + delete simuData; + }); + + QString resultMsg; + if (dialog->getExitStatus(&resultMsg)) { + if (resultMsg.isEmpty()) + resultMsg = QObject::tr("Uknown error during Simulator startup."); + QMessageBox::critical(NULL, QObject::tr("Simulator Error"), resultMsg); + dialog->deleteLater(); + } + else if (dialog->setRadioData(simuData)) { dialog->start(); - - QObject::connect(dialog, &SimulatorMainWindow::destroyed, [simuData] (void) { - // TODO simuData and Horus tmp directory is deleted on simulator close OR we could use it to get back data from the simulation - delete simuData; - }); - dialog->show(); } else { - QMessageBox::warning(NULL, - QObject::tr("Warning"), - QObject::tr("Simulator for this firmware is not yet available")); + QMessageBox::critical(NULL, QObject::tr("Data Load Error"), QObject::tr("Error occurred while starting simulator.")); + dialog->deleteLater(); } } diff --git a/companion/src/simulation/simulatorinterface.cpp b/companion/src/simulation/simulatorinterface.cpp index 1f78b20aa..24919e055 100644 --- a/companion/src/simulation/simulatorinterface.cpp +++ b/companion/src/simulation/simulatorinterface.cpp @@ -19,38 +19,29 @@ */ #include "simulatorinterface.h" -#include -#include -#include -#include -#include -#include +#include "customdebug.h" #include "version.h" + +#include +#include + #if defined _MSC_VER || !defined __GNUC__ #include #endif -QMap registered_simulators; +#ifndef SIMULATOR_INTERFACE_LOADER_METHOD + #define SIMULATOR_INTERFACE_LOADER_DYNAMIC 1 // How to load simulator libraries: 1=dynamic load and unload; 0=load once (old way) +#endif -void registerSimulator(const QString & filename) +QMap SimulatorLoader::registeredSimulators; + +QStringList SimulatorLoader::getAvailableSimulators() { - QLibrary lib(filename); - typedef SimulatorFactory * (*RegisterSimulator)(); - qDebug() << "trying to register simulator in " << filename; - RegisterSimulator registerFunc = (RegisterSimulator)lib.resolve("registerSimu"); - if (registerFunc) { - SimulatorFactory * factory = registerFunc(); - registered_simulators[factory->name()] = factory; - qDebug() << "Registered" << factory->name() << "simulator"; - } - else { - qWarning() << "Library error" << filename << lib.errorString(); - } + return registeredSimulators.keys(); } -int registerSimulators(const QDir & dir) +int SimulatorLoader::registerSimulators(const QDir & dir) { - int noSimulatorsFound = 0; QStringList filters; #if defined(__APPLE__) filters << "*-simulator.dylib"; @@ -59,17 +50,41 @@ int registerSimulators(const QDir & dir) #else filters << "*-simulator.so"; #endif + registeredSimulators.clear(); + + qCDebug(simulatorInterfaceLoader) << "Searching for simulators in" << dir.path() << "matching pattern" << filters; - qDebug() << "Searching for simulators in" << dir.path(); foreach(QString filename, dir.entryList(filters, QDir::Files)) { - QString libraryFilename = dir.path() + "/" + filename; - registerSimulator(libraryFilename); - noSimulatorsFound++; + QLibrary * lib = new QLibrary( dir.path() + "/" + filename); + + qCDebug(simulatorInterfaceLoader) << "Trying to register simulator in " << filename; + + SimulatorFactory * factory; + RegisterSimulator registerFunc = (RegisterSimulator)lib->resolve("registerSimu"); + + if (registerFunc && (factory = registerFunc())) { + if (getAvailableSimulators().contains(factory->name())) + continue; + + lib->setProperty("instances_used", 0); + registeredSimulators.insert(factory->name(), lib); + delete factory; +#if SIMULATOR_INTERFACE_LOADER_DYNAMIC + lib->unload(); +#endif + qCDebug(simulatorInterfaceLoader) << "Registered" << registeredSimulators.lastKey() << "simulator in " << lib->fileName() << "and unloaded:" << !lib->isLoaded(); + } + else { + qWarning() << "Library error" << lib->fileName() << lib->errorString(); + delete lib; + } + } - return noSimulatorsFound; + qCDebug(simulatorInterfaceLoader) << "Found libraries:" << (registeredSimulators.size() ? registeredSimulators.keys() : QStringList() << "none"); + return registeredSimulators.size(); } -void registerSimulators() +void SimulatorLoader::registerSimulators() { QDir dir("."); if (registerSimulators(dir)) { @@ -90,31 +105,93 @@ void registerSimulators() registerSimulators(dir); } -SimulatorFactory * getSimulatorFactory(const QString & name) +void SimulatorLoader::unregisterSimulators() { + foreach(QLibrary * lib, registeredSimulators) + delete lib; +} + +QString SimulatorLoader::findSimulatorByFirmwareName(const QString & name) +{ + int pos; + QString ret; QString simuName = name; + while(1) { - qDebug() << "searching" << simuName << "simulator"; - foreach (QString name, registered_simulators.keys()) { - if (name.contains(simuName)) { - simuName = name; - qDebug() << "found" << simuName; - return registered_simulators[simuName]; - } + qCDebug(simulatorInterfaceLoader) << "searching" << simuName << "simulator"; + if (registeredSimulators.contains(simuName)) { + ret = simuName; + break; } - int pos = simuName.lastIndexOf('-'); - if (pos <= 0) + if ((pos = simuName.lastIndexOf('-')) <= 0) break; simuName = simuName.mid(0, pos); if (simuName.count('-') == 0) break; } - return NULL; + return ret; } -void unregisterSimulators() +SimulatorInterface * SimulatorLoader::loadSimulator(const QString & name) { - foreach(SimulatorFactory *factory, registered_simulators) { + SimulatorInterface * si = NULL; + QString libname = findSimulatorByFirmwareName(name); + + if (libname.isEmpty()) { + qWarning() << "Simulator" << name << "not found."; + return si; + } + + QLibrary * lib = registeredSimulators.value(libname, NULL); + if (!lib) { + qWarning() << "Simulator library is NULL"; + return si; + } + + qCDebug(simulatorInterfaceLoader) << "Trying to load simulator in " << lib->fileName(); + + SimulatorFactory * factory; + RegisterSimulator registerFunc = (RegisterSimulator)lib->resolve("registerSimu"); + if (registerFunc && (factory = registerFunc()) && (si = factory->create())) { + quint8 instance = lib->property("instances_used").toUInt(); + lib->setProperty("instances_used", ++instance); + qCDebug(simulatorInterfaceLoader) << "Loaded" << factory->name() << "simulator instance" << instance; delete factory; } + else { + qWarning() << "Library error" << lib->fileName() << lib->errorString(); + } + return si; +} + +bool SimulatorLoader::unloadSimulator(const QString & name) +{ + bool ret = false; +#if SIMULATOR_INTERFACE_LOADER_DYNAMIC + QString simuName = findSimulatorByFirmwareName(name); + if (simuName.isEmpty()) + return ret; + + QLibrary * lib = registeredSimulators.value(simuName, NULL); + + if (lib && lib->isLoaded()) { + quint8 instance = lib->property("instances_used").toUInt(); + lib->setProperty("instances_used", --instance); + if (!instance) { + ret = lib->unload(); + qCDebug(simulatorInterfaceLoader) << "Unloading" << simuName << "(" << lib->fileName() << ")" << "result:" << ret; + } + else { + ret = true; + qCDebug(simulatorInterfaceLoader) << "Simulator" << simuName << "instances remaining:" << instance; + } + } + else { + qCDebug(simulatorInterfaceLoader) << "Simulator library for " << simuName << "already unloaded."; + } +#else + qCDebug(simulatorInterfaceLoader) << "Keeping simulator library" << simuName << "loaded."; +#endif + + return ret; } diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h index 42fef7557..faec70191 100644 --- a/companion/src/simulation/simulatorinterface.h +++ b/companion/src/simulation/simulatorinterface.h @@ -23,11 +23,16 @@ #include "boards.h" #include "constants.h" + +#include #include + +#include #include #include +#include +#include #include -#include struct TxInputs { @@ -122,9 +127,21 @@ class SimulatorFactory { virtual SimulatorInterface *create() = 0; }; -void registerSimulators(); -void unregisterSimulators(); -SimulatorFactory *getSimulatorFactory(const QString &name); -extern QMap registered_simulators; +class SimulatorLoader +{ + public: + static void registerSimulators(); + static void unregisterSimulators(); + static QStringList getAvailableSimulators(); + static QString findSimulatorByFirmwareName(const QString & name); + static SimulatorInterface * loadSimulator(const QString & name); + static bool unloadSimulator(const QString & name); + + protected: + typedef SimulatorFactory * (*RegisterSimulator)(); + + static int registerSimulators(const QDir & dir); + static QMap registeredSimulators; +}; #endif // _SIMULATORINTERFACE_H_ diff --git a/companion/src/simulation/simulatormainwindow.cpp b/companion/src/simulation/simulatormainwindow.cpp index a85f4b419..434ac429c 100644 --- a/companion/src/simulation/simulatormainwindow.cpp +++ b/companion/src/simulation/simulatormainwindow.cpp @@ -40,9 +40,8 @@ extern AppData g; // ensure what "g" means const quint16 SimulatorMainWindow::m_savedUiStateVersion = 2; -SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, SimulatorInterface * simulator, quint8 flags, Qt::WindowFlags wflags) : +SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, const QString & firmwareId, quint8 flags, Qt::WindowFlags wflags) : QMainWindow(parent, wflags), - m_simulator(simulator), ui(new Ui::SimulatorMainWindow), m_simulatorWidget(NULL), m_consoleWidget(NULL), @@ -52,12 +51,24 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, SimulatorInterface * s m_telemetryDockWidget(NULL), m_trainerDockWidget(NULL), m_outputsDockWidget(NULL), + m_simulatorId(firmwareId), + m_exitStatusCode(0), m_radioProfileId(g.sessionId()), m_radioSizeConstraint(Qt::Horizontal | Qt::Vertical), m_firstShow(true), m_showRadioDocked(true), m_showMenubar(true) { + if (m_simulatorId.isEmpty()) { + m_simulatorId = SimulatorLoader::findSimulatorByFirmwareName(getCurrentFirmware()->getId()); + } + m_simulator = SimulatorLoader::loadSimulator(m_simulatorId); + if (!m_simulator) { + m_exitStatusMsg = tr("ERROR: Failed to create simulator interface, possibly missing or bad library."); + m_exitStatusCode = -1; + return; + } + ui->setupUi(this); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); @@ -128,25 +139,30 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, SimulatorInterface * s SimulatorMainWindow::~SimulatorMainWindow() { - delete ui; -} - -void SimulatorMainWindow::closeEvent(QCloseEvent *) -{ - saveUiState(); - if (m_telemetryDockWidget) delete m_telemetryDockWidget; if (m_trainerDockWidget) delete m_trainerDockWidget; if (m_outputsDockWidget) delete m_outputsDockWidget; - if (m_consoleDockWidget) - delete m_consoleDockWidget; if (m_simulatorDockWidget) delete m_simulatorDockWidget; else if (m_simulatorWidget) delete m_simulatorWidget; + if (m_consoleDockWidget) + delete m_consoleDockWidget; + + delete ui; + + if (m_simulator) + delete m_simulator; + + SimulatorLoader::unloadSimulator(m_simulatorId); +} + +void SimulatorMainWindow::closeEvent(QCloseEvent *) +{ + saveUiState(); } void SimulatorMainWindow::show() @@ -173,7 +189,8 @@ void SimulatorMainWindow::changeEvent(QEvent *e) } } -QMenu * SimulatorMainWindow::createPopupMenu(){ +QMenu * SimulatorMainWindow::createPopupMenu() +{ QMenu * menu = QMainWindow::createPopupMenu(); menu->clear(); menu->addActions(ui->menuView->actions()); @@ -214,6 +231,13 @@ void SimulatorMainWindow::restoreUiState() restoreState(windowState, m_savedUiStateVersion); } +int SimulatorMainWindow::getExitStatus(QString * msg) +{ + if (msg) + *msg = m_exitStatusMsg; + return m_exitStatusCode; +} + bool SimulatorMainWindow::setRadioData(RadioData * radioData) { return m_simulatorWidget->setRadioData(radioData); diff --git a/companion/src/simulation/simulatormainwindow.h b/companion/src/simulation/simulatormainwindow.h index a63982bd6..4791cf0b4 100644 --- a/companion/src/simulation/simulatormainwindow.h +++ b/companion/src/simulation/simulatormainwindow.h @@ -25,7 +25,6 @@ #include #include -#include class DebugOutput; class RadioData; @@ -48,13 +47,14 @@ class SimulatorMainWindow : public QMainWindow Q_OBJECT public: - explicit SimulatorMainWindow(QWidget * parent, SimulatorInterface * simulator, quint8 flags=0, Qt::WindowFlags wflags = Qt::WindowFlags()); + explicit SimulatorMainWindow(QWidget * parent, const QString & firmwareId = "", quint8 flags=0, Qt::WindowFlags wflags = Qt::WindowFlags()); ~SimulatorMainWindow(); + int getExitStatus(QString * msg = Q_NULLPTR); bool setRadioData(RadioData * radioData); bool useTempDataPath(bool deleteOnClose = true); bool setOptions(SimulatorOptions & options, bool withSave = true); - QMenu * createPopupMenu(); + virtual QMenu * createPopupMenu(); public slots: virtual void show(); @@ -95,6 +95,9 @@ class SimulatorMainWindow : public QMainWindow QDockWidget * m_outputsDockWidget; QVector m_keymapHelp; + QString m_simulatorId; + QString m_exitStatusMsg; + int m_exitStatusCode; int m_radioProfileId; int m_radioSizeConstraint; bool m_firstShow; diff --git a/companion/src/simulation/simulatorstartupdialog.cpp b/companion/src/simulation/simulatorstartupdialog.cpp index b09d254e4..e232b36f9 100644 --- a/companion/src/simulation/simulatorstartupdialog.cpp +++ b/companion/src/simulation/simulatorstartupdialog.cpp @@ -23,13 +23,14 @@ #include "appdata.h" #include "constants.h" -#include "eeprominterface.h" +#include "simulatorinterface.h" #include "helpers.h" #include +using namespace Simulator; + extern AppData g; -extern QMap registered_simulators; SimulatorStartupDialog::SimulatorStartupDialog(SimulatorOptions * options, int * profId, QWidget *parent) : QDialog(parent), @@ -45,7 +46,7 @@ SimulatorStartupDialog::SimulatorStartupDialog(SimulatorOptions * options, int * ui->radioProfile->addItem(pi.value(), pi.key()); } - ui->radioType->addItems(registered_simulators.keys()); + ui->radioType->addItems(SimulatorLoader::getAvailableSimulators()); ui->optGrp_dataSource->setId(ui->optFile, SimulatorOptions::START_WITH_FILE); ui->optGrp_dataSource->setId(ui->optFolder, SimulatorOptions::START_WITH_FOLDER); @@ -151,7 +152,7 @@ void SimulatorStartupDialog::updateContainerTypes(void) void SimulatorStartupDialog::loadRadioProfile(int id) { - QString tmpstr; + QString tmpstr, tmpstr2; int i; if (id < 0 || !g.getActiveProfiles().contains(id)) @@ -166,8 +167,8 @@ void SimulatorStartupDialog::loadRadioProfile(int id) tmpstr = m_options->firmwareId; if (tmpstr.isEmpty() && !g.profile[id].fwType().isEmpty()) tmpstr = g.profile[id].fwType(); - else if (getSimulatorFactory(tmpstr)) - tmpstr = getSimulatorFactory(tmpstr)->name(); + else if (!(tmpstr2 = SimulatorLoader::findSimulatorByFirmwareName(m_options->firmwareId)).isEmpty()) + tmpstr = tmpstr2; i = ui->radioType->findText(findRadioId(tmpstr), Qt::MatchContains); if (i > -1) ui->radioType->setCurrentIndex(i); diff --git a/companion/src/simulation/simulatorstartupdialog.h b/companion/src/simulation/simulatorstartupdialog.h index dc5abcbea..ba5dc2f6a 100644 --- a/companion/src/simulation/simulatorstartupdialog.h +++ b/companion/src/simulation/simulatorstartupdialog.h @@ -28,8 +28,6 @@ namespace Ui { class SimulatorStartupDialog; } -using namespace Simulator; - class SimulatorStartupDialog : public QDialog { Q_OBJECT diff --git a/companion/src/simulator.cpp b/companion/src/simulator.cpp index 054c28179..ecd6a2556 100644 --- a/companion/src/simulator.cpp +++ b/companion/src/simulator.cpp @@ -19,13 +19,13 @@ */ #include -#include +#include #include #include -#include -#include -#include #include +#include +#include +#include #if defined(JOYSTICKS) || defined(SIMU_AUDIO) #include #undef main @@ -66,20 +66,11 @@ void sharedHelpText(QTextStream &stream) } // list all available radios stream << endl << QObject::tr("Available radios:") << endl; - foreach(QString name, registered_simulators.keys()) { + foreach(QString name, SimulatorLoader::getAvailableSimulators()) { stream << "\t" << name << endl; } } -QString findFirmwareId(int profileId) -{ - SimulatorFactory * sf = getSimulatorFactory(g.profile[profileId].fwType()); - if (sf) - return sf->name(); - else - return QString(); -} - int main(int argc, char *argv[]) { Q_INIT_RESOURCE(companion); @@ -100,6 +91,8 @@ int main(int argc, char *argv[]) g.init(); + QString resultMsg; + QTranslator companionTranslator; companionTranslator.load(":/companion_" + g.locale()); QTranslator qtTranslator; @@ -127,9 +120,9 @@ int main(int argc, char *argv[]) registerStorageFactories(); registerOpenTxFirmwares(); - registerSimulators(); + SimulatorLoader::registerSimulators(); - if (!registered_simulators.size()) { + if (!SimulatorLoader::getAvailableSimulators().size()) { showMessage(QObject::tr("ERROR: No simulator libraries available."), QMessageBox::Critical); return finish(3); } @@ -142,20 +135,19 @@ int main(int argc, char *argv[]) cliOptions.alias("help", "h"); cliOptions.parse(QCoreApplication::arguments()); if (cliOptions.count("help") || cliOptions.showUnrecognizedWarning()) { - QString msg; - QTextStream stream(&msg); + QTextStream stream(&resultMsg); stream << QObject::tr("Usage: simulator [OPTION]... [EEPROM.BIN FILE OR DATA FOLDER] ") << endl << endl; stream << QObject::tr("Options:") << endl; cliOptions.showUsage(false, stream); sharedHelpText(stream); // display - showMessage(msg, QMessageBox::Information); + showMessage(resultMsg, QMessageBox::Information); return finish(1); } // TODO : defaults should be set in Profile::init() if (simOptions.firmwareId.isEmpty()) - simOptions.firmwareId = findFirmwareId(profileId); + simOptions.firmwareId = SimulatorLoader::findSimulatorByFirmwareName(g.profile[profileId].fwType()); if (simOptions.dataFolder.isEmpty()) simOptions.dataFolder = g.eepromDir(); if (simOptions.sdPath.isEmpty()) @@ -209,28 +201,16 @@ int main(int argc, char *argv[]) qDebug() << "profileId=" << profileId << simOptions; if (profileId < 0 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) { - showMessage(QObject::tr("ERROR: Couldn't start simulator, missing radio/profile/data file/folder.\n Profile ID: [%1]; Radio ID: [%2];\nData File: [%3]") - .arg(profileId).arg(simOptions.firmwareId, simOptions.dataFile), QMessageBox::Critical); + resultMsg = QObject::tr("ERROR: Couldn't start simulator, missing radio/profile/data file/folder.\n Profile ID: [%1]; Radio ID: [%2];\nData File: [%3]"); + showMessage(resultMsg.arg(profileId).arg(simOptions.firmwareId, simOptions.dataFile), QMessageBox::Critical); return finish(1); } - if (!g.getActiveProfiles().contains(profileId) || !registered_simulators.keys().contains(simOptions.firmwareId)) { - QString msg; - QTextStream stream(&msg); + if (!g.getActiveProfiles().contains(profileId) || !SimulatorLoader::getAvailableSimulators().contains(simOptions.firmwareId)) { + QTextStream stream(&resultMsg); stream << QObject::tr("ERROR: Radio profile or simulator firmware not found.\nProfile ID: [%1]; Radio ID: [%2]") .arg(profileId).arg(simOptions.firmwareId); sharedHelpText(stream); - showMessage(msg, QMessageBox::Critical); - return finish(2); - } - - SimulatorFactory * factory = getSimulatorFactory(simOptions.firmwareId); - if (!factory) { - showMessage(QObject::tr("ERROR: Simulator %1 not found").arg(simOptions.firmwareId), QMessageBox::Critical); - return finish(2); - } - SimulatorInterface * simulator = factory->create(); - if (!simulator) { - showMessage(QObject::tr("ERROR: Failed to create simulator interface, possibly missing or bad library."), QMessageBox::Critical); + showMessage(resultMsg, QMessageBox::Critical); return finish(2); } @@ -239,26 +219,33 @@ int main(int argc, char *argv[]) g.sessionId(profileId); g.simuLastProfId(profileId); - int result = 1; - SimulatorMainWindow * mainWindow = new SimulatorMainWindow(NULL, simulator, SIMULATOR_FLAGS_STANDALONE); - if (mainWindow->setOptions(simOptions, true)) { + int result = 0; + SimulatorMainWindow * mainWindow = new SimulatorMainWindow(NULL, simOptions.firmwareId, SIMULATOR_FLAGS_STANDALONE); + if ((result = mainWindow->getExitStatus(&resultMsg))) { + if (resultMsg.isEmpty()) + resultMsg = QObject::tr("Uknown error during Simulator startup."); + showMessage(resultMsg, QMessageBox::Critical); + } + else if (mainWindow->setOptions(simOptions, true)) { mainWindow->start(); mainWindow->show(); result = app.exec(); + if (!result) { + if ((result = mainWindow->getExitStatus(&resultMsg)) && !resultMsg.isEmpty()) + qWarning() << "Exit message from SimulatorMainWindow:" << resultMsg; + } } else { result = 3; } - delete mainWindow; - delete simulator; + delete mainWindow; return finish(result); } int finish(int exitCode) { - qDebug() << "SIMULATOR EXIT" << exitCode; - unregisterSimulators(); + SimulatorLoader::unregisterSimulators(); unregisterOpenTxFirmwares(); unregisterStorageFactories(); @@ -266,5 +253,6 @@ int finish(int exitCode) SDL_Quit(); #endif + qDebug() << "SIMULATOR EXIT" << exitCode; return exitCode; }