1
0
Fork 0
mirror of https://github.com/EdgeTX/edgetx.git synced 2025-07-25 17:25:10 +03:00

{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.
This commit is contained in:
Max Paperno 2017-03-21 14:48:25 -04:00 committed by Bertrand Songis
parent dc89d2d630
commit e48b1fd07d
13 changed files with 268 additions and 167 deletions

View file

@ -105,7 +105,7 @@ int main(int argc, char *argv[])
registerStorageFactories(); registerStorageFactories();
registerOpenTxFirmwares(); registerOpenTxFirmwares();
registerSimulators(); SimulatorLoader::registerSimulators();
if (g.profile[g.id()].fwType().isEmpty()){ if (g.profile[g.id()].fwType().isEmpty()){
g.profile[g.id()].fwType(default_firmware_variant->getId()); g.profile[g.id()].fwType(default_firmware_variant->getId());
@ -135,7 +135,7 @@ int main(int argc, char *argv[])
delete splash; delete splash;
delete mainWin; delete mainWin;
unregisterSimulators(); SimulatorLoader::unregisterSimulators();
unregisterOpenTxFirmwares(); unregisterOpenTxFirmwares();
unregisterStorageFactories(); unregisterStorageFactories();

View file

@ -22,15 +22,19 @@
Q_LOGGING_CATEGORY(eepromImport, "eeprom.import") Q_LOGGING_CATEGORY(eepromImport, "eeprom.import")
Q_LOGGING_CATEGORY(simulatorInterfaceLoader, "simulator.interface.loader")
void CustomDebug::setFilterRules() void CustomDebug::setFilterRules()
{ {
QString rules; QString rules;
rules.append("eeprom.import="); rules.append("eeprom.import=");
#if defined(DEBUG_STORAGE_IMPORT) #if defined(DEBUG_STORAGE_IMPORT)
rules.append("true"); rules.append("true\n");
#else #else
rules.append("false"); rules.append("false\n");
#endif #endif
rules.append("simulator.interface.*=true\n");
QLoggingCategory::setFilterRules(rules); QLoggingCategory::setFilterRules(rules);
} }

View file

@ -24,7 +24,10 @@
#include <QLoggingCategory> #include <QLoggingCategory>
// Controls the generation of debug output for EEPROM import // 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 class CustomDebug
{ {

View file

@ -1837,16 +1837,6 @@ void Firmware::addOptions(Option options[])
this->opts.push_back(opts); 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) void FlightModeData::clear(const int phase)
{ {
memset(this, 0, sizeof(FlightModeData)); memset(this, 0, sizeof(FlightModeData));

View file

@ -21,6 +21,7 @@
#ifndef _EEPROMINTERFACE_H_ #ifndef _EEPROMINTERFACE_H_
#define _EEPROMINTERFACE_H_ #define _EEPROMINTERFACE_H_
#include "macros.h"
#include "radiodata.h" #include "radiodata.h"
#include "../../radio/src/definitions.h" #include "../../radio/src/definitions.h"
#include "simulatorinterface.h" #include "simulatorinterface.h"
@ -195,14 +196,8 @@ inline int applyStickMode(int stick, unsigned int mode)
return stick; 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) if (stick >= 1 && stick <= 4)
return stickModes[(mode-1)*4 + stick - 1]; return modn12x3[mode-1][stick-1];
else else
return stick; return stick;
} }
@ -358,8 +353,6 @@ inline Firmware * getCurrentFirmware()
return current_firmware_variant; return current_firmware_variant;
} }
SimulatorInterface * getCurrentSimulator();
inline EEPROMInterface * getCurrentEEpromInterface() inline EEPROMInterface * getCurrentEEpromInterface()
{ {
return getCurrentFirmware()->getEEpromInterface(); 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); 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<EEPROMInterface *> eepromInterfaces; extern QList<EEPROMInterface *> eepromInterfaces;

View file

@ -25,9 +25,6 @@
#elif defined __GNUC__ #elif defined __GNUC__
#include <unistd.h> #include <unistd.h>
#endif #endif
#if defined(WIN32) && defined(WIN_USE_CONSOLE_STDIO)
#include "windows.h"
#endif
#include "appdata.h" #include "appdata.h"
#include "helpers.h" #include "helpers.h"
@ -811,39 +808,45 @@ CompanionIcon::CompanionIcon(const QString &baseimage)
void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx) void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx)
{ {
SimulatorInterface * simulator = getCurrentSimulator(); QString fwId = SimulatorLoader::findSimulatorByFirmwareName(getCurrentFirmware()->getId());
if (simulator) { if (fwId.isEmpty()) {
RadioData * simuData = new RadioData(radioData); QMessageBox::warning(NULL,
unsigned int flags = 0; QObject::tr("Warning"),
QObject::tr("Simulator for this firmware is not yet available"));
return;
}
if (modelIdx >= 0) { RadioData * simuData = new RadioData(radioData);
flags |= SIMULATOR_FLAGS_NOTX; unsigned int flags = 0;
simuData->setCurrentModel(modelIdx);
}
SimulatorMainWindow * dialog = new SimulatorMainWindow(parent, simulator, flags); if (modelIdx >= 0) {
if (!dialog->setRadioData(simuData)) { flags |= SIMULATOR_FLAGS_NOTX;
QMessageBox::critical(NULL, QObject::tr("Data Load Error"), QObject::tr("Error occurred while starting simulator.")); simuData->setCurrentModel(modelIdx);
delete dialog; }
delete simuData;
return;
}
dialog->setWindowModality(Qt::ApplicationModal); SimulatorMainWindow * dialog = new SimulatorMainWindow(parent, fwId, flags);
dialog->setAttribute(Qt::WA_DeleteOnClose); 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(); 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(); dialog->show();
} }
else { else {
QMessageBox::warning(NULL, QMessageBox::critical(NULL, QObject::tr("Data Load Error"), QObject::tr("Error occurred while starting simulator."));
QObject::tr("Warning"), dialog->deleteLater();
QObject::tr("Simulator for this firmware is not yet available"));
} }
} }

