From acb5b11966e93397d04b48b4f58a26a6c9423ffa Mon Sep 17 00:00:00 2001 From: Roland Rossgotterer Date: Thu, 19 Sep 2019 16:36:22 +0200 Subject: [PATCH] Finish demo UI and connect it to AFVClient this includes: - enable/disable check boxes, - ptt button - loopback check box - map zoom buttons - showing the received callsign - VHF effects checkbox ref T731 --- samples/afvclient/qml/Transceiver.qml | 5 + samples/afvclient/qml/main.qml | 149 +++++++++++++++++------- src/blackcore/afv/clients/afvclient.cpp | 34 +++++- src/blackcore/afv/clients/afvclient.h | 15 ++- 4 files changed, 156 insertions(+), 47 deletions(-) diff --git a/samples/afvclient/qml/Transceiver.qml b/samples/afvclient/qml/Transceiver.qml index 3da417bf6..0bba44095 100644 --- a/samples/afvclient/qml/Transceiver.qml +++ b/samples/afvclient/qml/Transceiver.qml @@ -3,8 +3,11 @@ import QtQuick.Layouts 1.12 import QtQuick.Controls 2.12 Row { + id: idTransceiver property int transceiverId: 0 property alias frequency: sbFrequency.value + property alias rxOn: cbEnabled.checked + property alias txOn: cbTxOn.checked spacing: 10 Label { @@ -62,6 +65,7 @@ Row { text: qsTr("TX") checked: true anchors.verticalCenter: parent.verticalCenter + onClicked: idTransceiver.txOnChanged(checked) } CheckBox { @@ -70,5 +74,6 @@ Row { text: qsTr("Enabled") checked: true anchors.verticalCenter: parent.verticalCenter + onClicked: idTransceiver.rxOnChanged(checked) } } diff --git a/samples/afvclient/qml/main.qml b/samples/afvclient/qml/main.qml index 792dbc8dd..c91be9d78 100644 --- a/samples/afvclient/qml/main.qml +++ b/samples/afvclient/qml/main.qml @@ -7,13 +7,13 @@ import QtPositioning 5.12 ApplicationWindow { id: window width: 1200 - height: 520 + height: 800 visible: true title: "Audio For Vatsim" Plugin { id: mapPlugin - name: "osm" // "mapboxgl", "esri", ... + name: "osm" } Grid { @@ -42,6 +42,7 @@ ApplicationWindow { height: 25 text: qsTr("1234567") selectByMouse: true + enabled: voiceClient.connectionStatus == 0 // Disconnected horizontalAlignment: Text.AlignLeft renderType: Text.NativeRendering } @@ -61,6 +62,7 @@ ApplicationWindow { height: 25 text: qsTr("123456") selectByMouse: true + enabled: voiceClient.connectionStatus == 0 // Disconnected echoMode: TextInput.PasswordEchoOnEdit horizontalAlignment: Text.AlignLeft renderType: Text.NativeRendering @@ -81,6 +83,7 @@ ApplicationWindow { height: 25 text: qsTr("DECHK") selectByMouse: true + enabled: voiceClient.connectionStatus == 0 // Disconnected horizontalAlignment: Text.AlignLeft renderType: Text.NativeRendering } @@ -129,23 +132,16 @@ ApplicationWindow { Button { id: btConnect - - property bool connected: false width: 170 height: 25 - text: qsTr("Connect") + text: voiceClient.connectionStatus == 0 ? "Connect" : "Disconnect" onClicked: { - if (btConnect.connected) { - btConnect.connected = false; - btConnect.text = qsTr("Connect") - voiceClient.disconnectFrom() - } else { - btConnect.connected = true - btConnect.text = qsTr("Disconnect") + if (voiceClient.connectionStatus == 0) { voiceClient.connectTo(tfUsername.text, tfPassword.text, tfCallsign.text) afvMapReader.setOwnCallsign(tfCallsign.text) + } else if (voiceClient.connectionStatus == 1) { + voiceClient.disconnectFrom() } - } } @@ -173,10 +169,16 @@ ApplicationWindow { anchors.left: leftGrid.right anchors.right: parent.right spacing: 10 - rows: 2 + rows: 3 columns: 3 - Transceiver { id: transceiver1; transceiverId: 0 } + Transceiver { + id: transceiver1 + transceiverId: 0 + onRxOnChanged: { + voiceClient.enableTransceiver(transceiverId, enabled) + } + } SpinBox { id: sbAltitude @@ -191,11 +193,18 @@ ApplicationWindow { Label { id: lblReceivingCom1 height: 40 - text: qsTr("Receiving:") + text: qsTr("Receiving: ") + voiceClient.receivingCallsignsCom1 verticalAlignment: Text.AlignVCenter } - Transceiver { id: transceiver2; transceiverId: 1 } + Transceiver { + id: transceiver2 + transceiverId: 1 + txOn: false + onRxOnChanged: { + voiceClient.enableTransceiver(transceiverId, enabled) + } + } Button { id: btUpdateStack @@ -206,14 +215,13 @@ ApplicationWindow { voiceClient.updateComFrequency(0, transceiver1.frequency * 1000) voiceClient.updateComFrequency(1, transceiver2.frequency * 1000) voiceClient.updatePosition(map.center.latitude, map.center.longitude, sbAltitude.value) - voiceClient.updateTransceivers() } } Label { id: lblReceivingCom2 height: 40 - text: qsTr("Receiving:") + text: qsTr("Receiving: ") + voiceClient.receivingCallsignsCom2 verticalAlignment: Text.AlignVCenter // anchors.verticalCenter: parent.verticalCenter } @@ -221,7 +229,6 @@ ApplicationWindow { Column { id: column - padding: 10 spacing: 10 anchors.top: rightGrid.bottom anchors.left: leftGrid.right @@ -246,17 +253,60 @@ ApplicationWindow { } } -//// CheckBox { -//// id: cbVhfEffects -//// anchors.topMargin: 5 -//// anchors.leftMargin: 10 -//// anchors.left: sbAltitude.right -//// anchors.top: parent.top -//// anchors.verticalCenter: sbAltitude.verticalCenter -//// height: 25 -//// text: qsTr("VHF Effects") -//// checked: true -//// } + Row { + padding: 0 + spacing: 10 + anchors.top: column.bottom + anchors.left: leftGrid.right + anchors.right: parent.right + + CheckBox { + id: cbVhfEffects + text: qsTr("VHF Effects") + checked: true + anchors.verticalCenter: parent.verticalCenter + onClicked: voiceClient.setBypassEffects(!checked) + } + + CheckBox { + id: cbLoopback + text: qsTr("Loopback") + checked: false + anchors.verticalCenter: parent.verticalCenter + onClicked: voiceClient.setLoopBack(checked) + } + + Button { + id: btPtt + width: 150 + height: 40 + text: qsTr("PTT") + onPressed: voiceClient.setPtt(true) + onReleased: voiceClient.setPtt(false) + background: Rectangle { + implicitWidth: btPtt.width + implicitHeight: btPtt.height + color: btPtt.down ? "lightgreen" : "lightgrey" + border.width: 1 + radius: 2 + } + } + + Label { + function translateStatus(status) { + switch(status) { + case 0: return "Disconnected" + case 1: return "Connected" + default: return "Unknown" + } + } + + id: lblStatus + text: "Status: " + translateStatus(voiceClient.connectionStatus) + verticalAlignment: Text.AlignVCenter + anchors.verticalCenter: parent.verticalCenter + } + } Map { id: map @@ -269,19 +319,8 @@ ApplicationWindow { center: QtPositioning.coordinate(48.50, 11.50) // Oslo zoomLevel: 3 -// MapCircle { -// center { -// latitude: map.center.latitude -// longitude: map.center.longitude -// } -// radius: 500000.0 -// color: 'blue' -// border.width: 3 -// border.color: 'blue' -// opacity: 0.3 -// } - MapItemView { + id: mapItemView model: afvMapReader.atcStationModel delegate: atcDelegate } @@ -323,6 +362,30 @@ ApplicationWindow { anchors.verticalCenter: map.verticalCenter anchors.horizontalCenter: map.horizontalCenter } + + Button { + id: btZoomIn + width: 30 + height: 30 + text: "+" + anchors.right: parent.right + anchors.rightMargin: 20 + anchors.bottom: btZoomOut.top + anchors.bottomMargin: 5 + onClicked: map.zoomLevel = map.zoomLevel + 1 + } + + Button { + id: btZoomOut + width: 30 + height: 30 + text: "-" + anchors.right: parent.right + anchors.rightMargin: 20 + anchors.bottom: parent.bottom + anchors.bottomMargin: 20 + onClicked: map.zoomLevel = map.zoomLevel - 1 + } } Timer { diff --git a/src/blackcore/afv/clients/afvclient.cpp b/src/blackcore/afv/clients/afvclient.cpp index d4659dc00..12483d54d 100644 --- a/src/blackcore/afv/clients/afvclient.cpp +++ b/src/blackcore/afv/clients/afvclient.cpp @@ -44,6 +44,12 @@ namespace BlackCore { 1, 122800000, 48.5, 11.5, 1000.0, 1000.0 } }; + m_enabledTransceivers = + { + { 0 }, + { 1 } + }; + qDebug() << "UserClient instantiated"; } @@ -61,11 +67,15 @@ namespace BlackCore m_callsign = callsign; m_connection->connectTo(cid, password, callsign); updateTransceivers(); + + if (m_connection->isConnected()) { emit connectionStatusChanged(Connected); } + else { emit connectionStatusChanged(Disconnected); } } void AFVClient::disconnectFrom() { m_connection->disconnectFrom(); + emit connectionStatusChanged(Disconnected); } QStringList AFVClient::availableInputDevices() const @@ -177,6 +187,14 @@ namespace BlackCore m_output->stop(); } + void AFVClient::enableTransceiver(quint16 id, bool enable) + { + if (enable) { m_enabledTransceivers.insert(id); } + else { m_enabledTransceivers.remove(id); } + + updateTransceivers(); + } + void AFVClient::updateComFrequency(quint16 id, quint32 frequency) { if (id != 0 && id != 1) { return; } @@ -203,6 +221,7 @@ namespace BlackCore transceiver.HeightAglM = height; transceiver.HeightMslM = height; } + updateTransceivers(); } void AFVClient::updateTransceivers() @@ -219,7 +238,15 @@ namespace BlackCore updateComFrequency(1, ownAircraft.getCom2System().getFrequencyActive().value(CFrequencyUnit::Hz())); } - m_connection->updateTransceivers(m_callsign, m_transceivers); + QVector enabledTransceivers; + for (const TransceiverDto &transceiver : m_transceivers) + { + if (m_enabledTransceivers.contains(transceiver.id)) + { + enabledTransceivers.push_back(transceiver); + } + } + m_connection->updateTransceivers(m_callsign, enabledTransceivers); if (soundcardSampleProvider) { @@ -388,6 +415,11 @@ namespace BlackCore // m_outputVolume = (float)System.Math.Pow(10, value / 20); // TODO outputSampleProvider.Volume = outputVolume; } + + AFVClient::ConnectionStatus AFVClient::getConnectionStatus() const + { + return m_connection->isConnected() ? Connected : Disconnected; + } } // ns } // ns } // ns diff --git a/src/blackcore/afv/clients/afvclient.h b/src/blackcore/afv/clients/afvclient.h index 073da4c7b..ede391094 100644 --- a/src/blackcore/afv/clients/afvclient.h +++ b/src/blackcore/afv/clients/afvclient.h @@ -40,10 +40,14 @@ namespace BlackCore Q_OBJECT Q_PROPERTY(float inputVolumePeakVU READ getInputVolumePeakVU NOTIFY inputVolumePeakVU) Q_PROPERTY(float outputVolumePeakVU READ getOutputVolumePeakVU NOTIFY outputVolumePeakVU) + Q_PROPERTY(ConnectionStatus connectionStatus READ getConnectionStatus NOTIFY connectionStatusChanged) Q_PROPERTY(QString receivingCallsignsCom1 READ getReceivingCallsignsCom1 NOTIFY receivingCallsignsChanged) Q_PROPERTY(QString receivingCallsignsCom2 READ getReceivingCallsignsCom2 NOTIFY receivingCallsignsChanged) public: + enum ConnectionStatus { Disconnected, Connected }; + Q_ENUM(ConnectionStatus) + //! Ctor AFVClient(const QString &apiServer, QObject *parent = nullptr); @@ -65,7 +69,7 @@ namespace BlackCore Q_INVOKABLE QStringList availableInputDevices() const; Q_INVOKABLE QStringList availableOutputDevices() const; - void setBypassEffects(bool value); + Q_INVOKABLE void setBypassEffects(bool value); bool isStarted() const { return m_isStarted; } QDateTime getStartDateTimeUt() const { return m_startDateTimeUtc; } @@ -74,15 +78,16 @@ namespace BlackCore Q_INVOKABLE void start(const QString &inputDeviceName, const QString &outputDeviceName); void stop(); + Q_INVOKABLE void enableTransceiver(quint16 id, bool enable); Q_INVOKABLE void updateComFrequency(quint16 id, quint32 frequency); Q_INVOKABLE void updatePosition(double latitude, double longitude, double height); void setTransmittingTransceivers(quint16 transceiverID); void setTransmittingTransceivers(const QVector &transceivers); - void setPtt(bool active); + Q_INVOKABLE void setPtt(bool active); - void setLoopBack(bool on) { m_loopbackOn = on; } + Q_INVOKABLE void setLoopBack(bool on) { m_loopbackOn = on; } float inputVolumeDb() const { @@ -97,10 +102,13 @@ namespace BlackCore float getInputVolumePeakVU() const { return m_inputVolumeStream.PeakVU; } float getOutputVolumePeakVU() const { return m_outputVolumeStream.PeakVU; } + ConnectionStatus getConnectionStatus() const; + signals: void receivingCallsignsChanged(const Audio::TransceiverReceivingCallsignsChangedArgs &args); void inputVolumePeakVU(float value); void outputVolumePeakVU(float value); + void connectionStatusChanged(ConnectionStatus status); private: void opusDataAvailable(const Audio::OpusDataAvailableArgs &args); @@ -146,6 +154,7 @@ namespace BlackCore QTimer m_voiceServerPositionTimer; QVector m_transceivers; + QSet m_enabledTransceivers; Audio::InputVolumeStreamArgs m_inputVolumeStream; Audio::OutputVolumeStreamArgs m_outputVolumeStream;