[xswiftbus] Make xswiftbus completely Qt free

This commit is contained in:
Roland Winklmeier
2018-03-25 16:10:54 +02:00
parent b0a8fcaa45
commit 6a8ae67e06
13 changed files with 525 additions and 429 deletions

View File

@@ -97,8 +97,10 @@ namespace BlackSimPlugin
m_slowTimer.setObjectName(this->objectName().append(":m_slowTimer")); m_slowTimer.setObjectName(this->objectName().append(":m_slowTimer"));
connect(&m_fastTimer, &QTimer::timeout, this, &CSimulatorXPlane::fastTimerTimeout); connect(&m_fastTimer, &QTimer::timeout, this, &CSimulatorXPlane::fastTimerTimeout);
connect(&m_slowTimer, &QTimer::timeout, this, &CSimulatorXPlane::slowTimerTimeout); connect(&m_slowTimer, &QTimer::timeout, this, &CSimulatorXPlane::slowTimerTimeout);
connect(&m_airportUpdater, &QTimer::timeout, this, &CSimulatorXPlane::updateAirportsInRange);
m_fastTimer.start(100); m_fastTimer.start(100);
m_slowTimer.start(1000); m_slowTimer.start(1000);
m_airportUpdater.start(60000);
this->setDefaultModel({ "Jets A320_a A320_a_Austrian_Airlines A320_a_Austrian_Airlines", CAircraftModel::TypeModelMatchingDefaultModel, this->setDefaultModel({ "Jets A320_a A320_a_Austrian_Airlines A320_a_Austrian_Airlines", CAircraftModel::TypeModelMatchingDefaultModel,
"A320 AUA", CAircraftIcaoCode("A320", "L2J")}); "A320 AUA", CAircraftIcaoCode("A320", "L2J")});
@@ -793,6 +795,11 @@ namespace BlackSimPlugin
this->rememberElevationAndCG(callsign, elevation, CLength(modelVerticalOffsetMeters, CLengthUnit::m())); this->rememberElevationAndCG(callsign, elevation, CLength(modelVerticalOffsetMeters, CLengthUnit::m()));
} }
void CSimulatorXPlane::updateAirportsInRange()
{
if (this->isConnected()) { m_serviceProxy->updateAirportsInRange(); }
}
BlackCore::ISimulator *CSimulatorXPlaneFactory::create(const CSimulatorPluginInfo &info, BlackCore::ISimulator *CSimulatorXPlaneFactory::create(const CSimulatorPluginInfo &info,
IOwnAircraftProvider *ownAircraftProvider, IOwnAircraftProvider *ownAircraftProvider,
IRemoteAircraftProvider *remoteAircraftProvider, IRemoteAircraftProvider *remoteAircraftProvider,

View File

@@ -190,6 +190,7 @@ namespace BlackSimPlugin
void requestRemoteAircraftDataFromXPlane(); void requestRemoteAircraftDataFromXPlane();
void updateRemoteAircraftFromSimulator(const QString &callsign, double latitudeDeg, double longitudeDeg, double elevationMeters, double modelVerticalOffsetMeters); void updateRemoteAircraftFromSimulator(const QString &callsign, double latitudeDeg, double longitudeDeg, double elevationMeters, double modelVerticalOffsetMeters);
void updateAirportsInRange();
static constexpr int GuessRemoteAircraftPartsCycle = 20; //!< guess every n-th cycle static constexpr int GuessRemoteAircraftPartsCycle = 20; //!< guess every n-th cycle
@@ -201,6 +202,7 @@ namespace BlackSimPlugin
CXSwiftBusWeatherProxy *m_weatherProxy { nullptr }; CXSwiftBusWeatherProxy *m_weatherProxy { nullptr };
QTimer m_fastTimer; QTimer m_fastTimer;
QTimer m_slowTimer; QTimer m_slowTimer;
QTimer m_airportUpdater;
BlackMisc::Aviation::CAirportList m_airportsInRange; //!< aiports in range of own aircraft BlackMisc::Aviation::CAirportList m_airportsInRange; //!< aiports in range of own aircraft
BlackMisc::CData<BlackMisc::Simulation::Data::TModelSetCacheXP> m_modelSet { this }; BlackMisc::CData<BlackMisc::Simulation::Data::TModelSetCacheXP> m_modelSet { this };

View File

@@ -20,17 +20,6 @@
#define XPLM_MSG_LIVERY_LOADED 108 #define XPLM_MSG_LIVERY_LOADED 108
#endif #endif
// Change QSharedPointer<QCoreApplication> to QSharedPointer<QApplication> below
// in case you want to have Qt Gui components inside a X-Plane plugin. The current
// default was used since QApplication causes an infinite loop in X-Plane on MacOS
// platforms. X-Plane is allocating an NSApplication but never calling run(), rather
// it controls the main loop itself and pumps the event Q as needed. This causes
// unusual start conditions for QCocoaEventDispatcher and ends up in the infinite
// loop. Since QCoreApplication is not using QCocoaEventDispatcher it works fine
// and is used as a workaround.
// See https://dev.vatsim-germany.org/issues/293 for more information.
QSharedPointer<QCoreApplication> g_qApp;
XSwiftBus::CPlugin *g_plugin; XSwiftBus::CPlugin *g_plugin;
PLUGIN_API int XPluginStart(char *o_name, char *o_sig, char *o_desc) PLUGIN_API int XPluginStart(char *o_name, char *o_sig, char *o_desc)
@@ -54,10 +43,6 @@ PLUGIN_API void XPluginStop()
PLUGIN_API int XPluginEnable() PLUGIN_API int XPluginEnable()
{ {
QXPlaneMessageHandler::install();
g_qApp = QSharedApplication::sharedInstance();
QXPlaneEventLoop::exec();
g_plugin = new XSwiftBus::CPlugin; g_plugin = new XSwiftBus::CPlugin;
return 1; return 1;
} }
@@ -65,7 +50,6 @@ PLUGIN_API int XPluginEnable()
PLUGIN_API void XPluginDisable() PLUGIN_API void XPluginDisable()
{ {
delete g_plugin; delete g_plugin;
g_qApp.reset();
} }
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID from, long msg, void *param) PLUGIN_API void XPluginReceiveMessage(XPLMPluginID from, long msg, void *param)

View File

@@ -13,7 +13,6 @@
#include "weather.h" #include "weather.h"
#include "utils.h" #include "utils.h"
#include "XPLM/XPLMProcessing.h" #include "XPLM/XPLMProcessing.h"
#include <QTimer>
#include <functional> #include <functional>
#include <thread> #include <thread>
@@ -71,6 +70,8 @@ namespace XSwiftBus
m_service = new CService(m_dbusConnection.get()); m_service = new CService(m_dbusConnection.get());
m_traffic = new CTraffic(m_dbusConnection.get()); m_traffic = new CTraffic(m_dbusConnection.get());
m_weather = new CWeather(m_dbusConnection.get()); m_weather = new CWeather(m_dbusConnection.get());
INFO_LOG("XSwiftBus started.");
} }
void CPlugin::onAircraftModelChanged() void CPlugin::onAircraftModelChanged()

View File

