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:
parent
dc89d2d630
commit
e48b1fd07d
13 changed files with 268 additions and 167 deletions
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,10 @@
|
|||
#include <QLoggingCategory>
|
||||
|
||||
// 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
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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<EEPROMInterface *> eepromInterfaces;
|
||||
|
||||
|
|
|
@ -25,9 +25,6 @@
|
|||
#elif defined __GNUC__
|
||||
#include <unistd.h>
|
||||
#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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,38 +19,29 @@
|
|||
*/
|
||||
|
||||
#include "simulatorinterface.h"
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QLibrary>
|
||||
#include <QLibraryInfo>
|
||||
#include <QMap>
|
||||
#include <QMessageBox>
|
||||
#include "customdebug.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLibraryInfo>
|
||||
|
||||
#if defined _MSC_VER || !defined __GNUC__
|
||||
#include <windows.h>
|
||||
#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);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -23,11 +23,16 @@
|
|||
|
||||
#include "boards.h"
|
||||
#include "constants.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QDir>
|
||||
#include <QLibrary>
|
||||
#include <QMap>
|
||||
#include <algorithm>
|
||||
|
||||
struct TxInputs
|
||||
{
|
||||
|
@ -122,9 +127,21 @@ class SimulatorFactory {
|
|||
virtual SimulatorInterface *create() = 0;
|
||||
};
|
||||
|
||||
void registerSimulators();
|
||||
void unregisterSimulators();
|
||||
SimulatorFactory *getSimulatorFactory(const QString &name);
|
||||
extern QMap<QString, SimulatorFactory *> 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<QString, QLibrary *> registeredSimulators;
|
||||
};
|
||||
|
||||
#endif // _SIMULATORINTERFACE_H_
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include <QDockWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QPointer>
|
||||
|
||||
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<keymapHelp_t> m_keymapHelp;
|
||||
QString m_simulatorId;
|
||||
QString m_exitStatusMsg;
|
||||
int m_exitStatusCode;
|
||||
int m_radioProfileId;
|
||||
int m_radioSizeConstraint;
|
||||
bool m_firstShow;
|
||||
|
|
|
@ -23,13 +23,14 @@
|
|||
|
||||
#include "appdata.h"
|
||||
#include "constants.h"
|
||||
#include "eeprominterface.h"
|
||||
#include "simulatorinterface.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
using namespace Simulator;
|
||||
|
||||
extern AppData g;
|
||||
extern QMap<QString, SimulatorFactory *> 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);
|
||||
|
|
|
@ -28,8 +28,6 @@ namespace Ui {
|
|||
class SimulatorStartupDialog;
|
||||
}
|
||||
|
||||
using namespace Simulator;
|
||||
|
||||
class SimulatorStartupDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTranslator>
|
||||
#include <QDir>
|
||||
#include <QLibraryInfo>
|
||||
#include <QLocale>
|
||||
#include <QString>
|
||||
#include <QDir>
|
||||
#include <QTextStream>
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
#include <QTranslator>
|
||||
#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
|
||||
#include <SDL.h>
|
||||
#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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue