Ref T730, Ref T739 update from own aircraft in one step

* update all values from own aircraft in "one step"
* rational: avoid "single property" updates and numerous round trips (signals, transceiver updates)
* also allow updates of not yet connect, as "a kind of preset"
* do NOT send to network if not authenticated
This commit is contained in:
Klaus Basan
2019-10-09 22:58:11 +02:00
committed by Mat Sutcliffe
parent caa78395a9
commit ef9e7b0bf1
4 changed files with 171 additions and 87 deletions

View File

@@ -51,9 +51,9 @@ namespace BlackCore
connect(m_input, &CInput::opusDataAvailable, this, &CAfvClient::opusDataAvailable); connect(m_input, &CInput::opusDataAvailable, this, &CAfvClient::opusDataAvailable);
connect(m_input, &CInput::inputVolumeStream, this, &CAfvClient::inputVolumeStream); connect(m_input, &CInput::inputVolumeStream, this, &CAfvClient::inputVolumeStream);
connect(m_output, &Output::outputVolumeStream, this, &CAfvClient::outputVolumeStream); connect(m_output, &Output::outputVolumeStream, this, &CAfvClient::outputVolumeStream);
connect(m_connection, &CClientConnection::audioReceived, this, &CAfvClient::audioOutDataAvailable); connect(m_connection, &CClientConnection::audioReceived, this, &CAfvClient::audioOutDataAvailable);
connect(m_voiceServerPositionTimer, &QTimer::timeout, this, &CAfvClient::onPositionUpdateTimer); connect(m_voiceServerPositionTimer, &QTimer::timeout, this, &CAfvClient::onPositionUpdateTimer);
// deferred init // deferred init
QTimer::singleShot(1000, this, &CAfvClient::deferredInit); QTimer::singleShot(1000, this, &CAfvClient::deferredInit);
@@ -87,11 +87,9 @@ namespace BlackCore
// init with context values // init with context values
this->connectWithContexts(); this->connectWithContexts();
if (m_connectedWithContext && hasContext())
{ // update from context
// update from context this->onPositionUpdateTimer();
this->updateTransceivers();
}
} }
void CAfvClient::connectWithContexts() void CAfvClient::connectWithContexts()
@@ -119,12 +117,12 @@ namespace BlackCore
this->setCallsign(callsign); this->setCallsign(callsign);
m_connection->connectTo(cid, password, callsign); m_connection->connectTo(cid, password, callsign);
this->updateTransceivers(); // uses context if available m_aliasedStations = m_connection->getAllAliasedStations();
this->onPositionUpdateTimer();
if (m_connection->isConnected()) { emit this->connectionStatusChanged(Connected); } if (m_connection->isConnected()) { emit this->connectionStatusChanged(Connected); }
else { emit this->connectionStatusChanged(Disconnected); } else { emit this->connectionStatusChanged(Disconnected); }
m_aliasedStations = m_connection->getAllAliasedStations();
} }
void CAfvClient::disconnectFrom() void CAfvClient::disconnectFrom()
@@ -221,6 +219,8 @@ namespace BlackCore
this->onSettingsChanged(); // make sure all settings are applied this->onSettingsChanged(); // make sure all settings are applied
m_isStarted = true; m_isStarted = true;
CLogMessage(this).info(u"Started [Input: %1] [Output: %2]") << inputDevice.getName() << outputDevice.getName(); CLogMessage(this).info(u"Started [Input: %1] [Output: %2]") << inputDevice.getName() << outputDevice.getName();
this->onPositionUpdateTimer(); // update values
} }
void CAfvClient::startAudio(const QString &inputDeviceName, const QString &outputDeviceName) void CAfvClient::startAudio(const QString &inputDeviceName, const QString &outputDeviceName)
@@ -249,13 +249,6 @@ namespace BlackCore
m_isStarted = false; m_isStarted = false;
m_connection->setReceiveAudio(false); m_connection->setReceiveAudio(false);
// transceivers
{
QMutexLocker lock(&m_mutexTransceivers);
m_transceivers.clear();
}
this->updateTransceivers(false);
// stop input/output // stop input/output
m_updateTimer.stop(); m_updateTimer.stop();
m_input->stop(); m_input->stop();
@@ -304,19 +297,7 @@ namespace BlackCore
// Fix rounding issues like 128074999 Hz -> 128075000 Hz // Fix rounding issues like 128074999 Hz -> 128075000 Hz
quint32 roundedFrequencyHz = static_cast<quint32>(qRound(frequencyHz / 1000.0)) * 1000; quint32 roundedFrequencyHz = static_cast<quint32>(qRound(frequencyHz / 1000.0)) * 1000;
{ roundedFrequencyHz = this->getAliasFrequencyHz(roundedFrequencyHz);
QMutexLocker lock(&m_mutex);
auto it = std::find_if(m_aliasedStations.begin(), m_aliasedStations.end(), [roundedFrequencyHz](const StationDto & d)
{
return d.frequencyAliasHz == roundedFrequencyHz;
});
if (it != m_aliasedStations.end())
{
CLogMessage(this).debug(u"Aliasing %1Hz [VHF] to %2Hz [HF]") << frequencyHz << it->frequencyHz;
roundedFrequencyHz = it->frequencyHz;
}
}
bool updateTransceivers = false; bool updateTransceivers = false;
{ {
@@ -363,7 +344,8 @@ namespace BlackCore
void CAfvClient::updateTransceivers(bool updateFrequencies) void CAfvClient::updateTransceivers(bool updateFrequencies)
{ {
if (!m_connection->isConnected()) { return; } // also update if NOT connected, values will be preset
if (hasContext()) if (hasContext())
{ {
const CSimulatedAircraft ownAircraft = sApp->getIContextOwnAircraft()->getOwnAircraft(); const CSimulatedAircraft ownAircraft = sApp->getIContextOwnAircraft()->getOwnAircraft();
@@ -400,7 +382,7 @@ namespace BlackCore
void CAfvClient::setTransmittingTransceiver(quint16 transceiverID) void CAfvClient::setTransmittingTransceiver(quint16 transceiverID)
{ {
TxTransceiverDto tx = { transceiverID }; const TxTransceiverDto tx = { transceiverID };
this->setTransmittingTransceivers({ tx }); this->setTransmittingTransceivers({ tx });
} }
@@ -475,7 +457,7 @@ namespace BlackCore
if (!active) if (!active)
{ {
//AGC // AGC
// if (maxDbReadingInPTTInterval > -1) InputVolumeDb = InputVolumeDb - 1; // if (maxDbReadingInPTTInterval > -1) InputVolumeDb = InputVolumeDb - 1;
// if (maxDbReadingInPTTInterval < -4) InputVolumeDb = InputVolumeDb + 1; // if (maxDbReadingInPTTInterval < -4) InputVolumeDb = InputVolumeDb + 1;
m_maxDbReadingInPTTInterval = -100; m_maxDbReadingInPTTInterval = -100;
@@ -485,6 +467,12 @@ namespace BlackCore
emit this->ptt(active, com, this->identifier()); emit this->ptt(active, com, this->identifier());
} }
double CAfvClient::getInputVolumeDb() const
{
QMutexLocker lock(&m_mutex);
return m_inputVolumeDb;
}
void CAfvClient::setInputVolumeDb(double valueDb) void CAfvClient::setInputVolumeDb(double valueDb)
{ {
if (valueDb > MaxDbIn) { valueDb = MaxDbIn; } if (valueDb > MaxDbIn) { valueDb = MaxDbIn; }
@@ -498,6 +486,12 @@ namespace BlackCore
} }
} }
double CAfvClient::getOutputVolumeDb() const
{
QMutexLocker lock(&m_mutex);
return m_outputVolumeDb;
}
int CAfvClient::getNormalizedInputVolume() const int CAfvClient::getNormalizedInputVolume() const
{ {
const double db = this->getInputVolumeDb(); const double db = this->getInputVolumeDb();
@@ -635,26 +629,20 @@ namespace BlackCore
QString CAfvClient::getReceivingCallsignsCom1() QString CAfvClient::getReceivingCallsignsCom1()
{ {
QMutexLocker lock(&m_mutex); QMutexLocker lock(&m_mutex);
if (m_soundcardSampleProvider) if (!m_soundcardSampleProvider) return {};
{ return m_soundcardSampleProvider->getReceivingCallsigns(0);
return m_soundcardSampleProvider->getReceivingCallsigns(0);
}
return {};
} }
QString CAfvClient::getReceivingCallsignsCom2() QString CAfvClient::getReceivingCallsignsCom2()
{ {
QMutexLocker lock(&m_mutex); QMutexLocker lock(&m_mutex);
if (m_soundcardSampleProvider) if (!m_soundcardSampleProvider) return {};
{ return m_soundcardSampleProvider->getReceivingCallsigns(1);
return m_soundcardSampleProvider->getReceivingCallsigns(1);
}
return {};
} }
bool CAfvClient::updateVoiceServerUrl(const QString &url) bool CAfvClient::updateVoiceServerUrl(const QString &url)
{ {
if (m_connection) { return false; } if (!m_connection) { return false; }
return m_connection->updateVoiceServerUrl(url); return m_connection->updateVoiceServerUrl(url);
} }
@@ -665,7 +653,16 @@ namespace BlackCore
void CAfvClient::onPositionUpdateTimer() void CAfvClient::onPositionUpdateTimer()
{ {
this->updateTransceivers(); if (hasContext())
{
// for pilot client
this->updateFromOwnAircraft(sApp->getIContextOwnAircraft()->getOwnAircraft(), false);
}
else
{
// for AFV sample client
this->updateTransceivers();
}
} }
void CAfvClient::onSettingsChanged() void CAfvClient::onSettingsChanged()
@@ -676,38 +673,101 @@ namespace BlackCore
this->setBypassEffects(!audioSettings.isAudioEffectsEnabled()); this->setBypassEffects(!audioSettings.isAudioEffectsEnabled());
} }
void CAfvClient::onUpdateTransceiversFromContext(const CSimulatedAircraft &aircraft, const CIdentifier &originator) void CAfvClient::updateFromOwnAircraft(const CSimulatedAircraft &aircraft, bool withSignals)
{ {
Q_UNUSED(originator) if (!sApp || sApp->isShuttingDown()) { return; }
this->updatePosition(aircraft.latitude().value(CAngleUnit::deg()),
aircraft.longitude().value(CAngleUnit::deg()),
aircraft.getAltitude().value(CLengthUnit::ft()));
TransceiverDto transceiverCom1;
TransceiverDto transceiverCom2;
transceiverCom1.id = comUnitToTransceiverId(CComSystem::Com1);
transceiverCom2.id = comUnitToTransceiverId(CComSystem::Com2);
// position
const double latDeg = aircraft.latitude().value(CAngleUnit::deg());
const double lngDeg = aircraft.longitude().value(CAngleUnit::deg());
const double altM = aircraft.getAltitude().value(CLengthUnit::m());
transceiverCom1.LatDeg = transceiverCom2.LatDeg = latDeg;
transceiverCom1.LonDeg = transceiverCom2.LonDeg = lngDeg;
transceiverCom1.HeightAglM = transceiverCom2.HeightAglM = altM;
transceiverCom1.HeightMslM = transceiverCom2.HeightMslM = altM;
// enabled, rx/tx, frequency
const CComSystem com1 = aircraft.getCom1System(); const CComSystem com1 = aircraft.getCom1System();
const CComSystem com2 = aircraft.getCom2System(); const CComSystem com2 = aircraft.getCom2System();
this->updateComFrequency(CComSystem::Com1, com1); const quint32 f1 = static_cast<quint32>(com1.getFrequencyActive().valueInteger(CFrequencyUnit::Hz()));
this->updateComFrequency(CComSystem::Com2, com2); const quint32 f2 = static_cast<quint32>(com2.getFrequencyActive().valueInteger(CFrequencyUnit::Hz()));
transceiverCom1.frequencyHz = this->getAliasFrequencyHz(f1);
transceiverCom2.frequencyHz = this->getAliasFrequencyHz(f2);
const bool tx1 = com1.isTransmitEnabled(); const bool tx1 = com1.isTransmitEnabled();
const bool rx1 = com1.isReceiveEnabled(); const bool rx1 = com1.isReceiveEnabled();
const bool tx2 = com2.isTransmitEnabled(); const bool tx2 = com2.isTransmitEnabled(); // we only allow one (1) transmit
const bool rx2 = com2.isReceiveEnabled(); const bool rx2 = com2.isReceiveEnabled();
this->enableComUnit(CComSystem::Com1, tx1 || rx1); // enable, we currently treat receive as enable
this->enableComUnit(CComSystem::Com2, tx2 || rx2); // flight sim cockpits normally use rx and tx
// AFV uses tx and enable
const bool e1 = rx1;
const bool e2 = rx2;
// currently only transmitting at one unit // transceivers
if (tx1) QSet<quint16> newEnabledTransceiverIds;
QVector<TransceiverDto> newTransceivers { transceiverCom1, transceiverCom2 };
QVector<TransceiverDto> newEnabledTransceivers;
QVector<TxTransceiverDto> newTransmittingTransceivers;
if (e1) { newEnabledTransceivers.push_back(transceiverCom1); newEnabledTransceiverIds.insert(transceiverCom1.id); }
if (e2) { newEnabledTransceivers.push_back(transceiverCom2); newEnabledTransceiverIds.insert(transceiverCom2.id); }
// Transmitting transceivers, currently ALLOW ONLY ONE
if (tx1 && e1) { newTransmittingTransceivers.push_back(transceiverCom1); }
else if (tx2 && e2) { newTransmittingTransceivers.push_back(transceiverCom2); }
// lock and update
{ {
this->setTransmittingComUnit(CComSystem::Com1); QMutexLocker lock(&m_mutexTransceivers);
m_transceivers = newTransceivers;
m_enabledTransceivers = newEnabledTransceiverIds;
m_transmittingTransceivers = newTransmittingTransceivers;
} }
else if (tx2) // in connection and soundcard only use the enabled tarnsceivers
const QString callsign = this->getCallsign();
{ {
this->setTransmittingComUnit(CComSystem::Com2); QMutexLocker lock(&m_mutex);
if (m_connection) { m_connection->updateTransceivers(callsign, newEnabledTransceivers); }
if (m_soundcardSampleProvider) { m_soundcardSampleProvider->updateRadioTransceivers(newEnabledTransceivers); }
} }
this->updateTransceivers(); if (withSignals) { emit this->updatedFromOwnAircraftCockpit(); }
emit this->updatedFromOwnAircraftCockpit(); }
void CAfvClient::onUpdateTransceiversFromContext(const CSimulatedAircraft &aircraft, const CIdentifier &originator)
{
if (originator == this->identifier()) { return; }
this->updateFromOwnAircraft(aircraft);
}
quint32 CAfvClient::getAliasFrequencyHz(quint32 frequencyHz) const
{
// void rounding issues from float/double
quint32 roundedFrequencyHz = static_cast<quint32>(qRound(frequencyHz / 1000.0)) * 1000;
// change to aliased frequency if needed
{
QMutexLocker lock(&m_mutex);
auto it = std::find_if(m_aliasedStations.begin(), m_aliasedStations.end(), [roundedFrequencyHz](const StationDto & d)
{
return d.frequencyAliasHz == roundedFrequencyHz;
});
if (it != m_aliasedStations.end())
{
CLogMessage(this).debug(u"Aliasing %1Hz [VHF] to %2Hz [HF]") << frequencyHz << it->frequencyHz;
roundedFrequencyHz = it->frequencyHz;
}
}
return roundedFrequencyHz;
} }
quint16 CAfvClient::comUnitToTransceiverId(CComSystem::ComUnit comUnit) quint16 CAfvClient::comUnitToTransceiverId(CComSystem::ComUnit comUnit)
@@ -716,8 +776,7 @@ namespace BlackCore
{ {
case CComSystem::Com1: return 0; case CComSystem::Com1: return 0;
case CComSystem::Com2: return 1; case CComSystem::Com2: return 1;
default: default: break;
break;
} }
return 0; return 0;
} }

View File

@@ -106,10 +106,12 @@ namespace BlackCore
void setMuted(bool mute); void setMuted(bool mute);
//! @} //! @}
//! Start/stop client @{
bool restartWithNewDevices(const BlackMisc::Audio::CAudioDeviceInfo &inputDevice, const BlackMisc::Audio::CAudioDeviceInfo &outputDevice); bool restartWithNewDevices(const BlackMisc::Audio::CAudioDeviceInfo &inputDevice, const BlackMisc::Audio::CAudioDeviceInfo &outputDevice);
void startAudio(const BlackMisc::Audio::CAudioDeviceInfo &inputDevice, const BlackMisc::Audio::CAudioDeviceInfo &outputDevice, const QVector<quint16> &transceiverIDs); void startAudio(const BlackMisc::Audio::CAudioDeviceInfo &inputDevice, const BlackMisc::Audio::CAudioDeviceInfo &outputDevice, const QVector<quint16> &transceiverIDs);
Q_INVOKABLE void startAudio(const QString &inputDeviceName, const QString &outputDeviceName); Q_INVOKABLE void startAudio(const QString &inputDeviceName, const QString &outputDeviceName);
void stopAudio(); void stopAudio();
//! @}
//! Enable COM unit/transceiver //! Enable COM unit/transceiver
//! \threadsafe //! \threadsafe
@@ -155,6 +157,11 @@ namespace BlackCore
//! \threadsafe //! \threadsafe
Q_INVOKABLE void updatePosition(double latitudeDeg, double longitudeDeg, double heightMeters); Q_INVOKABLE void updatePosition(double latitudeDeg, double longitudeDeg, double heightMeters);
//! Update from own aircraft
//! \remark full update of frequency, position and enabled transceivers in one step
//! \threadsafe
void updateFromOwnAircraft(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, bool withSignals = true);
//! Push to talk @{ //! Push to talk @{
Q_INVOKABLE void setPtt(bool active); Q_INVOKABLE void setPtt(bool active);
void setPttForCom(bool active, BlackMisc::Audio::PTTCOM com); void setPttForCom(bool active, BlackMisc::Audio::PTTCOM com);
@@ -167,34 +174,46 @@ namespace BlackCore
Q_INVOKABLE bool isLoopback() const { return m_loopbackOn; } Q_INVOKABLE bool isLoopback() const { return m_loopbackOn; }
//! @} //! @}
//! Input volume in dB, +-18dB @{ //! Input volume in dB, +-18dB
double getInputVolumeDb() const { return m_inputVolumeDb; } //! \threadsafe
//! @{
double getInputVolumeDb() const;
Q_INVOKABLE void setInputVolumeDb(double valueDb); Q_INVOKABLE void setInputVolumeDb(double valueDb);
//! @} //! @}
//! Output volume in dB, +-18dB @{ //! Output volume in dB, +-18dB
double getOutputVolumeDb() const { return m_outputVolumeDb; } //! \threadsafe
//! @{
double getOutputVolumeDb() const;
Q_INVOKABLE void setOutputVolumeDb(double valueDb); Q_INVOKABLE void setOutputVolumeDb(double valueDb);
//! @} //! @}
//! Normalized volumes 0..100 @{ //! Normalized volumes 0..100
//! \threadsafe
//! @{
int getNormalizedInputVolume() const; int getNormalizedInputVolume() const;
int getNormalizedOutputVolume() const; int getNormalizedOutputVolume() const;
void setNormalizedInputVolume(int volume); void setNormalizedInputVolume(int volume);
void setNormalizedOutputVolume(int volume); void setNormalizedOutputVolume(int volume);
//! @} //! @}
//! VU values, 0..1 @{ //! VU values, 0..1
//! \threadsafe
//! @{
double getInputVolumePeakVU() const; double getInputVolumePeakVU() const;
double getOutputVolumePeakVU() const; double getOutputVolumePeakVU() const;
//! @} //! @}
//! Recently used device @{ //! Recently used device
//! \threadsafe
//! @{
const BlackMisc::Audio::CAudioDeviceInfo &getInputDevice() const; const BlackMisc::Audio::CAudioDeviceInfo &getInputDevice() const;
const BlackMisc::Audio::CAudioDeviceInfo &getOutputDevice() const; const BlackMisc::Audio::CAudioDeviceInfo &getOutputDevice() const;
//! @} //! @}
//! Callsigns currently received @{ //! Callsigns currently received
//! \threadsafe
//! @{
QString getReceivingCallsignsCom1(); QString getReceivingCallsignsCom1();
QString getReceivingCallsignsCom2(); QString getReceivingCallsignsCom2();
//! @} //! @}
@@ -238,6 +257,10 @@ namespace BlackCore
void updateTransceivers(bool updateFrequencies = true); void updateTransceivers(bool updateFrequencies = true);
void onUpdateTransceiversFromContext(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, const BlackMisc::CIdentifier &originator); void onUpdateTransceiversFromContext(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, const BlackMisc::CIdentifier &originator);
//! Frequency from aliased stations
//! \threadsafe
quint32 getAliasFrequencyHz(quint32 frequencyHz) const;
static constexpr int PositionUpdatesMs = 5000; //!< position timer static constexpr int PositionUpdatesMs = 5000; //!< position timer
static constexpr int SampleRate = 48000; static constexpr int SampleRate = 48000;
static constexpr int FrameSize = 960; // 20ms static constexpr int FrameSize = 960; // 20ms
@@ -276,8 +299,8 @@ namespace BlackCore
double m_outputVolume = 1.0; double m_outputVolume = 1.0;
double m_maxDbReadingInPTTInterval = -100; double m_maxDbReadingInPTTInterval = -100;
QTimer *m_voiceServerPositionTimer = nullptr; QTimer *m_voiceServerPositionTimer = nullptr;
QVector<StationDto> m_aliasedStations; QVector<StationDto> m_aliasedStations;
Audio::InputVolumeStreamArgs m_inputVolumeStream; Audio::InputVolumeStreamArgs m_inputVolumeStream;
Audio::OutputVolumeStreamArgs m_outputVolumeStream; Audio::OutputVolumeStreamArgs m_outputVolumeStream;

View File

@@ -138,6 +138,7 @@ namespace BlackCore
void CApiServerConnection::updateTransceivers(const QString &callsign, const QVector<TransceiverDto> &transceivers) void CApiServerConnection::updateTransceivers(const QString &callsign, const QVector<TransceiverDto> &transceivers)
{ {
if (!this->sendToNetworkIfAuthenticated()) { return; }
QJsonArray array; QJsonArray array;
for (const TransceiverDto &tx : transceivers) for (const TransceiverDto &tx : transceivers)
{ {
@@ -239,13 +240,7 @@ namespace BlackCore
void CApiServerConnection::postNoResponse(const QString &resource, const QJsonDocument &json) void CApiServerConnection::postNoResponse(const QString &resource, const QJsonDocument &json)
{ {
if (isShuttingDown()) { return; } // avoid crash if (isShuttingDown()) { return; }
if (!m_isAuthenticated)
{
CLogMessage(this).debug(u"AFV not authenticated");
return;
}
this->checkExpiry(); this->checkExpiry();
QUrl url(m_addressUrl); QUrl url(m_addressUrl);
@@ -273,8 +268,7 @@ namespace BlackCore
void CApiServerConnection::deleteResource(const QString &resource) void CApiServerConnection::deleteResource(const QString &resource)
{ {
if (isShuttingDown()) { return; } if (isShuttingDown()) { return; }
if (!m_isAuthenticated) { return; }
QUrl url(m_addressUrl); QUrl url(m_addressUrl);
url.setPath(resource); url.setPath(resource);
@@ -345,6 +339,11 @@ namespace BlackCore
return loop; return loop;
} }
bool CApiServerConnection::sendToNetworkIfAuthenticated() const
{
return m_isAuthenticated && !isShuttingDown();
}
bool CApiServerConnection::isShuttingDown() bool CApiServerConnection::isShuttingDown()
{ {
return !sApp || sApp->isShuttingDown(); return !sApp || sApp->isShuttingDown();

View File

@@ -80,9 +80,9 @@ namespace BlackCore
template<typename TResponse> template<typename TResponse>
TResponse postNoRequest(const QString &resource) TResponse postNoRequest(const QString &resource)
{ {
if (!m_isAuthenticated) if (!this->sendToNetworkIfAuthenticated())
{ {
BlackMisc::CLogMessage(this).debug(u"AFV not authenticated"); // BlackMisc::CLogMessage(this).debug(u"AFV not authenticated");
return {}; return {};
} }
@@ -103,9 +103,9 @@ namespace BlackCore
template<typename TResponse> template<typename TResponse>
QVector<TResponse> getAsVector(const QString &resource) QVector<TResponse> getAsVector(const QString &resource)
{ {
if (! m_isAuthenticated) if (!this->sendToNetworkIfAuthenticated())
{ {
BlackMisc::CLogMessage(this).debug(u"AFV not authenticated"); // BlackMisc::CLogMessage(this).debug(u"AFV not authenticated");
return {}; return {};
} }
@@ -156,6 +156,9 @@ namespace BlackCore
//! Get QLoop for network access, using class must delete the loop //! Get QLoop for network access, using class must delete the loop
QEventLoop *newEventLoop(); QEventLoop *newEventLoop();
//! Send to network
bool sendToNetworkIfAuthenticated() const;
//! Application shutting down //! Application shutting down
static bool isShuttingDown(); static bool isShuttingDown();