@@ -22,8 +22,6 @@
#endif #endif
#include "dbusconnection.h" #include "dbusconnection.h"
#include "menus.h" #include "menus.h"
#include <QObject>
#include <QVector>
#include <memory> #include <memory>
#include <thread> #include <thread>
@@ -36,10 +34,8 @@ namespace XSwiftBus
/*! /*!
* Main plugin class * Main plugin class
*/ */
class CPlugin : public QObject class CPlugin
{ {
Q_OBJECT
public: public:
//! Constructor //! Constructor
CPlugin(); CPlugin();

View File

@@ -10,11 +10,8 @@
#include "service.h" #include "service.h"
#include <XPLM/XPLMPlanes.h> #include <XPLM/XPLMPlanes.h>
#include <XPLM/XPLMUtilities.h> #include <XPLM/XPLMUtilities.h>
#include <QDebug> #include <fstream>
#include <QTimer> #include "utils.h"
#include <QRegularExpression>
#include <QStringBuilder>
#include <QDir>
// clazy:excludeall=reserve-candidates // clazy:excludeall=reserve-candidates
@@ -25,9 +22,6 @@ namespace XSwiftBus
{ {
registerDBusObjectPath(XSWIFTBUS_SERVICE_INTERFACENAME, XSWIFTBUS_SERVICE_OBJECTPATH); registerDBusObjectPath(XSWIFTBUS_SERVICE_INTERFACENAME, XSWIFTBUS_SERVICE_OBJECTPATH);
m_messages.addMessage( { "xswiftbus started.", 0, 255, 255 } ); m_messages.addMessage( { "xswiftbus started.", 0, 255, 255 } );
m_airportUpdater = new QTimer();
m_airportUpdater->start(60000);
QObject::connect(m_airportUpdater, &QTimer::timeout, [this] () { updateAirportsInRange(); });
updateAirportsInRange(); updateAirportsInRange();
} }
@@ -36,35 +30,38 @@ namespace XSwiftBus
char filename[256]; char filename[256];
char path[512]; char path[512];
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path); XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
const auto model = extractAcfProperties(path, QFileInfo(path)); const auto model = extractAcfProperties(path);
emitAircraftModelChanged(path, filename, getAircraftLivery(), getAircraftIcaoCode(), model.getModelString(), model.getName(), getAircraftDescription()); emitAircraftModelChanged(path, filename, getAircraftLivery(), getAircraftIcaoCode(), model.getModelString(), model.getName(), getAircraftDescription());
} }
void CService::addTextMessage(const QString &text, double red, double green, double blue) void CService::addTextMessage(const std::string &text, double red, double green, double blue)
{ {
if (text.isEmpty()) { return; } if (text.empty()) { return; }
int lineLength = m_messages.maxLineLength() - 1; static const std::string ellipsis = "...";
QStringList wrappedLines; int lineLength = m_messages.maxLineLength() - ellipsis.size();
for (int i = 0; i < text.size(); i += lineLength) std::vector<std::string> wrappedLines;
for (size_t i = 0; i < text.size(); i += lineLength)
{ {
static const QChar ellipsis = 0x2026; // static const QChar ellipsis = 0x2026;
wrappedLines.push_back(text.mid(i, lineLength) + ellipsis); // wrappedLines.push_back(QString::fromStdString(text).mid(i, lineLength) + ellipsis);
wrappedLines.push_back(text.substr(i, lineLength) + ellipsis);
} }
wrappedLines.back().chop(1); wrappedLines.back().erase(wrappedLines.back().size() - 3);
if (wrappedLines.back().isEmpty()) { wrappedLines.pop_back(); } if (wrappedLines.back().empty()) { wrappedLines.pop_back(); }
else if (wrappedLines.back().size() == 1 && wrappedLines.size() > 1) else if (wrappedLines.back().size() == ellipsis.size() && wrappedLines.size() > 1)
{ {
(wrappedLines.end() - 2)->chop(1); auto secondLastLine = wrappedLines.end() - 2;
(wrappedLines.end() - 2)->append(wrappedLines.back()); secondLastLine->erase(wrappedLines.back().size() - 3);
secondLastLine->append(wrappedLines.back());
wrappedLines.pop_back(); wrappedLines.pop_back();
} }
for (const auto &line : wrappedLines) for (const auto &line : wrappedLines)
{ {
m_messages.addMessage({ line.toStdString(), static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue) }); m_messages.addMessage({ line, static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue) });
} }
} }
QString CService::getAircraftModelPath() const std::string CService::getAircraftModelPath() const
{ {
char filename[256]; char filename[256];
char path[512]; char path[512];
@@ -72,7 +69,7 @@ namespace XSwiftBus
return path; return path;
} }
QString CService::getAircraftModelFilename() const std::string CService::getAircraftModelFilename() const
{ {
char filename[256]; char filename[256];
char path[512]; char path[512];
@@ -80,21 +77,21 @@ namespace XSwiftBus
return filename; return filename;
} }
QString CService::getAircraftModelString() const std::string CService::getAircraftModelString() const
{ {
char filename[256]; char filename[256];
char path[512]; char path[512];
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path); XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
const auto model = extractAcfProperties(path, QFileInfo(path)); const auto model = extractAcfProperties(path);
return model.getModelString(); return model.getModelString();
} }
QString CService::getAircraftName() const std::string CService::getAircraftName() const
{ {
char filename[256]; char filename[256];
char path[512]; char path[512];
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path); XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
const auto model = extractAcfProperties(path, QFileInfo(path)); const auto model = extractAcfProperties(path);
return model.getName(); return model.getName();
} }
@@ -114,14 +111,14 @@ namespace XSwiftBus
return version % 100; return version % 100;
} }
QString CService::getXPlaneInstallationPath() const std::string CService::getXPlaneInstallationPath() const
{ {
char path[512]; char path[512];
XPLMGetSystemPath(path); XPLMGetSystemPath(path);
return path; return path;
} }
QString CService::getXPlanePreferencesPath() const std::string CService::getXPlanePreferencesPath() const
{ {
char path[512]; char path[512];
XPLMGetPrefsPath(path); XPLMGetPrefsPath(path);
@@ -206,7 +203,7 @@ namespace XSwiftBus
queueDBusCall([=]() queueDBusCall([=]()
{ {
addTextMessage(QString::fromStdString(text), red, green, blue); addTextMessage(text, red, green, blue);
}); });
} }
else if (message.getMethodName() == "getOwnAircraftSituationData") else if (message.getMethodName() == "getOwnAircraftSituationData")
@@ -246,49 +243,49 @@ namespace XSwiftBus
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getAircraftModelPath().toStdString()); sendDBusReply(sender, serial, getAircraftModelPath());
}); });
} }
else if (message.getMethodName() == "getAircraftModelFilename") else if (message.getMethodName() == "getAircraftModelFilename")
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getAircraftModelFilename().toStdString()); sendDBusReply(sender, serial, getAircraftModelFilename());
}); });
} }
else if (message.getMethodName() == "getAircraftModelString") else if (message.getMethodName() == "getAircraftModelString")
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getAircraftModelString().toStdString()); sendDBusReply(sender, serial, getAircraftModelString());
}); });
} }
else if (message.getMethodName() == "getAircraftName") else if (message.getMethodName() == "getAircraftName")
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getAircraftName().toStdString()); sendDBusReply(sender, serial, getAircraftName());
}); });
} }
else if (message.getMethodName() == "getAircraftLivery") else if (message.getMethodName() == "getAircraftLivery")
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getAircraftLivery().toStdString()); sendDBusReply(sender, serial, getAircraftLivery());
}); });
} }
else if (message.getMethodName() == "getAircraftIcaoCode") else if (message.getMethodName() == "getAircraftIcaoCode")
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getAircraftIcaoCode().toStdString()); sendDBusReply(sender, serial, getAircraftIcaoCode());
}); });
} }
else if (message.getMethodName() == "getAircraftDescription") else if (message.getMethodName() == "getAircraftDescription")
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getAircraftDescription().toStdString()); sendDBusReply(sender, serial, getAircraftDescription());
}); });
} }
else if (message.getMethodName() == "getXPlaneVersionMajor") else if (message.getMethodName() == "getXPlaneVersionMajor")
@@ -309,14 +306,14 @@ namespace XSwiftBus
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getXPlaneInstallationPath().toStdString()); sendDBusReply(sender, serial, getXPlaneInstallationPath());
}); });
} }
else if (message.getMethodName() == "getXPlanePreferencesPath") else if (message.getMethodName() == "getXPlanePreferencesPath")
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
sendDBusReply(sender, serial, getXPlanePreferencesPath().toStdString()); sendDBusReply(sender, serial, getXPlanePreferencesPath());
}); });
} }
else if (message.getMethodName() == "isPaused") else if (message.getMethodName() == "isPaused")
@@ -599,7 +596,7 @@ namespace XSwiftBus
{ {
queueDBusCall([=]() queueDBusCall([=]()
{ {
std::vector<double> array = getEngineN1Percentage().toVector().toStdVector(); std::vector<double> array = getEngineN1Percentage();
sendDBusReply(sender, serial, array); sendDBusReply(sender, serial, array);
}); });
} }
@@ -633,19 +630,19 @@ namespace XSwiftBus
return 1; return 1;
} }
void CService::emitAircraftModelChanged(const QString &path, const QString &filename, const QString &livery, void CService::emitAircraftModelChanged(const std::string &path, const std::string &filename, const std::string &livery,
const QString &icao, const QString &modelString, const QString &name, const std::string &icao, const std::string &modelString, const std::string &name,
const QString &description) const std::string &description)
{ {
CDBusMessage signalAircraftModelChanged = CDBusMessage::createSignal(XSWIFTBUS_SERVICE_OBJECTPATH, XSWIFTBUS_SERVICE_INTERFACENAME, "aircraftModelChanged"); CDBusMessage signalAircraftModelChanged = CDBusMessage::createSignal(XSWIFTBUS_SERVICE_OBJECTPATH, XSWIFTBUS_SERVICE_INTERFACENAME, "aircraftModelChanged");
signalAircraftModelChanged.beginArgumentWrite(); signalAircraftModelChanged.beginArgumentWrite();
signalAircraftModelChanged.appendArgument(path.toStdString()); signalAircraftModelChanged.appendArgument(path);
signalAircraftModelChanged.appendArgument(filename.toStdString()); signalAircraftModelChanged.appendArgument(filename);
signalAircraftModelChanged.appendArgument(livery.toStdString()); signalAircraftModelChanged.appendArgument(livery);
signalAircraftModelChanged.appendArgument(icao.toStdString()); signalAircraftModelChanged.appendArgument(icao);
signalAircraftModelChanged.appendArgument(modelString.toStdString()); signalAircraftModelChanged.appendArgument(modelString);
signalAircraftModelChanged.appendArgument(name.toStdString()); signalAircraftModelChanged.appendArgument(name);
signalAircraftModelChanged.appendArgument(description.toStdString()); signalAircraftModelChanged.appendArgument(description);
sendDBusMessage(signalAircraftModelChanged); sendDBusMessage(signalAircraftModelChanged);
} }
@@ -676,105 +673,115 @@ namespace XSwiftBus
return closestAirports; return closestAirports;
} }
QString descriptionForFlyableModel(const CAircraftModel &model) //! Qt free version of BlackMisc::Simulation::XPlane::descriptionForFlyableModel()
std::string descriptionForFlyableModel(const CAircraftModel &model)
{ {
if (!model.getName().isEmpty()) if (!model.getName().empty())
{ {
if (model.getDistributor().hasDescription() && !model.getName().contains(model.getDistributor().getDescription())) if (model.getDistributor().hasDescription() && model.getName().find(model.getDistributor().getDescription()) == std::string::npos)
{ {
return QStringLiteral("[ACF] ") % model.getName() % QStringLiteral(" by ") % model.getDistributor().getDescription(); return std::string("[ACF] ") + model.getName() + " by " + model.getDistributor().getDescription();
} }
else else
{ {
return QStringLiteral("[ACF] ") % model.getName(); return std::string("[ACF] ") + model.getName();
} }
} }
else if (model.hasAircraftDesignator()) else if (model.hasAircraftDesignator())
{ {
if (model.getDistributor().hasDescription()) if (model.getDistributor().hasDescription())
{ {
return QStringLiteral("[ACF] ") % model.getAircraftIcaoCodeDesignator() % QStringLiteral(" by ") % model.getDistributor().getDescription(); return std::string("[ACF] ") + model.getAircraftIcaoCodeDesignator() + " by " + model.getDistributor().getDescription();
} }
else else
{ {
return QStringLiteral("[ACF] ") % model.getAircraftIcaoCodeDesignator(); return std::string("[ACF] ") + model.getAircraftIcaoCodeDesignator();
} }
} }
return QStringLiteral("[ACF]"); return std::string("[ACF]");
} }
QString stringForFlyableModel(const CAircraftModel &model, const QFileInfo &acfFile) //! Qt free version of BlackMisc::Simulation::XPlane::stringForFlyableModel()
std::string stringForFlyableModel(const CAircraftModel &model, const std::string &acfFile)
{ {
if (model.getDistributor().hasDescription()) if (model.getDistributor().hasDescription())
{ {
if (!model.getName().isEmpty()) if (!model.getName().empty())
{ {
if (model.getName().contains(model.getDistributor().getDescription())) if (model.getName().find(model.getDistributor().getDescription()) != std::string::npos)
{ {
return model.getName(); return model.getName();
} }
else else
{ {
return model.getDistributor().getDescription() % ' ' % model.getName(); return model.getDistributor().getDescription() + ' ' + model.getName();
} }
} }
else if (model.hasAircraftDesignator()) else if (model.hasAircraftDesignator())
{ {
return model.getDistributor().getDescription() % ' ' % model.getAircraftIcaoCodeDesignator(); return model.getDistributor().getDescription() + ' ' + model.getAircraftIcaoCodeDesignator();
} }
} }
return acfFile.dir().dirName() % ' ' % acfFile.baseName(); return getDirName(acfFile) + ' ' + getBaseName(acfFile);
} }
CAircraftModel CService::extractAcfProperties(const QString &filePath, const QFileInfo &fileInfo) CAircraftModel CService::extractAcfProperties(const std::string &filePath)
{ {
CAircraftModel model; CAircraftModel model;
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { return model; }
QTextStream ts(&file); std::ifstream fs(filePath, std::ios::in | std::ios::binary);
if (ts.readLine() == "I" && ts.readLine().contains("version") && ts.readLine() == "ACF") if(!fs.is_open()) { return model; }
std::string i;
std::string version;
std::string acf;
std::getline(fs, i);
std::getline(fs, version);
std::getline(fs, acf);
if (i == "I" && version.find("version") != std::string::npos && acf == "ACF")
{ {
while (!ts.atEnd()) std::string line;
while (std::getline(fs, line))
{ {
const QString line = ts.readLine(); auto tokens = split(line, 2);
QVector<QStringRef> tokens = line.splitRef(' ', QString::SkipEmptyParts); if (tokens.size() < 3 || tokens.at(0) != "P") { continue; }
if (tokens.size() < 3 || tokens.at(0) != QLatin1String("P")) { continue; } if (tokens.at(1) == "acf/_ICAO")
if (tokens.at(1) == QLatin1String("acf/_ICAO"))
{ {
const QString icao(tokens.at(2).toString()); const std::string icao(tokens.at(2));
model.setAircraftIcaoCode(icao); model.setAircraftIcaoCode(icao);
} }
else if (tokens.at(1) == QLatin1String("acf/_descrip")) else if (tokens.at(1) == "acf/_descrip")
{ {
const QString desc(line.mid(tokens.at(2).position())); const std::string desc(tokens.at(2));
model.setDescription("[ACF] " % desc); model.setDescription("[ACF] " + desc);
} }
else if (tokens.at(1) == QLatin1String("acf/_name")) else if (tokens.at(1) == "acf/_name")
{ {
const QString name(line.mid(tokens.at(2).position())); const std::string name(tokens.at(2));
model.setName(name); model.setName(name);
} }
else if (tokens.at(1) == QLatin1String("acf/_studio")) else if (tokens.at(1) == "acf/_studio")
{ {
const CDistributor dist(line.mid(tokens.at(2).position())); const CDistributor dist(tokens.at(2));
model.setDistributor(dist); model.setDistributor(dist);
} }
else if (tokens.at(1) == QLatin1String("acf/_author")) else if (tokens.at(1) == "acf/_author")
{ {
if (model.getDistributor().hasDescription()) { continue; } if (model.getDistributor().hasDescription()) { continue; }
thread_local const QRegularExpression end("\\W\\s", QRegularExpression::UseUnicodePropertiesOption); std::string author = tokens.at(2);
QString author = line.mid(tokens.at(2).position()); size_t pos = author.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
author = author.left(author.indexOf(end)).trimmed(); author = author.substr(0, pos);
if (author.isEmpty()) { continue; } if (author.empty()) { continue; }
const CDistributor dist(author); const CDistributor dist(author);
model.setDistributor(dist); model.setDistributor(dist);
} }
} }
} }
file.close();
model.setModelString(stringForFlyableModel(model, fileInfo)); fs.close();
model.setModelString(stringForFlyableModel(model, filePath));
if (!model.hasDescription()) { model.setDescription(descriptionForFlyableModel(model)); } if (!model.hasDescription()) { model.setDescription(descriptionForFlyableModel(model)); }
return model; return model;
} }

