From 4500bda1255dac65ea8f792ce1e438ce94a82482 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Mon, 8 Sep 2014 23:24:01 +0200 Subject: [PATCH] Added updates by VATSIM data file for voice capabilities --- src/blackcore/airspace_monitor.cpp | 37 ++++++++++++++++++-- src/blackcore/airspace_monitor.h | 3 ++ src/blackcore/vatsimdatafilereader.cpp | 36 +++++++++++++++++--- src/blackcore/vatsimdatafilereader.h | 5 +++ src/blackmisc/nwclient.h | 3 ++ src/blackmisc/nwvoicecapabilites.cpp | 47 ++++++++++++++++++++++++++ src/blackmisc/nwvoicecapabilities.h | 17 +++++++++- 7 files changed, 140 insertions(+), 8 deletions(-) diff --git a/src/blackcore/airspace_monitor.cpp b/src/blackcore/airspace_monitor.cpp index d9fca7c6b..71823b266 100644 --- a/src/blackcore/airspace_monitor.cpp +++ b/src/blackcore/airspace_monitor.cpp @@ -44,6 +44,7 @@ namespace BlackCore // AutoConnection: this should also avoid race conditions by updating the bookings this->connect(this->m_vatsimBookingReader, &CVatsimBookingReader::dataRead, this, &CAirspaceMonitor::ps_receivedBookings); + this->connect(this->m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CAirspaceMonitor::ps_receivedDataFile); } CFlightPlan CAirspaceMonitor::loadFlightPlanFromNetwork(const CCallsign &callsign) @@ -237,7 +238,9 @@ namespace BlackCore vm = CIndexVariantMap({CAircraft::IndexPilot, CUser::IndexRealName}, realname); this->m_aircraftsInRange.applyIf(&CAircraft::getCallsign, callsign, vm); + // Client vm = CIndexVariantMap({CClient::IndexUser, CUser::IndexRealName}, realname); + this->addVoiceCapabilitiesFromDataFile(vm, callsign); this->m_otherClients.applyIf(&CClient::getCallsign, callsign, vm); } @@ -249,6 +252,7 @@ namespace BlackCore capabilities.addValue(CClient::FsdWithInterimPositions, (flags & INetwork::SupportsInterimPosUpdates)); capabilities.addValue(CClient::FsdWithModelDescription, (flags & INetwork::SupportsModelDescriptions)); CIndexVariantMap vm(CClient::IndexCapabilities, capabilities.toQVariant()); + this->addVoiceCapabilitiesFromDataFile(vm, callsign); this->m_otherClients.applyIf(&CClient::getCallsign, callsign, vm); } @@ -293,7 +297,7 @@ namespace BlackCore if (this->m_atcStationsBooked.contains(&CAtcStation::getCallsign, callsignTower)) { emit this->changedAtcStationsBooked(); } } - void CAirspaceMonitor::ps_flightplanReceived(const CCallsign &callsign, const CFlightPlan &flightPlan) + void CAirspaceMonitor::ps_flightPlanReceived(const CCallsign &callsign, const CFlightPlan &flightPlan) { CFlightPlan plan(flightPlan); plan.setWhenLastSentOrLoaded(QDateTime::currentDateTimeUtc()); @@ -318,6 +322,17 @@ namespace BlackCore this->m_network->sendFsipirCustomPacket(recipientCallsign, icao.getAirlineDesignator(), icao.getAircraftDesignator(), icao.getAircraftCombinedType(), modelString); } + void CAirspaceMonitor::addVoiceCapabilitiesFromDataFile(CIndexVariantMap &vm, const CCallsign &callsign) + { + Q_ASSERT(this->m_vatsimDataFileReader); + if (callsign.isEmpty()) return; + CVoiceCapabilities vc = this->m_vatsimDataFileReader->getVoiceCapabilityForCallsign(callsign); + if (!vc.isUnknown()) + { + vm.addValue(CClient::IndexVoiceCapabilities, vc); + } + } + void CAirspaceMonitor::ps_receivedBookings(const CAtcStationList &bookedStations) { Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this)); @@ -326,7 +341,7 @@ namespace BlackCore { // complete by VATSIM data file data this->m_vatsimDataFileReader->getAtcStations().updateFromVatsimDataFileStation(bookedStation); - // exchange booking and online data + // exchange booking and online data, both sides are updated this->m_atcStationsOnline.mergeWithBooking(bookedStation); // into list this->m_atcStationsBooked.push_back(bookedStation); @@ -334,6 +349,20 @@ namespace BlackCore emit this->changedAtcStationsBooked(); // all booked stations reloaded } + void CAirspaceMonitor::ps_receivedDataFile() + { + Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this)); + for (auto i = this->m_otherClients.begin(); i != this->m_otherClients.end(); ++i) + { + CClient client = (*i); + if (client.hasSpecifiedVoiceCapabilities()) continue; + CVoiceCapabilities vc = this->m_vatsimDataFileReader->getVoiceCapabilityForCallsign(client.getCallsign()); + if (vc.isUnknown()) continue; + client.setVoiceCapabilities(vc); + (*i) = client; + } + } + void CAirspaceMonitor::ps_atcPositionUpdate(const CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &frequency, const CCoordinateGeodetic &position, const BlackMisc::PhysicalQuantities::CLength &range) { Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this)); @@ -422,7 +451,9 @@ namespace BlackCore this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsign, vm); emit this->changedAtcStationsBooked(); // single ATIS received } - vm = CIndexVariantMap(CClient::IndexVoiceCapabilities, CVoiceCapabilities(CVoiceCapabilities::Voice).toQVariant()); + + // receiving voice room means ATC has voice + vm = CIndexVariantMap(CClient::IndexVoiceCapabilities, CVoiceCapabilities::fromVoiceCapabilities(CVoiceCapabilities::Voice).toQVariant()); this->m_otherClients.applyIf(&CClient::getCallsign, callsign, vm); } diff --git a/src/blackcore/airspace_monitor.h b/src/blackcore/airspace_monitor.h index fcd132dc0..209a2c763 100644 --- a/src/blackcore/airspace_monitor.h +++ b/src/blackcore/airspace_monitor.h @@ -139,6 +139,9 @@ namespace BlackCore void sendFsipirCustomPacket(const BlackMisc::Aviation::CCallsign &recipientCallsign) const; QStringList createFsipiCustomPacketData() const; + //! Helper method, add voice capabilites if available + void addVoiceCapabilitiesFromDataFile(BlackMisc::CIndexVariantMap &vm, const BlackMisc::Aviation::CCallsign &callsign); + private slots: void ps_realNameReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &realname); void ps_capabilitiesReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, quint32 flags); diff --git a/src/blackcore/vatsimdatafilereader.cpp b/src/blackcore/vatsimdatafilereader.cpp index 261f64478..618019a45 100644 --- a/src/blackcore/vatsimdatafilereader.cpp +++ b/src/blackcore/vatsimdatafilereader.cpp @@ -87,6 +87,19 @@ namespace BlackCore return aircraft.getIcaoInfo(); } + CVoiceCapabilities CVatsimDataFileReader::getVoiceCapabilityForCallsign(const CCallsign &callsign) + { + QReadLocker rl(&this->m_lock); + if (this->m_voiceCapabilities.contains(callsign)) + { + return m_voiceCapabilities[callsign]; + } + else + { + return CVoiceCapabilities::fromVoiceCapabilities(CVoiceCapabilities::Unknown); + } + } + void CVatsimDataFileReader::updateWithVatsimDataFileData(CAircraft &aircraftToBeUdpated) const { this->getAircrafts().updateWithVatsimDataFileData(aircraftToBeUdpated); @@ -158,9 +171,10 @@ namespace BlackCore if (lines.isEmpty()) return; // build on local vars for thread safety - CServerList voiceServers; + CServerList voiceServers; CAtcStationList atcStations; - CAircraftList aircrafts; + CAircraftList aircrafts; + QMap voiceCapabilities; QDateTime updateTimestampFromFile; QStringList clientSectionAttributes; @@ -213,8 +227,9 @@ namespace BlackCore case SectionClients: { QMap clientPartsMap = clientPartsToMap(currentLine, clientSectionAttributes); - BlackMisc::Network::CUser user(clientPartsMap["cid"], clientPartsMap["realname"], CCallsign(clientPartsMap["callsign"])); - if (!user.hasValidCallsign()) continue; + CCallsign callsign = CCallsign(clientPartsMap["callsign"]); + if (callsign.isEmpty()) continue; + BlackMisc::Network::CUser user(clientPartsMap["cid"], clientPartsMap["realname"], callsign); const QString clientType = clientPartsMap["clienttype"].toLower(); if (clientType.isEmpty()) break; // sometimes type is empty double lat = clientPartsMap["latitude"].toDouble(); @@ -223,7 +238,19 @@ namespace BlackCore CFrequency frequency = CFrequency(clientPartsMap["frequency"].toDouble(), CFrequencyUnit::MHz()); CCoordinateGeodetic position(lat, lng, -1); CAltitude altitude(alt, CAltitude::MeanSeaLevel, CLengthUnit::ft()); + QString flightPlanRemarks = clientPartsMap["planned_remarks"]; + // Voice capabilities + if (!flightPlanRemarks.isEmpty()) + { + CVoiceCapabilities vc(flightPlanRemarks); + if (!vc.isUnknown()) + { + voiceCapabilities.insert(callsign, vc); + } + } + + // set as per ATC/pilot if (clientType.startsWith('p')) { // Pilot section @@ -300,6 +327,7 @@ namespace BlackCore this->m_aircrafts = aircrafts; this->m_atcStations = atcStations; this->m_voiceServers = voiceServers; + this->m_voiceCapabilities = voiceCapabilities; } } // read success diff --git a/src/blackcore/vatsimdatafilereader.h b/src/blackcore/vatsimdatafilereader.h index 38f4978d0..ad5057bf1 100644 --- a/src/blackcore/vatsimdatafilereader.h +++ b/src/blackcore/vatsimdatafilereader.h @@ -17,6 +17,7 @@ #include "blackmisc/avaircraftlist.h" #include "blackmisc/nwserverlist.h" #include "blackmisc/nwuserlist.h" +#include "blackmisc/nwvoicecapabilities.h" #include "blackmisc/avcallsignlist.h" #include @@ -80,6 +81,10 @@ namespace BlackCore //! \threadsafe BlackMisc::Aviation::CAircraftIcao getIcaoInfo(const BlackMisc::Aviation::CCallsign &callsign); + //! Voice capability for callsign + //! \threadsafe + BlackMisc::Network::CVoiceCapabilities getVoiceCapabilityForCallsign(const BlackMisc::Aviation::CCallsign &callsign); + //! Update aircraft with VATSIM aircraft data from data file //! \threadsafe void updateWithVatsimDataFileData(BlackMisc::Aviation::CAircraft &aircraftToBeUdpated) const; diff --git a/src/blackmisc/nwclient.h b/src/blackmisc/nwclient.h index 0675babb6..14c89a3b6 100644 --- a/src/blackmisc/nwclient.h +++ b/src/blackmisc/nwclient.h @@ -103,6 +103,9 @@ namespace BlackMisc //! Get voice capabilities const CVoiceCapabilities &getVoiceCapabilities() const { return m_voiceCapabilities;} + //! Has known voice capabilities? + bool hasSpecifiedVoiceCapabilities() const { return !m_voiceCapabilities.isUnknown();} + //! Set voice capabilities void setVoiceCapabilities(const CVoiceCapabilities &voiceCapabilities) { m_voiceCapabilities = voiceCapabilities;} diff --git a/src/blackmisc/nwvoicecapabilites.cpp b/src/blackmisc/nwvoicecapabilites.cpp index 46f0f3c10..c1f9b3115 100644 --- a/src/blackmisc/nwvoicecapabilites.cpp +++ b/src/blackmisc/nwvoicecapabilites.cpp @@ -76,6 +76,20 @@ namespace BlackMisc this->setCapabilities(Voice); return; } + + if (r.contains("/t/")) + { + this->setCapabilities(TextOnly); + return; + } + + if (r.contains("/r/")) + { + this->setCapabilities(VoiceReceivingOnly); + return; + } + + this->setCapabilities(Unknown); } /* @@ -191,6 +205,39 @@ namespace BlackMisc return TupleConverter::jsonMembers(); } + /* + * From enum + */ + const CVoiceCapabilities &CVoiceCapabilities::fromVoiceCapabilities(CVoiceCapabilities::VoiceCapabilities capabilities) + { + static const CVoiceCapabilities u(CVoiceCapabilities::Unknown); + static const CVoiceCapabilities to(CVoiceCapabilities::TextOnly); + static const CVoiceCapabilities v(CVoiceCapabilities::Voice); + static const CVoiceCapabilities vro(CVoiceCapabilities::VoiceReceivingOnly); + + switch (capabilities) + { + case CVoiceCapabilities::TextOnly: + return to; + case CVoiceCapabilities::Voice: + return v; + case CVoiceCapabilities::VoiceReceivingOnly: + return vro; + case CVoiceCapabilities::Unknown: + default: + return u; + } + } + + /* + * All + */ + const QList &CVoiceCapabilities::allCapabilities() + { + static const QList all({fromVoiceCapabilities(Unknown), fromVoiceCapabilities(Voice), fromVoiceCapabilities(VoiceReceivingOnly), fromVoiceCapabilities(TextOnly)}); + return all; + } + /* * Register metadata */ diff --git a/src/blackmisc/nwvoicecapabilities.h b/src/blackmisc/nwvoicecapabilities.h index 2934f5536..580173c94 100644 --- a/src/blackmisc/nwvoicecapabilities.h +++ b/src/blackmisc/nwvoicecapabilities.h @@ -51,6 +51,9 @@ namespace BlackMisc //! Set capabilites void setCapabilities(VoiceCapabilities capabilites) { m_voiceCapabilities = static_cast(capabilites); } + //! Is capability known + bool isUnknown() const { return m_voiceCapabilities == Unknown; } + //! \copydoc CValueObject::toIcon() virtual CIcon toIcon() const override; @@ -81,6 +84,18 @@ namespace BlackMisc //! Members static const QStringList &jsonMembers(); + //! From enum + static const CVoiceCapabilities &fromVoiceCapabilities(VoiceCapabilities capabilities); + + //! From flight plan remarks + static CVoiceCapabilities fromFlightPlanRemarks(const QString &remarks) + { + return CVoiceCapabilities(remarks); + } + + //! All capabilities as list + static const QList &allCapabilities(); + protected: //! \copydoc CValueObject::convertToQString virtual QString convertToQString(bool i18n = false) const override; @@ -105,7 +120,7 @@ namespace BlackMisc int m_voiceCapabilities = Unknown; //! Capabilites from flight plans remarks such as "/V/" - void fromFlightPlanRemarks(const QString &flightPlanRemarks); + void setFromFlightPlanRemarks(const QString &flightPlanRemarks); }; } // namespace