View file

@ -19,38 +19,29 @@
*/ */
#include "simulatorinterface.h" #include "simulatorinterface.h"
#include <QDebug> #include "customdebug.h"
#include <QDir>
#include <QLibrary>
#include <QLibraryInfo>
#include <QMap>
#include <QMessageBox>
#include "version.h" #include "version.h"
#include <QDebug>
#include <QLibraryInfo>
#if defined _MSC_VER || !defined __GNUC__ #if defined _MSC_VER || !defined __GNUC__
#include <windows.h> #include <windows.h>
#endif #endif
QMap<QString, SimulatorFactory *> 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<QString, QLibrary *> SimulatorLoader::registeredSimulators;
QStringList SimulatorLoader::getAvailableSimulators()
{ {
QLibrary lib(filename); return registeredSimulators.keys();
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();
}
} }
int registerSimulators(const QDir & dir) int SimulatorLoader::registerSimulators(const QDir & dir)
{ {
int noSimulatorsFound = 0;
QStringList filters; QStringList filters;
#if defined(__APPLE__) #if defined(__APPLE__)
filters << "*-simulator.dylib"; filters << "*-simulator.dylib";
@ -59,17 +50,41 @@ int registerSimulators(const QDir & dir)
#else #else
filters << "*-simulator.so"; filters << "*-simulator.so";
#endif #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)) { foreach(QString filename, dir.entryList(filters, QDir::Files)) {
QString libraryFilename = dir.path() + "/" + filename; QLibrary * lib = new QLibrary( dir.path() + "/" + filename);
registerSimulator(libraryFilename);
noSimulatorsFound++; 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("."); QDir dir(".");
if (registerSimulators(dir)) { if (registerSimulators(dir)) {
@ -90,31 +105,93 @@ void registerSimulators()
registerSimulators(dir); 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; QString simuName = name;
while(1) { while(1) {
qDebug() << "searching" << simuName << "simulator"; qCDebug(simulatorInterfaceLoader) << "searching" << simuName << "simulator";
foreach (QString name, registered_simulators.keys()) { if (registeredSimulators.contains(simuName)) {
if (name.contains(simuName)) { ret = simuName;
simuName = name; break;
qDebug() << "found" << simuName;
return registered_simulators[simuName];
}
} }
int pos = simuName.lastIndexOf('-'); if ((pos = simuName.lastIndexOf('-')) <= 0)
if (pos <= 0)
break; break;
simuName = simuName.mid(0, pos); simuName = simuName.mid(0, pos);
if (simuName.count('-') == 0) if (simuName.count('-') == 0)
break; 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; 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;
} }

View file

@ -23,11 +23,16 @@
#include "boards.h" #include "boards.h"
#include "constants.h" #include "constants.h"
#include <algorithm>
#include <inttypes.h> #include <inttypes.h>
#include <QObject>
#include <QString> #include <QString>
#include <QByteArray> #include <QByteArray>
#include <QDir>
#include <QLibrary>
#include <QMap> #include <QMap>
#include <algorithm>
struct TxInputs struct TxInputs
{ {
@ -122,9 +127,21 @@ class SimulatorFactory {
virtual SimulatorInterface *create() = 0; virtual SimulatorInterface *create() = 0;
}; };
void registerSimulators(); class SimulatorLoader
void unregisterSimulators(); {
SimulatorFactory *getSimulatorFactory(const QString &name); public:
extern QMap<QString, SimulatorFactory *> registered_simulators; 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<QString, QLibrary *> registeredSimulators;
};
#endif // _SIMULATORINTERFACE_H_ #endif // _SIMULATORINTERFACE_H_

View file

@ -40,9 +40,8 @@ extern AppData g; // ensure what "g" means
const quint16 SimulatorMainWindow::m_savedUiStateVersion = 2; 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), QMainWindow(parent, wflags),
m_simulator(simulator),
ui(new Ui::SimulatorMainWindow), ui(new Ui::SimulatorMainWindow),
m_simulatorWidget(NULL), m_simulatorWidget(NULL),
m_consoleWidget(NULL), m_consoleWidget(NULL),
@ -52,12 +51,24 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, SimulatorInterface * s
m_telemetryDockWidget(NULL), m_telemetryDockWidget(NULL),
m_trainerDockWidget(NULL), m_trainerDockWidget(NULL),
m_outputsDockWidget(NULL), m_outputsDockWidget(NULL),
m_simulatorId(firmwareId),
m_exitStatusCode(0),
m_radioProfileId(g.sessionId()), m_radioProfileId(g.sessionId()),
m_radioSizeConstraint(Qt::Horizontal | Qt::Vertical), m_radioSizeConstraint(Qt::Horizontal | Qt::Vertical),
m_firstShow(true), m_firstShow(true),
m_showRadioDocked(true), m_showRadioDocked(true),
m_showMenubar(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); ui->setupUi(this);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
@ -128,25 +139,30 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, SimulatorInterface * s
SimulatorMainWindow::~SimulatorMainWindow() SimulatorMainWindow::~SimulatorMainWindow()
{ {
delete ui;
}
void SimulatorMainWindow::closeEvent(QCloseEvent *)
{
saveUiState();
if (m_telemetryDockWidget) if (m_telemetryDockWidget)
delete m_telemetryDockWidget; delete m_telemetryDockWidget;
if (m_trainerDockWidget) if (m_trainerDockWidget)
delete m_trainerDockWidget; delete m_trainerDockWidget;
if (m_outputsDockWidget) if (m_outputsDockWidget)
delete m_outputsDockWidget; delete m_outputsDockWidget;
if (m_consoleDockWidget)
delete m_consoleDockWidget;
if (m_simulatorDockWidget) if (m_simulatorDockWidget)
delete m_simulatorDockWidget; delete m_simulatorDockWidget;
else if (m_simulatorWidget) else if (m_simulatorWidget)
delete 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() void SimulatorMainWindow::show()
@ -173,7 +189,8 @@ void SimulatorMainWindow::changeEvent(QEvent *e)
} }
} }
QMenu * SimulatorMainWindow::createPopupMenu(){ QMenu * SimulatorMainWindow::createPopupMenu()
{
QMenu * menu = QMainWindow::createPopupMenu(); QMenu * menu = QMainWindow::createPopupMenu();
menu->clear(); menu->clear();
menu->addActions(ui->menuView->actions()); menu->addActions(ui->menuView->actions());
@ -214,6 +231,13 @@ void SimulatorMainWindow::restoreUiState()
restoreState(windowState, m_savedUiStateVersion); restoreState(windowState, m_savedUiStateVersion);
} }
int SimulatorMainWindow::getExitStatus(QString * msg)
{
if (msg)
*msg = m_exitStatusMsg;
return m_exitStatusCode;
}
bool SimulatorMainWindow::setRadioData(RadioData * radioData) bool SimulatorMainWindow::setRadioData(RadioData * radioData)
{ {
return m_simulatorWidget->setRadioData(radioData); return m_simulatorWidget->setRadioData(radioData);

View file

@ -25,7 +25,6 @@
#include <QDockWidget> #include <QDockWidget>
#include <QMainWindow> #include <QMainWindow>
#include <QPointer>
class DebugOutput; class DebugOutput;
class RadioData; class RadioData;
@ -48,13 +47,14 @@ class SimulatorMainWindow : public QMainWindow
Q_OBJECT Q_OBJECT
public: 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(); ~SimulatorMainWindow();
int getExitStatus(QString * msg = Q_NULLPTR);
bool setRadioData(RadioData * radioData); bool setRadioData(RadioData * radioData);
bool useTempDataPath(bool deleteOnClose = true); bool useTempDataPath(bool deleteOnClose = true);
bool setOptions(SimulatorOptions & options, bool withSave = true); bool setOptions(SimulatorOptions & options, bool withSave = true);
QMenu * createPopupMenu(); virtual QMenu * createPopupMenu();
public slots: public slots:
virtual void show(); virtual void show();
@ -95,6 +95,9 @@ class SimulatorMainWindow : public QMainWindow
QDockWidget * m_outputsDockWidget; QDockWidget * m_outputsDockWidget;
QVector<keymapHelp_t> m_keymapHelp; QVector<keymapHelp_t> m_keymapHelp;
QString m_simulatorId;
QString m_exitStatusMsg;
int m_exitStatusCode;
int m_radioProfileId; int m_radioProfileId;
int m_radioSizeConstraint; int m_radioSizeConstraint;
bool m_firstShow; bool m_firstShow;

View file

@ -23,13 +23,14 @@
#include "appdata.h" #include "appdata.h"
#include "constants.h" #include "constants.h"
#include "eeprominterface.h" #include "simulatorinterface.h"
#include "helpers.h" #include "helpers.h"
#include <QFileDialog> #include <QFileDialog>
using namespace Simulator;
extern AppData g; extern AppData g;
extern QMap<QString, SimulatorFactory *> registered_simulators;
SimulatorStartupDialog::SimulatorStartupDialog(SimulatorOptions * options, int * profId, QWidget *parent) : SimulatorStartupDialog::SimulatorStartupDialog(SimulatorOptions * options, int * profId, QWidget *parent) :
QDialog(parent), QDialog(parent),
@ -45,7 +46,7 @@ SimulatorStartupDialog::SimulatorStartupDialog(SimulatorOptions * options, int *
ui->radioProfile->addItem(pi.value(), pi.key()); 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->optFile, SimulatorOptions::START_WITH_FILE);
ui->optGrp_dataSource->setId(ui->optFolder, SimulatorOptions::START_WITH_FOLDER); ui->optGrp_dataSource->setId(ui->optFolder, SimulatorOptions::START_WITH_FOLDER);
@ -151,7 +152,7 @@ void SimulatorStartupDialog::updateContainerTypes(void)
void SimulatorStartupDialog::loadRadioProfile(int id) void SimulatorStartupDialog::loadRadioProfile(int id)
{ {
QString tmpstr; QString tmpstr, tmpstr2;
int i; int i;
if (id < 0 || !g.getActiveProfiles().contains(id)) if (id < 0 || !g.getActiveProfiles().contains(id))
@ -166,8 +167,8 @@ void SimulatorStartupDialog::loadRadioProfile(int id)
tmpstr = m_options->firmwareId; tmpstr = m_options->firmwareId;
if (tmpstr.isEmpty() && !g.profile[id].fwType().isEmpty()) if (tmpstr.isEmpty() && !g.profile[id].fwType().isEmpty())
tmpstr = g.profile[id].fwType(); tmpstr = g.profile[id].fwType();
else if (getSimulatorFactory(tmpstr)) else if (!(tmpstr2 = SimulatorLoader::findSimulatorByFirmwareName(m_options->firmwareId)).isEmpty())
tmpstr = getSimulatorFactory(tmpstr)->name(); tmpstr = tmpstr2;
i = ui->radioType->findText(findRadioId(tmpstr), Qt::MatchContains); i = ui->radioType->findText(findRadioId(tmpstr), Qt::MatchContains);
if (i > -1) if (i > -1)
ui->radioType->setCurrentIndex(i); ui->radioType->setCurrentIndex(i);

View file

@ -28,8 +28,6 @@ namespace Ui {
class SimulatorStartupDialog; class SimulatorStartupDialog;
} }
using namespace Simulator;
class SimulatorStartupDialog : public QDialog class SimulatorStartupDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT

View file

@ -19,13 +19,13 @@
*/ */
#include <QApplication> #include <QApplication>
#include <QTranslator> #include <QDir>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QLocale> #include <QLocale>
#include <QString>
#include <QDir>
#include <QTextStream>
#include <QMessageBox> #include <QMessageBox>
#include <QString>
#include <QTextStream>
#include <QTranslator>
#if defined(JOYSTICKS) || defined(SIMU_AUDIO) #if defined(JOYSTICKS) || defined(SIMU_AUDIO)
#include <SDL.h> #include <SDL.h>
#undef main #undef main
@ -66,20 +66,11 @@ void sharedHelpText(QTextStream &stream)
} }
// list all available radios // list all available radios
stream << endl << QObject::tr("Available radios:") << endl; stream << endl << QObject::tr("Available radios:") << endl;
foreach(QString name, registered_simulators.keys()) { foreach(QString name, SimulatorLoader::getAvailableSimulators()) {
stream << "\t" << name << endl; 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[]) int main(int argc, char *argv[])
{ {
Q_INIT_RESOURCE(companion); Q_INIT_RESOURCE(companion);
@ -100,6 +91,8 @@ int main(int argc, char *argv[])
g.init(); g.init();
QString resultMsg;
QTranslator companionTranslator; QTranslator companionTranslator;
companionTranslator.load(":/companion_" + g.locale()); companionTranslator.load(":/companion_" + g.locale());
QTranslator qtTranslator; QTranslator qtTranslator;
@ -127,9 +120,9 @@ int main(int argc, char *argv[])
registerStorageFactories(); registerStorageFactories();
registerOpenTxFirmwares(); registerOpenTxFirmwares();
registerSimulators(); SimulatorLoader::registerSimulators();
if (!registered_simulators.size()) { if (!SimulatorLoader::getAvailableSimulators().size()) {
showMessage(QObject::tr("ERROR: No simulator libraries available."), QMessageBox::Critical); showMessage(QObject::tr("ERROR: No simulator libraries available."), QMessageBox::Critical);
return finish(3); return finish(3);
} }
@ -142,20 +135,19 @@ int main(int argc, char *argv[])
cliOptions.alias("help", "h"); cliOptions.alias("help", "h");
cliOptions.parse(QCoreApplication::arguments()); cliOptions.parse(QCoreApplication::arguments());
if (cliOptions.count("help") || cliOptions.showUnrecognizedWarning()) { if (cliOptions.count("help") || cliOptions.showUnrecognizedWarning()) {
QString msg; QTextStream stream(&resultMsg);
QTextStream stream(&msg);
stream << QObject::tr("Usage: simulator [OPTION]... [EEPROM.BIN FILE OR DATA FOLDER] ") << endl << endl; stream << QObject::tr("Usage: simulator [OPTION]... [EEPROM.BIN FILE OR DATA FOLDER] ") << endl << endl;
stream << QObject::tr("Options:") << endl; stream << QObject::tr("Options:") << endl;
cliOptions.showUsage(false, stream); cliOptions.showUsage(false, stream);
sharedHelpText(stream); sharedHelpText(stream);
// display // display
showMessage(msg, QMessageBox::Information); showMessage(resultMsg, QMessageBox::Information);
return finish(1); return finish(1);
} }
// TODO : defaults should be set in Profile::init() // TODO : defaults should be set in Profile::init()
if (simOptions.firmwareId.isEmpty()) if (simOptions.firmwareId.isEmpty())
simOptions.firmwareId = findFirmwareId(profileId); simOptions.firmwareId = SimulatorLoader::findSimulatorByFirmwareName(g.profile[profileId].fwType());
if (simOptions.dataFolder.isEmpty()) if (simOptions.dataFolder.isEmpty())
simOptions.dataFolder = g.eepromDir(); simOptions.dataFolder = g.eepromDir();
if (simOptions.sdPath.isEmpty()) if (simOptions.sdPath.isEmpty())
@ -209,28 +201,16 @@ int main(int argc, char *argv[])
qDebug() << "profileId=" << profileId << simOptions; qDebug() << "profileId=" << profileId << simOptions;
if (profileId < 0 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) { 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]") resultMsg = 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); showMessage(resultMsg.arg(profileId).arg(simOptions.firmwareId, simOptions.dataFile), QMessageBox::Critical);
return finish(1); return finish(1);
} }
if (!g.getActiveProfiles().contains(profileId) || !registered_simulators.keys().contains(simOptions.firmwareId)) { if (!g.getActiveProfiles().contains(profileId) || !SimulatorLoader::getAvailableSimulators().contains(simOptions.firmwareId)) {
QString msg; QTextStream stream(&resultMsg);
QTextStream stream(&msg);
stream << QObject::tr("ERROR: Radio profile or simulator firmware not found.\nProfile ID: [%1]; Radio ID: [%2]") stream << QObject::tr("ERROR: Radio profile or simulator firmware not found.\nProfile ID: [%1]; Radio ID: [%2]")
.arg(profileId).arg(simOptions.firmwareId); .arg(profileId).arg(simOptions.firmwareId);
sharedHelpText(stream); sharedHelpText(stream);
showMessage(msg, QMessageBox::Critical); showMessage(resultMsg, 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);
return finish(2); return finish(2);
} }
@ -239,26 +219,33 @@ int main(int argc, char *argv[])
g.sessionId(profileId); g.sessionId(profileId);
g.simuLastProfId(profileId); g.simuLastProfId(profileId);
int result = 1; int result = 0;
SimulatorMainWindow * mainWindow = new SimulatorMainWindow(NULL, simulator, SIMULATOR_FLAGS_STANDALONE); SimulatorMainWindow * mainWindow = new SimulatorMainWindow(NULL, simOptions.firmwareId, SIMULATOR_FLAGS_STANDALONE);
if (mainWindow->setOptions(simOptions, true)) { 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->start();
mainWindow->show(); mainWindow->show();
result = app.exec(); result = app.exec();
if (!result) {
if ((result = mainWindow->getExitStatus(&resultMsg)) && !resultMsg.isEmpty())
qWarning() << "Exit message from SimulatorMainWindow:" << resultMsg;
}
} }
else { else {
result = 3; result = 3;
} }
delete mainWindow;
delete simulator;
delete mainWindow;
return finish(result); return finish(result);
} }
int finish(int exitCode) int finish(int exitCode)
{ {
qDebug() << "SIMULATOR EXIT" << exitCode; SimulatorLoader::unregisterSimulators();
unregisterSimulators();
unregisterOpenTxFirmwares(); unregisterOpenTxFirmwares();
unregisterStorageFactories(); unregisterStorageFactories();
@ -266,5 +253,6 @@ int finish(int exitCode)
SDL_Quit(); SDL_Quit();
#endif #endif
qDebug() << "SIMULATOR EXIT" << exitCode;
return exitCode; return exitCode;
} }