View File

@@ -21,12 +21,7 @@
#include "messages.h" #include "messages.h"
#include "navdatareference.h" #include "navdatareference.h"
#include <XPLM/XPLMNavigation.h> #include <XPLM/XPLMNavigation.h>
#include <QStringList> #include <string>
#include <QObject>
#include <QList>
#include <QFileInfo>
class QTimer;
//! \cond PRIVATE //! \cond PRIVATE
#define XSWIFTBUS_SERVICE_INTERFACENAME "org.swift_project.xswiftbus.service" #define XSWIFTBUS_SERVICE_INTERFACENAME "org.swift_project.xswiftbus.service"
@@ -40,15 +35,20 @@ namespace XSwiftBus
class CDistributor class CDistributor
{ {
public: public:
//! Default constructor
CDistributor() = default; CDistributor() = default;
CDistributor(const QString &distributor) : m_distributor(distributor) {}
bool hasDescription() const { return !m_description.isEmpty(); } //! Constructor
QString getDescription() const { return m_description; } CDistributor(const std::string &description) : m_description(description) {}
//! \copydoc BlackMisc::Simulation::CDistributor::hasDescription
bool hasDescription() const { return !m_description.empty(); }
//! \copydoc BlackMisc::Simulation::CDistributor::getDescription
std::string getDescription() const { return m_description; }
private: private:
QString m_distributor; std::string m_description;
QString m_description;
}; };
//! Simplified implementation of \sa BlackMisc::Simulation::CAircraftModel //! Simplified implementation of \sa BlackMisc::Simulation::CAircraftModel
@@ -58,44 +58,44 @@ namespace XSwiftBus
CAircraftModel() = default; CAircraftModel() = default;
//! \copydoc BlackMisc::Simulation::CAircraftModel::hasDescription //! \copydoc BlackMisc::Simulation::CAircraftModel::hasDescription
bool hasDescription() const { return !m_description.isEmpty(); } bool hasDescription() const { return !m_description.empty(); }
//! \copydoc BlackMisc::Simulation::CAircraftModel::hasAircraftDesignator //! \copydoc BlackMisc::Simulation::CAircraftModel::hasAircraftDesignator
bool hasAircraftDesignator() const { return !m_icao.isEmpty(); } bool hasAircraftDesignator() const { return !m_icao.empty(); }
//! \copydoc BlackMisc::Simulation::CAircraftModel::getName //! \copydoc BlackMisc::Simulation::CAircraftModel::getName
QString getName() const { return m_name; } std::string getName() const { return m_name; }
//! \copydoc BlackMisc::Simulation::CAircraftModel::getDistributor //! \copydoc BlackMisc::Simulation::CAircraftModel::getDistributor
CDistributor getDistributor() const { return m_distributor; } CDistributor getDistributor() const { return m_distributor; }
//! \copydoc BlackMisc::Simulation::CAircraftModel::getAircraftIcaoCodeDesignator //! \copydoc BlackMisc::Simulation::CAircraftModel::getAircraftIcaoCodeDesignator
QString getAircraftIcaoCodeDesignator() const { return m_icao; } std::string getAircraftIcaoCodeDesignator() const { return m_icao; }
//! \copydoc BlackMisc::Simulation::CAircraftModel::getModelString //! \copydoc BlackMisc::Simulation::CAircraftModel::getModelString
QString getModelString() const { return m_modelString; } std::string getModelString() const { return m_modelString; }
//! \copydoc BlackMisc::Simulation::CAircraftModel::setAircraftIcaoCode //! \copydoc BlackMisc::Simulation::CAircraftModel::setAircraftIcaoCode
void setAircraftIcaoCode(const QString &icao) { m_icao = icao; } void setAircraftIcaoCode(const std::string &icao) { m_icao = icao; }
//! \copydoc BlackMisc::Simulation::CAircraftModel::setDescription //! \copydoc BlackMisc::Simulation::CAircraftModel::setDescription
void setDescription(const QString &description) { m_description = description; } void setDescription(const std::string &description) { m_description = description; }
//! \copydoc BlackMisc::Simulation::CAircraftModel::setName //! \copydoc BlackMisc::Simulation::CAircraftModel::setName
void setName(const QString &name) { m_name = name; } void setName(const std::string &name) { m_name = name; }
//! \copydoc BlackMisc::Simulation::CAircraftModel::setDistributor //! \copydoc BlackMisc::Simulation::CAircraftModel::setDistributor
void setDistributor(const CDistributor &distributor) { m_distributor = distributor; } void setDistributor(const CDistributor &distributor) { m_distributor = distributor; }
//! \copydoc BlackMisc::Simulation::CAircraftModel::setModelString //! \copydoc BlackMisc::Simulation::CAircraftModel::setModelString
void setModelString(const QString &modelString) { m_modelString = modelString; } void setModelString(const std::string &modelString) { m_modelString = modelString; }
private: private:
QString m_name; std::string m_name;
QString m_icao; std::string m_icao;
QString m_description; std::string m_description;
CDistributor m_distributor; CDistributor m_distributor;
QString m_modelString; std::string m_modelString;
}; };
/*! /*!
@@ -111,16 +111,16 @@ namespace XSwiftBus
~CService() override = default; ~CService() override = default;
//! DBus interface name //! DBus interface name
static const QString &InterfaceName() static const std::string &InterfaceName()
{ {
static const QString s(XSWIFTBUS_SERVICE_INTERFACENAME); static const std::string s(XSWIFTBUS_SERVICE_INTERFACENAME);
return s; return s;
} }
//! DBus object path //! DBus object path
static const QString &ObjectPath() static const std::string &ObjectPath()
{ {
static const QString s(XSWIFTBUS_SERVICE_OBJECTPATH); static const std::string s(XSWIFTBUS_SERVICE_OBJECTPATH);
return s; return s;
} }
@@ -128,31 +128,31 @@ namespace XSwiftBus
void onAircraftModelChanged(); void onAircraftModelChanged();
//! Add a text message to the on-screen display, with RGB components in the range [0,1] //! Add a text message to the on-screen display, with RGB components in the range [0,1]
void addTextMessage(const QString &text, double red, double green, double blue); void addTextMessage(const std::string &text, double red, double green, double blue);
//! Called by newly connected client to cause airportsInRangeUpdated to be emitted. //! Called by newly connected client to cause airportsInRangeUpdated to be emitted.
void updateAirportsInRange(); void updateAirportsInRange();
//! Get full path to current aircraft model //! Get full path to current aircraft model
QString getAircraftModelPath() const; std::string getAircraftModelPath() const;
//! Get base filename of current aircraft model //! Get base filename of current aircraft model
QString getAircraftModelFilename() const; std::string getAircraftModelFilename() const;
//! Get canonical swift model string of current aircraft model //! Get canonical swift model string of current aircraft model
QString getAircraftModelString() const; std::string getAircraftModelString() const;
//! Get name of current aircraft model //! Get name of current aircraft model
QString getAircraftName() const; std::string getAircraftName() const;
//! Get path to current aircraft livery //! Get path to current aircraft livery
QString getAircraftLivery() const { return m_liveryPath.get().c_str(); } std::string getAircraftLivery() const { return m_liveryPath.get(); }
//! Get the ICAO code of the current aircraft model //! Get the ICAO code of the current aircraft model
QString getAircraftIcaoCode() const { return m_icao.get().c_str(); } std::string getAircraftIcaoCode() const { return m_icao.get(); }
//! Get the description of the current aircraft model //! Get the description of the current aircraft model
QString getAircraftDescription() const { return m_descrip.get().c_str(); } std::string getAircraftDescription() const { return m_descrip.get(); }
//! Get major version number //! Get major version number
int getXPlaneVersionMajor() const; int getXPlaneVersionMajor() const;
@@ -161,10 +161,10 @@ namespace XSwiftBus
int getXPlaneVersionMinor() const; int getXPlaneVersionMinor() const;
//! Get root of X-Plane install path //! Get root of X-Plane install path
QString getXPlaneInstallationPath() const; std::string getXPlaneInstallationPath() const;
//! Get full path to X-Plane preferences file //! Get full path to X-Plane preferences file
QString getXPlanePreferencesPath() const; std::string getXPlanePreferencesPath() const;
//! True if sim is paused //! True if sim is paused
bool isPaused() const { return m_paused.get(); } bool isPaused() const { return m_paused.get(); }
@@ -275,14 +275,14 @@ namespace XSwiftBus
int getNumberOfEngines() const { return m_numberOfEngines.get(); } int getNumberOfEngines() const { return m_numberOfEngines.get(); }
//! Get the N1 speed as percent of max (per engine) //! Get the N1 speed as percent of max (per engine)
QList<double> getEngineN1Percentage() const std::vector<double> getEngineN1Percentage() const
{ {
QList<double> list; std::vector<double> list;
const int number = getNumberOfEngines(); const auto number = static_cast<unsigned int>(getNumberOfEngines());
list.reserve(number); list.reserve(number);
for (int engineNumber = 0; engineNumber < number; ++engineNumber) for (unsigned int engineNumber = 0; engineNumber < number; ++engineNumber)
{ {
list.append(m_enginesN1Percentage.getAt(engineNumber)); list.push_back(m_enginesN1Percentage.getAt(engineNumber));
} }
return list; return list;
} }
@@ -299,21 +299,20 @@ namespace XSwiftBus
DBusHandlerResult dbusMessageHandler(const CDBusMessage &message) override; DBusHandlerResult dbusMessageHandler(const CDBusMessage &message) override;
private: private:
void emitAircraftModelChanged(const QString &path, const QString &filename, const QString &livery, void emitAircraftModelChanged(const std::string &path, const std::string &filename, const std::string &livery,
const QString &icao, const QString &modelString, const QString &name, const std::string &icao, const std::string &modelString, const std::string &name,
const QString &description); const std::string &description);
void emitAirportsInRangeUpdated(const std::vector<std::string> &icaoCodes, const std::vector<std::string> &names, void emitAirportsInRangeUpdated(const std::vector<std::string> &icaoCodes, const std::vector<std::string> &names,
const std::vector<double> &lats, const std::vector<double> &lons, const std::vector<double> &alts); const std::vector<double> &lats, const std::vector<double> &lons, const std::vector<double> &alts);
CMessageBoxControl m_messages { 128, 128, 16 }; CMessageBoxControl m_messages { 128, 128, 16 };
std::vector<CNavDataReference> m_airports; std::vector<CNavDataReference> m_airports;
QTimer *m_airportUpdater = nullptr;
void readAirportsDatabase(); void readAirportsDatabase();
std::vector<CNavDataReference> findClosestAirports(int number, double latitude, double longitude); std::vector<CNavDataReference> findClosestAirports(int number, double latitude, double longitude);
static CAircraftModel extractAcfProperties(const QString &filePath, const QFileInfo &fileInfo); static CAircraftModel extractAcfProperties(const std::string &filePath);
StringDataRef<xplane::data::sim::aircraft::view::acf_livery_path> m_liveryPath; StringDataRef<xplane::data::sim::aircraft::view::acf_livery_path> m_liveryPath;
StringDataRef<xplane::data::sim::aircraft::view::acf_ICAO> m_icao; StringDataRef<xplane::data::sim::aircraft::view::acf_ICAO> m_icao;

View File

@@ -18,18 +18,17 @@
#include "XPMPPlaneRenderer.h" #include "XPMPPlaneRenderer.h"
#include <XPLM/XPLMProcessing.h> #include <XPLM/XPLMProcessing.h>
#include <XPLM/XPLMUtilities.h> #include <XPLM/XPLMUtilities.h>
#include <QDateTime>
#include <QDebug>
#include <QStringList>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <cmath> #include <cmath>
#include <ctime>
#include <algorithm>
// clazy:excludeall=reserve-candidates // clazy:excludeall=reserve-candidates
namespace XSwiftBus namespace XSwiftBus
{ {
CTraffic::Plane::Plane(void *id_, QString callsign_, QString aircraftIcao_, QString airlineIcao_, QString livery_, QString modelName_) CTraffic::Plane::Plane(void *id_, const std::string &callsign_, const std::string &aircraftIcao_, const std::string &airlineIcao_, const std::string &livery_, const std::string &modelName_)
: id(id_), callsign(callsign_), aircraftIcao(aircraftIcao_), airlineIcao(airlineIcao_), livery(livery_), modelName(modelName_) : id(id_), callsign(callsign_), aircraftIcao(aircraftIcao_), airlineIcao(airlineIcao_), livery(livery_), modelName(modelName_)
{ {
std::memset(static_cast<void *>(&surfaces), 0, sizeof(surfaces)); std::memset(static_cast<void *>(&surfaces), 0, sizeof(surfaces));
@@ -38,8 +37,9 @@ namespace XSwiftBus
surfaces.size = sizeof(surfaces); surfaces.size = sizeof(surfaces);
xpdr.size = sizeof(xpdr); xpdr.size = sizeof(xpdr);
std::strncpy(label, qPrintable(callsign), sizeof(label)); std::strncpy(label, callsign.c_str(), sizeof(label));
surfaces.lights.timeOffset = static_cast<quint16>(qrand() % 0xffff); std::srand(static_cast<unsigned int>(std::time(nullptr)));
surfaces.lights.timeOffset = static_cast<uint16_t>(std::rand() % 0xffff);
} }
CTraffic::CTraffic(CDBusConnection *dbusConnection) : CTraffic::CTraffic(CDBusConnection *dbusConnection) :
@@ -60,8 +60,12 @@ namespace XSwiftBus
initXPlanePath(); initXPlanePath();
auto dir = g_xplanePath + "Resources" + g_sep + "plugins" + g_sep + "xswiftbus" + g_sep + "LegacyData" + g_sep; auto dir = g_xplanePath + "Resources" + g_sep + "plugins" + g_sep + "xswiftbus" + g_sep + "LegacyData" + g_sep;
auto err = XPMPMultiplayerInitLegacyData(qPrintable(dir + "CSL"), qPrintable(dir + "related.txt"), std::string csl = dir + "CSL";
qPrintable(dir + "lights.png"), qPrintable(dir + "Doc8643.txt"), "C172", preferences, preferences); std::string related = dir + "related.txt";
std::string doc8643 = dir + "Doc8643.txt";
std::string lights = dir + "lights.png";
auto err = XPMPMultiplayerInitLegacyData(csl.c_str(), related.c_str(), lights.c_str(), doc8643.c_str(),
"C172", preferences, preferences);
if (*err) { s_legacyDataOK = false; } if (*err) { s_legacyDataOK = false; }
} }
@@ -70,7 +74,7 @@ namespace XSwiftBus
if (! s_legacyDataOK) { return false; } if (! s_legacyDataOK) { return false; }
auto dir = g_xplanePath + "Resources" + g_sep + "plugins" + g_sep + "xswiftbus" + g_sep; auto dir = g_xplanePath + "Resources" + g_sep + "plugins" + g_sep + "xswiftbus" + g_sep;
auto err = XPMPMultiplayerInit(preferences, preferences, qPrintable(dir)); auto err = XPMPMultiplayerInit(preferences, preferences, dir.c_str());
if (*err) { cleanup(); return false; } if (*err) { cleanup(); return false; }
m_initialized = true; m_initialized = true;
@@ -104,11 +108,11 @@ namespace XSwiftBus
sendDBusSignal("simFrame"); sendDBusSignal("simFrame");
} }
void CTraffic::emitRemoteAircraftData(const QString &callsign, double latitude, double longitude, double elevation, double modelVerticalOffset) void CTraffic::emitRemoteAircraftData(const std::string &callsign, double latitude, double longitude, double elevation, double modelVerticalOffset)
{ {
CDBusMessage signalRemoteAircraftData = CDBusMessage::createSignal(XSWIFTBUS_TRAFFIC_OBJECTPATH, XSWIFTBUS_TRAFFIC_INTERFACENAME, "remoteAircraftData"); CDBusMessage signalRemoteAircraftData = CDBusMessage::createSignal(XSWIFTBUS_TRAFFIC_OBJECTPATH, XSWIFTBUS_TRAFFIC_INTERFACENAME, "remoteAircraftData");
signalRemoteAircraftData.beginArgumentWrite(); signalRemoteAircraftData.beginArgumentWrite();
signalRemoteAircraftData.appendArgument(callsign.toStdString()); signalRemoteAircraftData.appendArgument(callsign);
signalRemoteAircraftData.appendArgument(latitude); signalRemoteAircraftData.appendArgument(latitude);
signalRemoteAircraftData.appendArgument(longitude); signalRemoteAircraftData.appendArgument(longitude);
signalRemoteAircraftData.appendArgument(elevation); signalRemoteAircraftData.appendArgument(elevation);
@@ -141,19 +145,21 @@ namespace XSwiftBus
return def; return def;
} }
bool CTraffic::loadPlanesPackage(const QString &path) bool CTraffic::loadPlanesPackage(const std::string &path)
{ {
initXPlanePath(); initXPlanePath();
auto dir = g_xplanePath + "Resources" + g_sep + "plugins" + g_sep + "xswiftbus" + g_sep + "LegacyData" + g_sep; auto dir = g_xplanePath + "Resources" + g_sep + "plugins" + g_sep + "xswiftbus" + g_sep + "LegacyData" + g_sep;
auto err = XPMPLoadCSLPackage(qPrintable(path), qPrintable(dir + "related.txt"), qPrintable(dir + "Doc8643.txt")); std::string related = dir + "related.txt";
std::string doc8643 = dir + "Doc8643.txt";
auto err = XPMPLoadCSLPackage(path.c_str(), related.c_str(), doc8643.c_str());
if (*err) { return false; } if (*err) { return false; }
return true; return true;
} }
void CTraffic::setDefaultIcao(const QString &defaultIcao) void CTraffic::setDefaultIcao(const std::string &defaultIcao)
{ {
XPMPSetDefaultPlaneICAO(qPrintable(defaultIcao)); XPMPSetDefaultPlaneICAO(defaultIcao.c_str());
} }
void CTraffic::setDrawingLabels(bool drawing) void CTraffic::setDrawingLabels(bool drawing)
@@ -183,16 +189,16 @@ namespace XSwiftBus
g_drawDistance = static_cast<float>(nauticalMiles); g_drawDistance = static_cast<float>(nauticalMiles);
} }
void CTraffic::addPlane(const QString &callsign, const QString &modelName, const QString &aircraftIcao, const QString &airlineIcao, const QString &livery) void CTraffic::addPlane(const std::string &callsign, const std::string &modelName, const std::string &aircraftIcao, const std::string &airlineIcao, const std::string &livery)
{ {
XPMPPlaneID id = nullptr; XPMPPlaneID id = nullptr;
if (modelName.isEmpty()) if (modelName.empty())
{ {
id = XPMPCreatePlane(qPrintable(aircraftIcao), qPrintable(airlineIcao), qPrintable(livery), getPlaneData, static_cast<void *>(this)); id = XPMPCreatePlane(aircraftIcao.c_str(), airlineIcao.c_str(), livery.c_str(), getPlaneData, static_cast<void *>(this));
} }
else else
{ {
id = XPMPCreatePlaneWithModelName(qPrintable(modelName), qPrintable(aircraftIcao), qPrintable(airlineIcao), qPrintable(livery), getPlaneData, static_cast<void *>(this)); id = XPMPCreatePlaneWithModelName(modelName.c_str(), aircraftIcao.c_str(), airlineIcao.c_str(), livery.c_str(), getPlaneData, static_cast<void *>(this));
} }
if (id) if (id)
@@ -203,21 +209,23 @@ namespace XSwiftBus
} }
} }
void CTraffic::removePlane(const QString &callsign) void CTraffic::removePlane(const std::string &callsign)
{ {
Plane *plane = m_planesByCallsign.value(callsign, nullptr); auto planeIt = m_planesByCallsign.find(callsign);
if (!plane) { return; } if (planeIt == m_planesByCallsign.end()) { return; }
m_planesByCallsign.remove(callsign);
m_planesById.remove(plane->id); Plane *plane = planeIt->second;
m_planesByCallsign.erase(callsign);
m_planesById.erase(plane->id);
XPMPDestroyPlane(plane->id); XPMPDestroyPlane(plane->id);
delete plane; delete plane;
} }
void CTraffic::removeAllPlanes() void CTraffic::removeAllPlanes()
{ {
const QList<Plane *> planes = m_planesByCallsign.values(); for (const auto &kv : m_planesByCallsign)
for (Plane *plane : planes)
{ {
Plane *plane = kv.second;
assert(plane); assert(plane);
XPMPDestroyPlane(plane->id); XPMPDestroyPlane(plane->id);
delete plane; delete plane;
@@ -226,9 +234,12 @@ namespace XSwiftBus
m_planesById.clear(); m_planesById.clear();
} }
void CTraffic::setPlanePosition(const QString &callsign, double latitude, double longitude, double altitude, double pitch, double roll, double heading) void CTraffic::setPlanePosition(const std::string &callsign, double latitude, double longitude, double altitude, double pitch, double roll, double heading)
{ {
Plane *plane = m_planesByCallsign.value(callsign, nullptr); auto planeIt = m_planesByCallsign.find(callsign);
if (planeIt == m_planesByCallsign.end()) { return; }
Plane *plane = planeIt->second;
if (!plane) { return; } if (!plane) { return; }
plane->position.lat = latitude; plane->position.lat = latitude;
plane->position.lon = longitude; plane->position.lon = longitude;
@@ -238,11 +249,14 @@ namespace XSwiftBus
plane->position.heading = static_cast<float>(heading); plane->position.heading = static_cast<float>(heading);
} }
void CTraffic::setPlaneSurfaces(const QString &callsign, double gear, double flap, double spoiler, double speedBrake, double slat, double wingSweep, double thrust, void CTraffic::setPlaneSurfaces(const std::string &callsign, double gear, double flap, double spoiler, double speedBrake, double slat, double wingSweep, double thrust,
double elevator, double rudder, double aileron, bool landLight, bool beaconLight, bool strobeLight, bool navLight, int lightPattern, bool onGround) double elevator, double rudder, double aileron, bool landLight, bool beaconLight, bool strobeLight, bool navLight, int lightPattern, bool onGround)
{ {
Q_UNUSED(onGround); (void) onGround;
Plane *plane = m_planesByCallsign.value(callsign, nullptr); auto planeIt = m_planesByCallsign.find(callsign);
if (planeIt == m_planesByCallsign.end()) { return; }
Plane *plane = planeIt->second;
if (!plane) { return; } if (!plane) { return; }
plane->hasSurfaces = true; plane->hasSurfaces = true;
@@ -263,9 +277,12 @@ namespace XSwiftBus
plane->surfaces.lights.flashPattern = lightPattern; plane->surfaces.lights.flashPattern = lightPattern;
} }
void CTraffic::setPlaneTransponder(const QString &callsign, int code, bool modeC, bool ident) void CTraffic::setPlaneTransponder(const std::string &callsign, int code, bool modeC, bool ident)
{ {
Plane *plane = m_planesByCallsign.value(callsign, nullptr); auto planeIt = m_planesByCallsign.find(callsign);
if (planeIt == m_planesByCallsign.end()) { return; }
Plane *plane = planeIt->second;
if (!plane) { return; } if (!plane) { return; }
plane->hasXpdr = true; plane->hasXpdr = true;
plane->xpdr.code = code; plane->xpdr.code = code;
@@ -277,9 +294,9 @@ namespace XSwiftBus
void CTraffic::requestRemoteAircraftData() void CTraffic::requestRemoteAircraftData()
{ {
if (m_planesByCallsign.empty()) { return; } if (m_planesByCallsign.empty()) { return; }
const QList<Plane *> planes = m_planesByCallsign.values(); for (const auto &kv : m_planesByCallsign)
for (const Plane *plane : planes)
{ {
Plane *plane = kv.second;
assert(plane); assert(plane);
double lat = plane->position.lat; double lat = plane->position.lat;
double lon = plane->position.lon; double lon = plane->position.lon;
@@ -287,7 +304,7 @@ namespace XSwiftBus
double groundElevation = plane->terrainProbe.getElevation(lat, lon, elevation); double groundElevation = plane->terrainProbe.getElevation(lat, lon, elevation);
if (std::isnan(groundElevation)) { groundElevation = 0.0; } if (std::isnan(groundElevation)) { groundElevation = 0.0; }
double fudgeFactor = 3.0; double fudgeFactor = 3.0;
actualVertOffsetInfo(qPrintable(plane->modelName), nullptr, &fudgeFactor); actualVertOffsetInfo(plane->modelName.c_str(), nullptr, &fudgeFactor);
emitRemoteAircraftData(plane->callsign, lat, lon, groundElevation, fudgeFactor); emitRemoteAircraftData(plane->callsign, lat, lon, groundElevation, fudgeFactor);
} }
} }
@@ -332,7 +349,7 @@ namespace XSwiftBus
message.getArgument(path); message.getArgument(path);
queueDBusCall([ = ]() queueDBusCall([ = ]()
{ {
sendDBusReply(sender, serial, loadPlanesPackage(QString::fromStdString(path))); sendDBusReply(sender, serial, loadPlanesPackage(path));
}); });
} }
else if (message.getMethodName() == "setDefaultIcao") else if (message.getMethodName() == "setDefaultIcao")
@@ -342,7 +359,7 @@ namespace XSwiftBus
message.getArgument(defaultIcao); message.getArgument(defaultIcao);
queueDBusCall([ = ]() queueDBusCall([ = ]()
{ {
setDefaultIcao(QString::fromStdString(defaultIcao)); setDefaultIcao(defaultIcao);
}); });
} }
else if (message.getMethodName() == "setDrawingLabels") else if (message.getMethodName() == "setDrawingLabels")
@@ -404,7 +421,7 @@ namespace XSwiftBus
queueDBusCall([ = ]() queueDBusCall([ = ]()
{ {
addPlane(QString::fromStdString(callsign), QString::fromStdString(modelName), QString::fromStdString(aircraftIcao), QString::fromStdString(airlineIcao), QString::fromStdString(livery)); addPlane(callsign, modelName, aircraftIcao, airlineIcao, livery);
}); });
} }
else if (message.getMethodName() == "removePlane") else if (message.getMethodName() == "removePlane")
@@ -415,7 +432,7 @@ namespace XSwiftBus
message.getArgument(callsign); message.getArgument(callsign);
queueDBusCall([ = ]() queueDBusCall([ = ]()
{ {
removePlane(QString::fromStdString(callsign)); removePlane(callsign);
}); });
} }
else if (message.getMethodName() == "removeAllPlanes") else if (message.getMethodName() == "removeAllPlanes")
@@ -446,7 +463,7 @@ namespace XSwiftBus
message.getArgument(heading); message.getArgument(heading);
queueDBusCall([ = ]() queueDBusCall([ = ]()
{ {
setPlanePosition(QString::fromStdString(callsign), latitude, longitude, altitude, pitch, roll, heading); setPlanePosition(callsign, latitude, longitude, altitude, pitch, roll, heading);
}); });
} }
else if (message.getMethodName() == "setPlaneSurfaces") else if (message.getMethodName() == "setPlaneSurfaces")
@@ -489,7 +506,7 @@ namespace XSwiftBus
message.getArgument(onGround); message.getArgument(onGround);
queueDBusCall([ = ]() queueDBusCall([ = ]()
{ {
setPlaneSurfaces(QString::fromStdString(callsign), gear, flap, spoiler, speedBrake, slat, wingSweep, thrust, elevator, setPlaneSurfaces(callsign, gear, flap, spoiler, speedBrake, slat, wingSweep, thrust, elevator,
rudder, aileron, landLight, beaconLight, strobeLight, navLight, lightPattern, rudder, aileron, landLight, beaconLight, strobeLight, navLight, lightPattern,
onGround); onGround);
}); });
@@ -508,7 +525,7 @@ namespace XSwiftBus
message.getArgument(ident); message.getArgument(ident);
queueDBusCall([ = ]() queueDBusCall([ = ]()
{ {
setPlaneTransponder(QString::fromStdString(callsign), code, modeC, ident); setPlaneTransponder(callsign, code, modeC, ident);
}); });
} }
else if (message.getMethodName() == "requestRemoteAircraftData") else if (message.getMethodName() == "requestRemoteAircraftData")
@@ -546,8 +563,9 @@ namespace XSwiftBus
int CTraffic::getPlaneData(void *id, int dataType, void *io_data) int CTraffic::getPlaneData(void *id, int dataType, void *io_data)
{ {
QHash<void *, Plane *> planesById = m_planesById; auto planeIt = m_planesById.find(id);
Plane *plane = m_planesById.value(id, nullptr); assert(planeIt != m_planesById.end());
Plane *plane = planeIt->second;
if (!plane) { return xpmpData_Unavailable; } if (!plane) { return xpmpData_Unavailable; }
switch (dataType) switch (dataType)
@@ -568,18 +586,20 @@ namespace XSwiftBus
case xpmpDataType_Surfaces: case xpmpDataType_Surfaces:
if (plane->hasSurfaces) if (plane->hasSurfaces)
{ {
const auto currentTime = QDateTime::currentMSecsSinceEpoch(); const auto now = std::chrono::system_clock::now();
if (plane->surfaces.gearPosition != plane->targetGearPosition) if (plane->surfaces.gearPosition != plane->targetGearPosition)
{ {
// interpolate gear position // interpolate gear position
constexpr float gearMoveTimeMs = 5000; constexpr float gearMoveTimeMs = 5000;
const auto gearPositionDiffRemaining = plane->targetGearPosition - plane->surfaces.gearPosition; const auto gearPositionDiffRemaining = plane->targetGearPosition - plane->surfaces.gearPosition;
const auto gearPositionDiffThisFrame = (currentTime - plane->prevSurfacesLerpTime) / gearMoveTimeMs;
auto diffMs = std::chrono::duration_cast<std::chrono::milliseconds>(now - plane->prevSurfacesLerpTime);
const auto gearPositionDiffThisFrame = (diffMs.count()) / gearMoveTimeMs;
plane->surfaces.gearPosition += std::copysign(gearPositionDiffThisFrame, gearPositionDiffRemaining); plane->surfaces.gearPosition += std::copysign(gearPositionDiffThisFrame, gearPositionDiffRemaining);
plane->surfaces.gearPosition = qBound(0.0f, plane->surfaces.gearPosition, 1.0f); plane->surfaces.gearPosition = std::max(0.0f, std::min(plane->surfaces.gearPosition, 1.0f));
} }
plane->prevSurfacesLerpTime = currentTime; plane->prevSurfacesLerpTime = now;
const auto io_surfaces = static_cast<XPMPPlaneSurfaces_t *>(io_data); const auto io_surfaces = static_cast<XPMPPlaneSurfaces_t *>(io_data);
if (memcmpPayload(io_surfaces, &plane->surfaces)) if (memcmpPayload(io_surfaces, &plane->surfaces))

View File

@@ -15,11 +15,6 @@
#include "dbusobject.h" #include "dbusobject.h"
#include "datarefs.h" #include "datarefs.h"
#include "terrainprobe.h" #include "terrainprobe.h"
#include <QDateTime>
#include <QObject>
#include <QHash>
#include <QVector>
#include <QStringList>
#include "XPMPMultiplayer.h" #include "XPMPMultiplayer.h"
#include <XPLM/XPLMDisplay.h> #include <XPLM/XPLMDisplay.h>
#include <functional> #include <functional>
@@ -42,19 +37,19 @@ namespace XSwiftBus
CTraffic(CDBusConnection *dbusConnection); CTraffic(CDBusConnection *dbusConnection);
//! Destructor //! Destructor
virtual ~CTraffic(); ~CTraffic() override;
//! DBus interface name //! DBus interface name
static const QString &InterfaceName() static const std::string &InterfaceName()
{ {
static QString s(XSWIFTBUS_TRAFFIC_INTERFACENAME); static std::string s(XSWIFTBUS_TRAFFIC_INTERFACENAME);
return s; return s;
} }
//! DBus object path //! DBus object path
static const QString &ObjectPath() static const std::string &ObjectPath()
{ {
static QString s(XSWIFTBUS_TRAFFIC_OBJECTPATH); static std::string s(XSWIFTBUS_TRAFFIC_OBJECTPATH);
return s; return s;
} }
@@ -68,10 +63,10 @@ namespace XSwiftBus
void cleanup(); void cleanup();
//! Load a collection of planes from the given directory and return true if successful //! Load a collection of planes from the given directory and return true if successful
bool loadPlanesPackage(const QString &path); bool loadPlanesPackage(const std::string &path);
//! Set the ICAO code to use for aircraft without a model match //! Set the ICAO code to use for aircraft without a model match
void setDefaultIcao(const QString &defaultIcao); void setDefaultIcao(const std::string &defaultIcao);
//! Set whether the plugin draws type and callsign labels above aircraft //! Set whether the plugin draws type and callsign labels above aircraft
void setDrawingLabels(bool drawing); void setDrawingLabels(bool drawing);
@@ -86,23 +81,23 @@ namespace XSwiftBus
void setMaxDrawDistance(double nauticalMiles); void setMaxDrawDistance(double nauticalMiles);
//! Introduce a new traffic aircraft //! Introduce a new traffic aircraft
void addPlane(const QString &callsign, const QString &modelName, const QString &aircraftIcao, const QString &airlineIcao, const QString &livery); void addPlane(const std::string &callsign, const std::string &modelName, const std::string &aircraftIcao, const std::string &airlineIcao, const std::string &livery);
//! Remove a traffic aircraft //! Remove a traffic aircraft
void removePlane(const QString &callsign); void removePlane(const std::string &callsign);
//! Remove all traffic aircraft //! Remove all traffic aircraft
void removeAllPlanes(); void removeAllPlanes();
//! Set the position of a traffic aircraft //! Set the position of a traffic aircraft
void setPlanePosition(const QString &callsign, double latitude, double longitude, double altitude, double pitch, double roll, double heading); void setPlanePosition(const std::string &callsign, double latitude, double longitude, double altitude, double pitch, double roll, double heading);
//! Set the flight control surfaces and lights of a traffic aircraft //! Set the flight control surfaces and lights of a traffic aircraft
void setPlaneSurfaces(const QString &callsign, double gear, double flap, double spoiler, double speedBrake, double slat, double wingSweep, double thrust, void setPlaneSurfaces(const std::string &callsign, double gear, double flap, double spoiler, double speedBrake, double slat, double wingSweep, double thrust,
double elevator, double rudder, double aileron, bool landLight, bool beaconLight, bool strobeLight, bool navLight, int lightPattern, bool onGround); double elevator, double rudder, double aileron, bool landLight, bool beaconLight, bool strobeLight, bool navLight, int lightPattern, bool onGround);
//! Set the transponder of a traffic aircraft //! Set the transponder of a traffic aircraft
void setPlaneTransponder(const QString &callsign, int code, bool modeC, bool ident); void setPlaneTransponder(const std::string &callsign, int code, bool modeC, bool ident);
//! Request traffic plane data. A signal remoteAircraftData will be emitted for each known plane //! Request traffic plane data. A signal remoteAircraftData will be emitted for each known plane
void requestRemoteAircraftData(); void requestRemoteAircraftData();
@@ -117,7 +112,7 @@ namespace XSwiftBus
bool m_enabled = false; bool m_enabled = false;
void emitSimFrame(); void emitSimFrame();
void emitRemoteAircraftData(const QString &callsign, double latitude, double longitude, double elevation, double modelVerticalOffset); void emitRemoteAircraftData(const std::string &callsign, double latitude, double longitude, double elevation, double modelVerticalOffset);
static int preferences(const char *section, const char *name, int def); static int preferences(const char *section, const char *name, int def);
static float preferences(const char *section, const char *name, float def); static float preferences(const char *section, const char *name, float def);
@@ -125,26 +120,27 @@ namespace XSwiftBus
struct Plane struct Plane
{ {
void *id = nullptr; void *id = nullptr;
QString callsign; std::string callsign;
QString aircraftIcao; std::string aircraftIcao;
QString airlineIcao; std::string airlineIcao;
QString livery; std::string livery;
QString modelName; std::string modelName;
bool hasSurfaces = false; bool hasSurfaces = false;
bool hasXpdr = false; bool hasXpdr = false;
char label[32] {}; char label[32] {};
CTerrainProbe terrainProbe; CTerrainProbe terrainProbe;
XPMPPlaneSurfaces_t surfaces; XPMPPlaneSurfaces_t surfaces;
float targetGearPosition = 0; float targetGearPosition = 0;
qint64 prevSurfacesLerpTime = 0; std::chrono::system_clock::time_point prevSurfacesLerpTime;
XPMPPlaneRadar_t xpdr; XPMPPlaneRadar_t xpdr;
XPMPPlanePosition_t position; XPMPPlanePosition_t position;
Plane(void *id_, QString callsign_, QString aircraftIcao_, QString airlineIcao_, QString livery_, QString modelName_); Plane(void *id_, const std::string &callsign_, const std::string &aircraftIcao_, const std::string &airlineIcao_,
const std::string &livery_, const std::string &modelName_);
}; };
QHash<QString, Plane *> m_planesByCallsign; std::unordered_map<std::string, Plane *> m_planesByCallsign;
QHash<void *, Plane *> m_planesById; std::unordered_map<void *, Plane *> m_planesById;
qint64 m_timestampLastSimFrame = QDateTime::currentMSecsSinceEpoch(); std::chrono::system_clock::time_point m_timestampLastSimFrame = std::chrono::system_clock::now();
int getPlaneData(void *id, int dataType, void *io_data); int getPlaneData(void *id, int dataType, void *io_data);
static int getPlaneData(void *id, int dataType, void *io_data, void *self) static int getPlaneData(void *id, int dataType, void *io_data, void *self)

View File

@@ -15,19 +15,19 @@
#include "utils.h" #include "utils.h"
#include <XPMPMultiplayerCSL.h> #include <XPMPMultiplayerCSL.h>
#include <QString> #include <string>
#include <QtGlobal> #include <sstream>
namespace XSwiftBus namespace XSwiftBus
{ {
QString g_xplanePath; std::string g_xplanePath;
QString g_sep; std::string g_sep;
//! Init global xplane path //! Init global xplane path
void initXPlanePath() void initXPlanePath()
{ {
if (!g_xplanePath.isEmpty() && !g_sep.isEmpty()) {} if (!g_xplanePath.empty() && !g_sep.empty()) {}
char xplanePath[512]; char xplanePath[512];
XPLMGetSystemPath(xplanePath); XPLMGetSystemPath(xplanePath);
@@ -43,6 +43,116 @@ namespace XSwiftBus
g_xplanePath = xplanePath; g_xplanePath = xplanePath;
} }
std::string getDirName(const string &filePath)
{
std::string seperator = "/\\";
std::size_t sepPos = filePath.find_last_of(seperator);
if(sepPos != std::string::npos)
{
return filePath.substr(0, sepPos);
}
else
{
return {};
}
}
std::string getFileName(const std::string &filePath)
{
std::string seperator = "/\\";
std::size_t sepPos = filePath.find_last_of(seperator);
if(sepPos != std::string::npos)
{
return filePath.substr(sepPos + 1, filePath.size() - 1);
}
else
{
return filePath;
}
}
std::string getBaseName(const std::string &filePath)
{
std::string seperator = ".";
std::string fileName = getFileName(filePath);
std::size_t sepPos = fileName.find(seperator);
if(sepPos != std::string::npos)
{
return fileName.substr(0, sepPos);
}
else
{
return fileName;
}
}
std::vector<std::string> split(const std::string &str, size_t maxSplitCount)
{
std::string s(str);
std::string delimiter = " ";
size_t pos = 0;
std::vector<std::string> tokens;
while ((pos = s.find(delimiter)) != std::string::npos)
{
tokens.push_back(s.substr(0, pos));
s.erase(0, pos + delimiter.length());
if (tokens.size() == maxSplitCount) { break; }
}
tokens.push_back(s);
return tokens;
}
void Logger::print(const std::string &filePath, int line, MsgType type, const std::string &message)
{
(void) line;
(void) type;
assert(!filePath.empty());
std::ostringstream ss;
ss << "xswiftbus";
ss << ' ';
#if defined(XSWIFTBUS_ENABLE_TRACE_LOG)
switch (type)
{
case DebugMsg:
ss << "Debug";
break;
case InfoMsg:
ss << "Info";
break;
case WarningMsg:
ss << "Warning";
break;
case FatalMsg:
ss << "Fatal";
}
ss << ' ';
std::string seperator = "/\\";
std::size_t sepPos = filePath.find_last_of(seperator);
if(sepPos != std::string::npos)
{
ss << filePath.substr(sepPos + 1, filePath.size() - 1);
}
else
{
ss << filePath;
}
ss << ' ';
ss << line;
ss << " : ";
#endif
ss << message;
ss << "\n";
std::string buffer = ss.str();
XPLMDebugString(buffer.c_str());
}
} }
//! \endcond //! \endcond

View File

@@ -14,12 +14,12 @@
#include <XPLM/XPLMPlugin.h> #include <XPLM/XPLMPlugin.h>
#include <XPLM/XPLMProcessing.h> #include <XPLM/XPLMProcessing.h>
#include <XPLM/XPLMUtilities.h> #include <XPLM/XPLMUtilities.h>
#include <QCoreApplication> #include <vector>
#include <QSharedPointer>
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <clocale> #include <clocale>
#include <string>
/*! /*!
* \file * \file
@@ -28,58 +28,58 @@
/*! /*!
* Install a Qt message handler which outputs to the X-Plane debug log. * Install a Qt message handler which outputs to the X-Plane debug log.
*/ */
class QXPlaneMessageHandler //class QXPlaneMessageHandler
{ //{
static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg) // static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ // {
QByteArray localMsg = msg.toLocal8Bit(); // QByteArray localMsg = msg.toLocal8Bit();
QByteArray file(context.file); // QByteArray file(context.file);
if (file.isEmpty()) file = "<unknown>"; // if (file.isEmpty()) file = "<unknown>";
int line = context.line; // int line = context.line;
char *buffer = new char[64 + localMsg.size() + file.size()]; // char *buffer = new char[64 + localMsg.size() + file.size()];
switch (type) { // switch (type) {
case QtDebugMsg: // case QtDebugMsg:
std::sprintf(buffer, "%s:%d: Debug: %s\n", file.constData(), line, localMsg.constData()); // std::sprintf(buffer, "%s:%d: Debug: %s\n", file.constData(), line, localMsg.constData());
XPLMDebugString(buffer); // XPLMDebugString(buffer);
break; // break;
case QtInfoMsg: // case QtInfoMsg:
std::sprintf(buffer, "%s:%d: Info: %s\n", file.constData(), line, localMsg.constData()); // std::sprintf(buffer, "%s:%d: Info: %s\n", file.constData(), line, localMsg.constData());
XPLMDebugString(buffer); // XPLMDebugString(buffer);
break; // break;
case QtWarningMsg: // case QtWarningMsg:
std::sprintf(buffer, "%s:%d: Warning: %s\n", file.constData(), line, localMsg.constData()); // std::sprintf(buffer, "%s:%d: Warning: %s\n", file.constData(), line, localMsg.constData());
XPLMDebugString(buffer); // XPLMDebugString(buffer);
break; // break;
default: // default:
case QtCriticalMsg: // case QtCriticalMsg:
std::sprintf(buffer, "%s:%d: Error: %s\n", file.constData(), line, localMsg.constData()); // std::sprintf(buffer, "%s:%d: Error: %s\n", file.constData(), line, localMsg.constData());
XPLMDebugString(buffer); // XPLMDebugString(buffer);
break; // break;
case QtFatalMsg: // case QtFatalMsg:
std::sprintf(buffer, "%s:%d: Fatal: %s\n", file.constData(), line, localMsg.constData()); // std::sprintf(buffer, "%s:%d: Fatal: %s\n", file.constData(), line, localMsg.constData());
XPLMDebugString(buffer); // XPLMDebugString(buffer);
std::abort(); // std::abort();
} // }
delete[] buffer; // delete[] buffer;
} // }
public: //public:
/*! // /*!
* Install the handler. // * Install the handler.
*/ // */
static void install() // static void install()
{ // {
qInstallMessageHandler(handler); // qInstallMessageHandler(handler);
} // }
//! Not copyable. // //! Not copyable.
//! @{ // //! @{
QXPlaneMessageHandler(const QXPlaneMessageHandler &) = delete; // QXPlaneMessageHandler(const QXPlaneMessageHandler &) = delete;
QXPlaneMessageHandler &operator =(const QXPlaneMessageHandler &) = delete; // QXPlaneMessageHandler &operator =(const QXPlaneMessageHandler &) = delete;
//! @} // //! @}
}; //};
/*! /*!
* QApplication subclass used by XSwiftBus. * QApplication subclass used by XSwiftBus.
@@ -89,101 +89,134 @@ public:
* Qt framework, they can simply copy & paste this class into their project * Qt framework, they can simply copy & paste this class into their project
* and both X-Plane plugins will be able to share a single QApplication safely. * and both X-Plane plugins will be able to share a single QApplication safely.
*/ */
class QSharedApplication : public QCoreApplication //class QSharedApplication : public QCoreApplication
{ //{
Q_OBJECT // Q_OBJECT
QWeakPointer<QCoreApplication> m_weakptr; // QWeakPointer<QCoreApplication> m_weakptr;
QSharedApplication(QSharedPointer<QCoreApplication> &ptr, int &argc, char **argv) : QCoreApplication(argc, argv) // QSharedApplication(QSharedPointer<QCoreApplication> &ptr, int &argc, char **argv) : QCoreApplication(argc, argv)
{ // {
ptr.reset(this); // ptr.reset(this);
m_weakptr = ptr; // m_weakptr = ptr;
} // }
static char *strdup(const char *s) { auto s2 = static_cast<char *>(std::malloc(std::strlen(s) + 1)); return std::strcpy(s2, s); } // static char *strdup(const char *s) { auto s2 = static_cast<char *>(std::malloc(std::strlen(s) + 1)); return std::strcpy(s2, s); }
public: //public:
/*! // /*!
* Returns a shared pointer to the QApplication. // * Returns a shared pointer to the QApplication.
* // *
* The QApplication will not be destroyed while this shared pointer exists. // * The QApplication will not be destroyed while this shared pointer exists.
*/ // */
static QSharedPointer<QCoreApplication> sharedInstance() // static QSharedPointer<QCoreApplication> sharedInstance()
{ // {
QSharedPointer<QCoreApplication> ptr; // QSharedPointer<QCoreApplication> ptr;
if (! instance()) // if (! instance())
{ // {
static int argc = 1; // static int argc = 1;
static char *argv[] = { strdup("X-Plane") }; // static char *argv[] = { strdup("X-Plane") };
#ifdef Q_OS_UNIX //#ifdef Q_OS_UNIX
/* Workaround for #362 */ // /* Workaround for #362 */
char* xplocale = setlocale(LC_ALL, nullptr); // char* xplocale = setlocale(LC_ALL, nullptr);
#endif //#endif
new QSharedApplication(ptr, argc, argv); // new QSharedApplication(ptr, argc, argv);
#ifdef Q_OS_UNIX //#ifdef Q_OS_UNIX
setlocale(LC_ALL, xplocale); // setlocale(LC_ALL, xplocale);
#endif //#endif
} // }
if (! instance()->inherits("QSharedApplication")) // if (! instance()->inherits("QSharedApplication"))
{ // {
qFatal("There is an unshared QCoreApplication in another plugin"); // qFatal("There is an unshared QCoreApplication in another plugin");
} // }
return static_cast<QSharedApplication*>(instance())->m_weakptr; // return static_cast<QSharedApplication*>(instance())->m_weakptr;
} // }
}; //};
/*! ///*!
* Runs the Qt event loop inside the X-Plane event loop. // * Runs the Qt event loop inside the X-Plane event loop.
*/ // */
class QXPlaneEventLoop : public QObject //class QXPlaneEventLoop : public QObject
{ //{
Q_OBJECT // Q_OBJECT
QXPlaneEventLoop(QObject *parent) : QObject(parent) // QXPlaneEventLoop(QObject *parent) : QObject(parent)
{ // {
XPLMRegisterFlightLoopCallback(callback, -1, nullptr); // XPLMRegisterFlightLoopCallback(callback, -1, nullptr);
} // }
~QXPlaneEventLoop() // ~QXPlaneEventLoop()
{ // {
XPLMUnregisterFlightLoopCallback(callback, nullptr); // XPLMUnregisterFlightLoopCallback(callback, nullptr);
} // }
static float callback(float, float, int, void *) // static float callback(float, float, int, void *)
{ // {
QCoreApplication::processEvents(); // QCoreApplication::processEvents();
QCoreApplication::sendPostedEvents(); // QCoreApplication::sendPostedEvents();
return -1; // return -1;
} // }
public: //public:
/*! // /*!
* Registers the X-Plane callback which calls into the Qt event loop, // * Registers the X-Plane callback which calls into the Qt event loop,
* unless one was already registered. // * unless one was already registered.
*/ // */
static void exec() // static void exec()
{ // {
if (! QCoreApplication::instance()->findChild<QXPlaneEventLoop *>()) // if (! QCoreApplication::instance()->findChild<QXPlaneEventLoop *>())
{ // {
new QXPlaneEventLoop(QCoreApplication::instance()); // new QXPlaneEventLoop(QCoreApplication::instance());
} // }
} // }
}; //};
namespace XSwiftBus namespace XSwiftBus
{ {
//! Absolute xplane path //! Absolute xplane path
extern QString g_xplanePath; extern std::string g_xplanePath;
//! Platform specific dir separator //! Platform specific dir separator
extern QString g_sep; extern std::string g_sep;
//! Init global xplane path //! Init global xplane path
void initXPlanePath(); void initXPlanePath();
//! Returns the directory name of a given file path
std::string getDirName(const std::string &filePath);
//! Returns the filename (including extension) of a given file path
std::string getFileName(const std::string &filePath);
//! Returns the filename without extension of a given file path
std::string getBaseName(const std::string &filePath);
//! Splits the given string maximal maxSplitCount times and returns the tokens
//! The size of the returned vector is up to maxSplitCount + 1 or less
std::vector<std::string> split(const std::string &str, size_t maxSplitCount = 0);
//! Simple logger class.
//! Don't use it directly, but the _LOG macros instead
class Logger
{
public:
//! Message type
enum MsgType { DebugMsg, WarningMsg, FatalMsg, InfoMsg };
Logger() = delete;
//! Print message to X-Plane log
static void print(const std::string &filePath, int line, MsgType type, const std::string &message);
};
//! Logger convenience macros
//! @{
#define DEBUG_LOG(msg) Logger::print(__FILE__, __LINE__, Logger::DebugMsg, msg)
#define INFO_LOG(msg) Logger::print(__FILE__, __LINE__, Logger::InfoMsg, msg)
//! @}
} }
#endif // guard #endif // guard

