6 #include <XPLM/XPLMPlanes.h>
7 #include <XPLM/XPLMUtilities.h>
20 using namespace swift::misc::simulation::xplane::qtfreeutils;
25 struct CService::FramePeriodSampler :
public CDrawable
27 DataRef<xplane::data::sim::operation::misc::frame_rate_period> m_thisFramePeriod;
28 DataRef<xplane::data::sim::time::framerate_period> m_thisFramePeriodXP11;
29 DataRef<xplane::data::sim::time::total_flight_time_sec> m_secondsSinceReset;
30 DataRef<xplane::data::sim::flightmodel::position::groundspeed> m_groundSpeed;
32 std::vector<float> m_samples;
34 float m_totalOverBudget = 0;
35 float m_totalMetersShort = 0;
36 float m_totalSecondsLate = 0;
37 size_t m_lastSampleIndex = 0;
38 static constexpr
size_t c_maxSampleCount = 500;
39 static constexpr
float c_framePeriodBudget = 0.05f;
41 FramePeriodSampler() : CDrawable(xplm_Phase_Window, true) {}
43 std::tuple<float, float, float, float> getFrameStats()
45 if (m_total < 0.001f) {
return {}; }
46 const float fps = m_samples.size() / m_total;
47 const float ratio = 1 - m_totalOverBudget / m_total;
48 const float miles = m_totalMetersShort / 1852.0f;
49 const float minutes = m_totalSecondsLate / 60.0f;
51 m_totalOverBudget = 0;
53 m_lastSampleIndex = 0;
54 return std::make_tuple(fps, ratio, miles, minutes);
58 virtual void draw() override
61 m_thisFramePeriodXP11.isValid() ? m_thisFramePeriodXP11.get() : m_thisFramePeriod.get();
63 ++m_lastSampleIndex %= c_maxSampleCount;
64 if (m_samples.size() == c_maxSampleCount)
66 auto &oldSample = m_samples[m_lastSampleIndex];
68 if (oldSample > c_framePeriodBudget) { m_totalOverBudget -= oldSample - c_framePeriodBudget; }
71 else { m_samples.push_back(current); }
74 if (current > c_framePeriodBudget)
76 m_totalOverBudget += current - c_framePeriodBudget;
78 if (m_secondsSinceReset.get() > 10)
80 const float metersShort = m_groundSpeed.get() * std::max(0.0f, current - c_framePeriodBudget);
81 m_totalMetersShort += metersShort;
82 if (m_groundSpeed.get() > 1.0f)
84 m_totalSecondsLate += std::max(0.0f, current - c_framePeriodBudget);
92 :
CDBusObject(settingsProvider), m_framePeriodSampler(std::make_unique<FramePeriodSampler>())
94 this->updateMessageBoxFromSettings();
95 m_framePeriodSampler->show();
96 m_swiftNetworkConnected.set(0);
97 m_swiftCallsign.set(
"");
107 XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
108 if (std::strlen(filename) < 1 || std::strlen(path) < 1)
110 WARNING_LOG(
"Aircraft changed, but NO path or file name");
126 if (!m_framePeriodSampler) {
return {}; }
127 const auto result = m_framePeriodSampler->getFrameStats();
128 return std::make_tuple(
static_cast<double>(std::get<0>(result)),
static_cast<double>(std::get<1>(result)),
129 static_cast<double>(std::get<2>(result)),
static_cast<double>(std::get<3>(result)));
134 if (m_framePeriodSampler)
136 m_framePeriodSampler->m_totalMetersShort = 0;
137 m_framePeriodSampler->m_totalSecondsLate = 0;
147 if (text.empty()) {
return; }
152 U8It
begin(text.begin(), text.end());
153 auto characters = std::distance(
begin, U8It(text.end(), text.end()));
154 std::vector<CMessage::string> wrappedLines;
156 for (; characters > lineLength; characters -= lineLength)
158 auto end = std::next(
begin, lineLength);
159 wrappedLines.emplace_back(
begin.base,
end.base);
160 wrappedLines.back() += ellipsis;
163 if (characters > 0) { wrappedLines.emplace_back(
begin.base, text.end()); }
164 for (
const auto &line : wrappedLines)
167 { line,
static_cast<float>(red),
static_cast<float>(green),
static_cast<float>(blue) });
170 if (!m_messages.
isVisible() && m_popupMessageWindow) { m_messages.
toggle(); }
172 if (m_disappearMessageWindow)
174 m_disappearMessageWindowTime = std::chrono::system_clock::now() +
175 std::chrono::milliseconds(std::max(m_disapperMessageWindowTimeMs, 1500));
183 XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
191 XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
199 XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
208 XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
215 std::string liveryPath = m_liveryPath.
get();
216 if (liveryPath.empty()) {
return {}; }
219 liveryPath.pop_back();
226 XPLMGetVersions(&version,
nullptr,
nullptr);
227 if (version > 5000) { version /= 10; }
228 return version / 100;
234 XPLMGetVersions(&version,
nullptr,
nullptr);
235 if (version > 5000) { version /= 10; }
236 return version % 100;
242 XPLMGetSystemPath(path);
249 XPLMGetPrefsPath(path);
263 this->updateMessageBoxFromSettings();
265 if (w) {
INFO_LOG(
"Written new config file"); }
268 static const char *introspection_service = DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
269 #include "org.swift_project.xswiftbus.service.xml"
275 const std::string sender = message.
getSender();
276 const dbus_uint32_t serial = message.
getSerial();
308 else if (message.
getMethodName() ==
"getOwnAircraftSituationData")
311 const double lat = m_latitude.
get();
312 const double lon = m_longitude.
get();
313 const double alt = m_elevation.
get();
314 const double gs = m_groundSpeed.get();
315 const double pitch = m_pitch.
get();
316 const double roll = m_roll.
get();
317 const double trueHeading = m_heading.
get();
318 const double qnh = m_qnhInhg.
get();
332 else if (message.
getMethodName() ==
"getOwnAircraftVelocityData")
335 const double velocityX = m_velocityX.
get();
336 const double velocityY = m_velocityY.
get();
337 const double velocityZ = m_velocityZ.
get();
338 const double pitchVelocity = m_pitchVelocity.
get();
339 const double rollVelocity = m_rollVelocity.
get();
340 const double headingVelocity = m_headingVelocity.
get();
352 else if (message.
getMethodName() ==
"getOwnAircraftCom1Data")
355 const int active = m_com1Active.
get();
356 const int standby = m_com1Standby.
get();
357 const double volume = m_com1Volume.
get();
370 else if (message.
getMethodName() ==
"getOwnAircraftCom2Data")
373 const int active = m_com2Active.
get();
374 const int standby = m_com2Standby.
get();
375 const double volume = m_com2Volume.
get();
391 const int code = m_xpdrCode.
get();
392 const int mode = m_xpdrMode.
get();
393 const bool id = m_xpdrIdent.
get();
405 const bool beaconLightsOn = m_beaconLightsOn.
get();
406 const bool landingLightsOn = m_landingLightsOn.
get();
407 const bool navLightsOn = m_navLightsOn.
get();
408 const bool strobeLightsOn = m_strobeLightsOn.
get();
409 const bool taxiLightsOn = m_taxiLightsOn.
get();
423 const double flapsReployRatio = m_flapsReployRatio.
get();
424 const double gearReployRatio = m_gearReployRatio.
getAt(0);
425 const double speedBrakeRatio = m_speedBrakeRatio.
get();
436 else if (message.
getMethodName() ==
"getOwnAircraftModelData")
452 else if (message.
getMethodName() ==
"getAircraftModelFilename")
456 else if (message.
getMethodName() ==
"getAircraftModelString")
472 else if (message.
getMethodName() ==
"getAircraftDescription")
484 else if (message.
getMethodName() ==
"getXPlaneInstallationPath")
488 else if (message.
getMethodName() ==
"getXPlanePreferencesPath")
518 else if (message.
getMethodName() ==
"setFlightNetworkConnected")
521 bool connected =
false;
529 std::string callsign;
558 else if (message.
getMethodName() ==
"getIndicatedAirspeedKias")
776 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
779 return DBUS_HANDLER_RESULT_HANDLED;
784 if (m_sceneryIsLoading.
get() != m_sceneryWasLoading)
787 m_sceneryWasLoading = m_sceneryIsLoading.
get();
792 if (m_disappearMessageWindowTime != std::chrono::system_clock::time_point() &&
793 std::chrono::system_clock::now() > m_disappearMessageWindowTime && m_messages.
isVisible())
796 m_disappearMessageWindowTime = std::chrono::system_clock::time_point();
802 void CService::emitAircraftModelChanged(
const std::string &path,
const std::string &filename,
803 const std::string &livery,
const std::string &icao,
804 const std::string &modelString,
const std::string &name,
805 const std::string &description)
808 XSWIFTBUS_SERVICE_OBJECTPATH, XSWIFTBUS_SERVICE_INTERFACENAME,
"aircraftModelChanged");
820 void CService::emitSceneryLoaded()
822 CDBusMessage signal =
827 void CService::updateMessageBoxFromSettings()
831 if (values.size() >= 6)
833 m_messages.
setValues(values[0], values[1], values[2], values[3], values[4], values[5]);
DataRefType getAt(int index) const
Get the value of a single element.
bool wantsReply() const
Does this message want a reply?
void appendArgument(bool value)
Append argument. Make sure to call.
void getArgument(int &value)
Read single argument. Make sure to call.
std::string getSender() const
Get the message sender.
std::string_view getMethodName() const
Get the called method name.
dbus_uint32_t getSerial() const
Get the message serial. This is usally required for reply message.
std::string_view getInterfaceName() const
Get the called interface name.
void beginArgumentRead()
Begin reading arguments.
void beginArgumentWrite()
Begin writing argument.
static CDBusMessage createReply(const std::string &destination, dbus_uint32_t serial)
Creates a DBus message containing a DBus reply.
static CDBusMessage createSignal(const std::string &path, const std::string &interfaceName, const std::string &signalName)
Creates a DBus message containing a DBus signal.
void queueDBusCall(const std::function< void()> &func)
Queue a DBus call to be executed in a different thread.
void maybeSendEmptyDBusReply(bool wantsReply, const std::string &destination, dbus_uint32_t serial)
Maybe sends an empty DBus reply (acknowledgement)
void sendDBusMessage(const CDBusMessage &message)
Send DBus message.
void invokeQueuedDBusCalls()
Invoke all pending DBus calls. They will be executed in the calling thread.
void sendDBusReply(const std::string &destination, dbus_uint32_t serial, const T &argument)
Send DBus reply.
bool isVisible() const
Is message box currently visible?
void addMessage(const CMessage &message)
Add a new message to the bottom of the list.
int maxLineLength() const
Returns the maximum number of characters per line.
void setValues(int leftPx, int topPx, int rightPx, int bottomPx, int lines, int durationMs)
Set margin values.
void toggle()
Toggles the visibility of the message box.
int getXPlaneVersionMinor() const
Get minor version number.
bool isCom1Transmitting() const
Is COM1 transmitting?
std::string getAircraftName() const
Get name of current aircraft model.
double getRollDeg() const
Get aircraft roll in degrees.
float getCom1Volume() const
Get the COM1 volume 0..1.
double getFlapsDeployRatio() const
Get flaps deploy ratio, where 0.0 is flaps fully retracted, and 1.0 is flaps fully extended.
float getCom2Volume() const
Get the COM2 volume 0..1.
int getCom1ActiveKhz() const
Get the current COM1 active frequency in kHz.
virtual ~CService()
Destructor.
double getLongitudeDeg() const
Get aircraft longitude in degrees.
double getAltitudeMslM() const
Get aircraft altitude in meters.
double getGroundSpeedMps() const
Get aircraft groundspeed in meters per second.
std::string getAircraftIcaoCode() const
Get the ICAO code of the current aircraft model.
std::string getAircraftModelString() const
Get canonical swift model string of current aircraft model.
bool isPaused() const
True if sim is paused.
int getCom2StandbyKhz() const
Get the current COM2 standby frequency in kHz.
void setFlightNetworkConnected(bool connected)
Set the current connection state.
double getTrueAirspeedKias() const
Get aircraft TAS in meters per second.
double getRollRadPerSec() const
Get aircraft angular velocity in radians per second.
int getXPlaneVersionMajor() const
Get major version number.
bool isCom2Receiving() const
Is COM2 receiving?
std::tuple< double, double, double, double > getFrameStats()
Frames-per-second, averaged over the last 500 frames, or since this function was last called,...
void resetFrameTotals()
Reset the monitoring of total miles and minutes lost due to low frame rate.
double getLocalZVelocityMps() const
Get aircraft local velocity in world coordinates meters per second.
DBusHandlerResult dbusMessageHandler(const CDBusMessage &message)
DBus message handler.
bool getTaxiLightsOn() const
Get whether taxi lights are on.
double getPitchRadPerSec() const
Get aircraft angular velocity in radians per second.
double getSpeedBrakeRatio() const
Get the ratio how much the speedbrakes surfaces are extended (0.0 is fully retracted,...
double getHeadingRadPerSec() const
Get aircraft angular velocity in radians per second.
double getPitchDeg() const
Get aircraft pitch in degrees above horizon.
std::string getXPlaneInstallationPath() const
Get root of X-Plane install path.
std::string getCommitHash() const
Returns the SHA1 of the last commit that could influence xswiftbus.
void onAircraftModelChanged()
Called by XPluginReceiveMessage when the model changes.
int getTransponderCode() const
Get the current transponder code in decimal.
std::string getXPlanePreferencesPath() const
Get full path to X-Plane preferences file.
double getGearDeployRatio() const
Get gear deploy ratio, where 0 is up and 1 is down.
double getLocalYVelocityMps() const
Get aircraft local velocity in world coordinates meters per second.
bool getTransponderIdent() const
Get whether we are currently squawking ident.
int getCom1StandbyKhz() const
Get the current COM1 standby frequency in kHz.
void setOwnCallsign(const std::string &callsign)
Set the current own callsign.
bool getAnyWheelOnGround() const
Get whether any wheel is on the ground.
void setTransponderMode(int mode)
Set the current transponder mode (depends on the aircraft, 0 and 1 usually mean standby,...
void setCom1StandbyKhz(int freq)
Set the current COM1 standby frequency in kHz.
std::string getVersionNumber() const
Returns the xswiftbus version number.
bool getLandingLightsOn() const
Get whether landing lights are on.
bool isCom1Receiving() const
Is COM1 receiving?
void onSceneryLoaded()
Called by XPluginReceiveMessage when some scenery is loaded.
double getHeightAglM() const
Get aircraft height in meters.
std::string getAircraftDescription() const
Get the description of the current aircraft model.
void setTransponderCode(int code)
Set the current transponder code in decimal.
void setDisappearMessageWindowTimeMs(int durationMs)
Enable/disable message window disappearing after x ms.
double getIndicatedAirspeedKias() const
Get aircraft IAS in knots.
void setCom2ActiveKhz(int freq)
Set the current COM2 active frequency in kHz.
double getLocalXVelocityMps() const
Get aircraft local velocity in world coordinates meters per second.
bool getBeaconLightsOn() const
Get whether beacon lights are on.
int process()
Perform generic processing.
double getPressureAltitudeFt() const
Get aircraft pressure altitude in feet in standard atmosphere in X-Plane 12. NaN in earlier versions ...
bool getStrobeLightsOn() const
Get whether strobe lights are on.
std::string getAircraftModelPath() const
Get full path to current aircraft model.
void addTextMessage(const std::string &text, double red, double green, double blue)
Add a text message to the on-screen display, with RGB components in the range [0,1].
double getLatitudeDeg() const
Get aircraft latitude in degrees.
int getCom2ActiveKhz() const
Get the current COM2 active frequency in kHz.
bool isCom2Transmitting() const
Is COM2 transmitting?
double getTrueHeadingDeg() const
Get aircraft true heading in degrees.
std::string getAircraftLivery() const
Get current aircraft livery.
double getQNHInHg() const
Get barometric pressure at sea level in inches of mercury.
void setCom1ActiveKhz(int freq)
Set the current COM1 active frequency in kHz.
void setCom2StandbyKhz(int freq)
Set the current COM2 standby frequency in kHz.
int getTransponderMode() const
Get the current transponder mode (depends on the aircraft, 0 and 1 usually mean standby,...
int getNumberOfEngines() const
Get the number of engines of current aircraft.
std::string getSettingsJson() const
Get settings in JSON format.
bool isUsingRealTime() const
True if sim time is tracking operating system time.
double getGroundElevation() const
Get elevation of ground under the plane in meters.
std::vector< double > getEngineN1Percentage() const
Get the N1 speed as percent of max (per engine)
std::string getAircraftModelFilename() const
Get base filename of current aircraft model.
void setSettingsJson(const std::string &jsonString)
Set settings.
bool getAllWheelsOnGround() const
Get whether all wheels are on the ground.
bool getNavLightsOn() const
Get whether nav lights are on.
void setSettings(const CSettings &settings)
Set settings.
CSettings getSettings() const
Get settings.
bool writeConfig(bool tcas, bool debug)
Write a config file with these new values.
xswiftbus/swift side settings class, JSON capable, shared among all services
Something owning the settings.
DataRefType get() const
Get the value of the dataref.
std::string get() const
Get the value of the whole string.
std::vector< int > getMessageBoxValuesVector() const
Left, top, right, bottom, lines, duration, color(freq, priv, serv, stat, sup)
bool isLogRenderPhases() const
Debug messages?
bool isTcasEnabled() const
TCAS functionality?
std::string convertToString() const
Convert to string.
std::string toXSwiftBusJsonString() const
As JSON string.
bool parseXSwiftBusString(const std::string &json)
Load and parse config file.
Plugin loaded by X-Plane which publishes a DBus service.
T::const_iterator begin(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
AcfProperties extractAcfProperties(const std::string &filePath)
Extract ACF properties from an aircraft file.
std::string getFileName(const std::string &filePath)
Get filename (including all extensions) from a filePath.
decltype(Private::empty_u8string()) string
String type.
std::string modelString
Generated model string.
std::string modelName
Model name.
Encoding-aware iterator adaptor for std::u8string.
#define INFO_LOG(msg)
Logger convenience macros.
#define WARNING_LOG(msg)
Logger convenience macros.