View File

@@ -10,7 +10,7 @@
//! \cond PRIVATE //! \cond PRIVATE
#include "weather.h" #include "weather.h"
#include <QDebug> #include "utils.h"
namespace XSwiftBus namespace XSwiftBus
{ {
@@ -37,7 +37,7 @@ namespace XSwiftBus
case 0: setCloudLayerImpl(m_cloudLayer0, base, tops, type, coverage); break; case 0: setCloudLayerImpl(m_cloudLayer0, base, tops, type, coverage); break;
case 1: setCloudLayerImpl(m_cloudLayer1, base, tops, type, coverage); break; case 1: setCloudLayerImpl(m_cloudLayer1, base, tops, type, coverage); break;
case 2: setCloudLayerImpl(m_cloudLayer2, base, tops, type, coverage); break; case 2: setCloudLayerImpl(m_cloudLayer2, base, tops, type, coverage); break;
default: qDebug() << "Invalid cloud layer" << layer; break; default: DEBUG_LOG("Invalid cloud layer"); break;
} }
} }
@@ -60,7 +60,7 @@ namespace XSwiftBus
case 0: setWindLayerImpl(m_windLayer0, altitude, direction, speed, shearDirection, shearSpeed, turbulence); break; case 0: setWindLayerImpl(m_windLayer0, altitude, direction, speed, shearDirection, shearSpeed, turbulence); break;
case 1: setWindLayerImpl(m_windLayer1, altitude, direction, speed, shearDirection, shearSpeed, turbulence); break; case 1: setWindLayerImpl(m_windLayer1, altitude, direction, speed, shearDirection, shearSpeed, turbulence); break;
case 2: setWindLayerImpl(m_windLayer2, altitude, direction, speed, shearDirection, shearSpeed, turbulence); break; case 2: setWindLayerImpl(m_windLayer2, altitude, direction, speed, shearDirection, shearSpeed, turbulence); break;
default: qDebug() << "Invalid wind layer" << layer; break; default: DEBUG_LOG("Invalid wind layer"); break;
} }
} }

View File

@@ -1,10 +1,9 @@
load(common_pre) load(common_pre)
QT += core gui widgets dbus network
TEMPLATE = lib TEMPLATE = lib
CONFIG += shared plugin CONFIG += shared plugin
CONFIG -= qt
INCLUDEPATH += $$EXTERNALSROOT/common/include/XPLM INCLUDEPATH += $$EXTERNALSROOT/common/include/XPLM
@@ -107,7 +106,6 @@ INSTALLS += target
dep_target.path = $$PREFIX/$$XSWIFTBUS_DIR dep_target.path = $$PREFIX/$$XSWIFTBUS_DIR
win32 { win32 {
dep_target.files *= $$DestRoot/lib/blackmisc.dll
dep_target.files *= $$DestRoot/bin/dbus-daemon.exe dep_target.files *= $$DestRoot/bin/dbus-daemon.exe
win32-g++ { win32-g++ {
dep_target.files *= $$DestRoot/bin/libdbus-1-3.dll dep_target.files *= $$DestRoot/bin/libdbus-1-3.dll
@@ -118,12 +116,6 @@ win32 {
dep_target.files *= $$DestRoot/bin/expat.dll dep_target.files *= $$DestRoot/bin/expat.dll
dep_target.files *= $$DestRoot/bin/libevent_core.dll dep_target.files *= $$DestRoot/bin/libevent_core.dll
} }
dep_target.files *= $$[QT_INSTALL_BINS]/Qt5Core$${DLL_DEBUG_SUFFIX}.dll
dep_target.files *= $$[QT_INSTALL_BINS]/Qt5Gui$${DLL_DEBUG_SUFFIX}.dll
dep_target.files *= $$[QT_INSTALL_BINS]/Qt5Widgets$${DLL_DEBUG_SUFFIX}.dll
dep_target.files *= $$[QT_INSTALL_BINS]/Qt5DBus$${DLL_DEBUG_SUFFIX}.dll
dep_target.files *= $$[QT_INSTALL_BINS]/Qt5Network$${DLL_DEBUG_SUFFIX}.dll
dep_target.files *= $$[QT_INSTALL_BINS]/Qt5Xml$${DLL_DEBUG_SUFFIX}.dll
dep_target.CONFIG += no_check_exist dep_target.CONFIG += no_check_exist
dbus_share.path = $$PREFIX/$$XSWIFTBUS_DIR/share/dbus-1 dbus_share.path = $$PREFIX/$$XSWIFTBUS_DIR/share/dbus-1
@@ -135,24 +127,8 @@ win32 {
legacy_data_target.files *= LegacyData legacy_data_target.files *= LegacyData
} else:macx: { } else:macx: {
dep_target.files *= $$DestRoot/lib/libdbus-1.3.dylib dep_target.files *= $$DestRoot/lib/libdbus-1.3.dylib
dep_target.files *= $$DestRoot/lib/libevent_core.2.1.8.dylib
dep_target.extra += rsync -avzl --exclude \'Headers*\' --exclude \'*debug*\' $$[QT_INSTALL_LIBS]/QtCore.framework/ $${PREFIX}/$$XSWIFTBUS_DIR/QtCore.framework/ &&
dep_target.extra += rsync -avzl --exclude \'Headers*\' --exclude \'*debug*\' $$[QT_INSTALL_LIBS]/QtGui.framework/ $${PREFIX}/$$XSWIFTBUS_DIR/QtGui.framework/ &&
dep_target.extra += rsync -avzl --exclude \'Headers*\' --exclude \'*debug*\' $$[QT_INSTALL_LIBS]/QtWidgets.framework/ $${PREFIX}/$$XSWIFTBUS_DIR/QtWidgets.framework/ &&
dep_target.extra += rsync -avzl --exclude \'Headers*\' --exclude \'*debug*\' $$[QT_INSTALL_LIBS]/QtDBus.framework/ $${PREFIX}/$$XSWIFTBUS_DIR/QtDBus.framework/ &&
dep_target.extra += rsync -avzl --exclude \'Headers*\' --exclude \'*debug*\' $$[QT_INSTALL_LIBS]/QtNetwork.framework/ $${PREFIX}/$$XSWIFTBUS_DIR/QtNetwork.framework/ &&
dep_target.extra += rsync -avzl --exclude \'Headers*\' --exclude \'*debug*\' $$[QT_INSTALL_LIBS]/QtXml.framework/ $${PREFIX}/$$XSWIFTBUS_DIR/QtXml.framework/
dep_target.CONFIG += no_check_exist dep_target.CONFIG += no_check_exist
# Manually copy to workaround shortcomings introduced
# when qmake migrated away from GNU install in Qt 5.9
dep_target.depends += copy_blackmisc
copy_blackmisc.target = copy_blackmisc
source_path = $$PREFIX/lib/libblackmisc.0.dylib
dest_path = $$PREFIX/$$XSWIFTBUS_DIR
copy_blackmisc.commands = cp $$shell_path($$source_path) $$shell_path($$dest_path)
QMAKE_EXTRA_TARGETS += copy_blackmisc
legacy_data_target.path = $$PREFIX/xswiftbus legacy_data_target.path = $$PREFIX/xswiftbus
legacy_data_target.files *= LegacyData legacy_data_target.files *= LegacyData
@@ -160,48 +136,13 @@ win32 {
# We cannot modify the original library since this is xswiftbus specific. # We cannot modify the original library since this is xswiftbus specific.
legacy_data_target.depends += fix_plugin_rpath legacy_data_target.depends += fix_plugin_rpath
fix_plugin_rpath.target = fix_plugin_rpath fix_plugin_rpath.target = fix_plugin_rpath
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/libblackmisc.0.dylib\" \"@loader_path/libblackmisc.0.dylib\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) &&
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/QtWidgets.framework/Versions/5/QtWidgets\" \"@loader_path/QtWidgets.framework/Versions/5/QtWidgets\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) &&
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/QtGui.framework/Versions/5/QtGui\" \"@loader_path/QtGui.framework/Versions/5/QtGui\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) &&
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/QtDBus.framework/Versions/5/QtDBus\" \"@loader_path/QtDBus.framework/Versions/5/QtDBus\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) &&
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/QtNetwork.framework/Versions/5/QtNetwork\" \"@loader_path/QtNetwork.framework/Versions/5/QtNetwork\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) &&
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/QtCore.framework/Versions/5/QtCore\" \"@loader_path/QtCore.framework/Versions/5/QtCore\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) &&
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/QtXml.framework/Versions/5/QtXml\" \"@loader_path/QtXml.framework/Versions/5/QtXml\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/libblackmisc.0.dylib) &&
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/libevent_core.2.1.8.dylib\" \"@loader_path/libevent_core.2.1.8.dylib\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) && fix_plugin_rpath.commands += install_name_tool -change \"@rpath/libevent_core.2.1.8.dylib\" \"@loader_path/libevent_core.2.1.8.dylib\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) &&
fix_plugin_rpath.commands += install_name_tool -change \"@rpath/libdbus-1.3.dylib\" \"@loader_path/libdbus-1.3.dylib\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl) fix_plugin_rpath.commands += install_name_tool -change \"@rpath/libdbus-1.3.dylib\" \"@loader_path/libdbus-1.3.dylib\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/mac.xpl)
QMAKE_EXTRA_TARGETS += fix_plugin_rpath QMAKE_EXTRA_TARGETS += fix_plugin_rpath
fix_plugin_rpath.depends += fix_misc_rpath
fix_misc_rpath.target = fix_misc_rpath
fix_misc_rpath.commands += install_name_tool -id \"@loader_path/libblackmisc.0.dylib\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/libblackmisc.0.dylib) &&
fix_misc_rpath.commands += install_name_tool -change \"@rpath/QtGui.framework/Versions/5/QtGui\" \"@loader_path/QtGui.framework/Versions/5/QtGui\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/libblackmisc.0.dylib) &&
fix_misc_rpath.commands += install_name_tool -change \"@rpath/QtDBus.framework/Versions/5/QtDBus\" \"@loader_path/QtDBus.framework/Versions/5/QtDBus\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/libblackmisc.0.dylib) &&
fix_misc_rpath.commands += install_name_tool -change \"@rpath/QtNetwork.framework/Versions/5/QtNetwork\" \"@loader_path/QtNetwork.framework/Versions/5/QtNetwork\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/libblackmisc.0.dylib) &&
fix_misc_rpath.commands += install_name_tool -change \"@rpath/QtCore.framework/Versions/5/QtCore\" \"@loader_path/QtCore.framework/Versions/5/QtCore\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/libblackmisc.0.dylib) &&
fix_misc_rpath.commands += install_name_tool -change \"@rpath/QtXml.framework/Versions/5/QtXml\" \"@loader_path/QtXml.framework/Versions/5/QtXml\" $$shell_path($$PREFIX/$$XSWIFTBUS_DIR/libblackmisc.0.dylib)
QMAKE_EXTRA_TARGETS += fix_misc_rpath
} else:unix: { } else:unix: {
dep_target.files *= $$[QT_INSTALL_LIBS]/libQt5Core.so.5
dep_target.files *= $$[QT_INSTALL_LIBS]/libQt5Gui.so.5
dep_target.files *= $$[QT_INSTALL_LIBS]/libQt5Widgets.so.5
dep_target.files *= $$[QT_INSTALL_LIBS]/libQt5DBus.so.5
dep_target.files *= $$[QT_INSTALL_LIBS]/libQt5Network.so.5
dep_target.files *= $$[QT_INSTALL_LIBS]/libQt5Xml.so.5
dep_target.files *= $$[QT_INSTALL_LIBS]/libicui18n.so.56
dep_target.files *= $$[QT_INSTALL_LIBS]/libicuuc.so.56
dep_target.files *= $$[QT_INSTALL_LIBS]/libicudata.so.56
dep_target.CONFIG += no_check_exist dep_target.CONFIG += no_check_exist
# Manually copy to workaround shortcomings introduced
# when qmake migrated away from GNU install in Qt 5.9
dep_target.depends += copy_blackmisc
copy_blackmisc.target = copy_blackmisc
source_path = $$PREFIX/lib/libblackmisc.so.0
dest_path = $$PREFIX/$$XSWIFTBUS_DIR
copy_blackmisc.commands = cp $$shell_path($$source_path) $$shell_path($$dest_path)
QMAKE_EXTRA_TARGETS += copy_blackmisc
legacy_data_target.path = $$PREFIX/xswiftbus legacy_data_target.path = $$PREFIX/xswiftbus
legacy_data_target.files *= LegacyData legacy_data_target.files *= LegacyData
} }