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
This commit is contained in:
Roland Rossgotterer
2019-09-19 16:36:22 +02:00
committed by Mat Sutcliffe
parent 852247e893
commit acb5b11966
4 changed files with 156 additions and 47 deletions

View File

@@ -3,8 +3,11 @@ import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12 import QtQuick.Controls 2.12
Row { Row {
id: idTransceiver
property int transceiverId: 0 property int transceiverId: 0
property alias frequency: sbFrequency.value property alias frequency: sbFrequency.value
property alias rxOn: cbEnabled.checked
property alias txOn: cbTxOn.checked
spacing: 10 spacing: 10
Label { Label {
@@ -62,6 +65,7 @@ Row {
text: qsTr("TX") text: qsTr("TX")
checked: true checked: true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
onClicked: idTransceiver.txOnChanged(checked)
} }
CheckBox { CheckBox {
@@ -70,5 +74,6 @@ Row {
text: qsTr("Enabled") text: qsTr("Enabled")
checked: true checked: true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
onClicked: idTransceiver.rxOnChanged(checked)
} }
} }

View File

@@ -7,13 +7,13 @@ import QtPositioning 5.12
ApplicationWindow { ApplicationWindow {
id: window id: window
width: 1200 width: 1200
height: 520 height: 800
visible: true visible: true
title: "Audio For Vatsim" title: "Audio For Vatsim"
Plugin { Plugin {
id: mapPlugin id: mapPlugin
name: "osm" // "mapboxgl", "esri", ... name: "osm"
} }
Grid { Grid {
@@ -42,6 +42,7 @@ ApplicationWindow {
height: 25 height: 25
text: qsTr("1234567") text: qsTr("1234567")
selectByMouse: true selectByMouse: true
enabled: voiceClient.connectionStatus == 0 // Disconnected
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@@ -61,6 +62,7 @@ ApplicationWindow {
height: 25 height: 25
text: qsTr("123456") text: qsTr("123456")
selectByMouse: true selectByMouse: true
enabled: voiceClient.connectionStatus == 0 // Disconnected
echoMode: TextInput.PasswordEchoOnEdit echoMode: TextInput.PasswordEchoOnEdit
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
renderType: Text.NativeRendering renderType: Text.NativeRendering
@@ -81,6 +83,7 @@ ApplicationWindow {
height: 25 height: 25
text: qsTr("DECHK") text: qsTr("DECHK")
selectByMouse: true selectByMouse: true
enabled: voiceClient.connectionStatus == 0 // Disconnected
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@@ -129,23 +132,16 @@ ApplicationWindow {
Button { Button {
id: btConnect id: btConnect
property bool connected: false
width: 170 width: 170
height: 25 height: 25
text: qsTr("Connect") text: voiceClient.connectionStatus == 0 ? "Connect" : "Disconnect"
onClicked: { onClicked: {
if (btConnect.connected) { if (voiceClient.connectionStatus == 0) {
btConnect.connected = false;
btConnect.text = qsTr("Connect")
voiceClient.disconnectFrom()
} else {
btConnect.connected = true
btConnect.text = qsTr("Disconnect")
voiceClient.connectTo(tfUsername.text, tfPassword.text, tfCallsign.text) voiceClient.connectTo(tfUsername.text, tfPassword.text, tfCallsign.text)
afvMapReader.setOwnCallsign(tfCallsign.text) afvMapReader.setOwnCallsign(tfCallsign.text)
} else if (voiceClient.connectionStatus == 1) {
voiceClient.disconnectFrom()
} }
} }
} }
@@ -173,10 +169,16 @@ ApplicationWindow {
anchors.left: leftGrid.right anchors.left: leftGrid.right
anchors.right: parent.right anchors.right: parent.right
spacing: 10 spacing: 10
rows: 2 rows: 3
columns: 3 columns: 3
Transceiver { id: transceiver1; transceiverId: 0 } Transceiver {
id: transceiver1
transceiverId: 0
onRxOnChanged: {
voiceClient.enableTransceiver(transceiverId, enabled)
}
}
SpinBox { SpinBox {
id: sbAltitude id: sbAltitude
@@ -191,11 +193,18 @@ ApplicationWindow {
Label { Label {
id: lblReceivingCom1 id: lblReceivingCom1
height: 40 height: 40
text: qsTr("Receiving:") text: qsTr("Receiving: ") + voiceClient.receivingCallsignsCom1
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
Transceiver { id: transceiver2; transceiverId: 1 } Transceiver {
id: transceiver2
transceiverId: 1
txOn: false
onRxOnChanged: {
voiceClient.enableTransceiver(transceiverId, enabled)
}
}
Button { Button {
id: btUpdateStack id: btUpdateStack
@@ -206,14 +215,13 @@ ApplicationWindow {
voiceClient.updateComFrequency(0, transceiver1.frequency * 1000) voiceClient.updateComFrequency(0, transceiver1.frequency * 1000)
voiceClient.updateComFrequency(1, transceiver2.frequency * 1000) voiceClient.updateComFrequency(1, transceiver2.frequency * 1000)
voiceClient.updatePosition(map.center.latitude, map.center.longitude, sbAltitude.value) voiceClient.updatePosition(map.center.latitude, map.center.longitude, sbAltitude.value)
voiceClient.updateTransceivers()
} }
} }
Label { Label {
id: lblReceivingCom2 id: lblReceivingCom2
height: 40 height: 40
text: qsTr("Receiving:") text: qsTr("Receiving: ") + voiceClient.receivingCallsignsCom2
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
// anchors.verticalCenter: parent.verticalCenter // anchors.verticalCenter: parent.verticalCenter
} }
@@ -221,7 +229,6 @@ ApplicationWindow {
Column { Column {
id: column id: column
padding: 10
spacing: 10 spacing: 10
anchors.top: rightGrid.bottom anchors.top: rightGrid.bottom
anchors.left: leftGrid.right anchors.left: leftGrid.right
@@ -246,17 +253,60 @@ ApplicationWindow {
} }
} }
//// CheckBox { Row {
//// id: cbVhfEffects padding: 0
//// anchors.topMargin: 5 spacing: 10
//// anchors.leftMargin: 10 anchors.top: column.bottom
//// anchors.left: sbAltitude.right anchors.left: leftGrid.right
//// anchors.top: parent.top anchors.right: parent.right
//// anchors.verticalCenter: sbAltitude.verticalCenter
//// height: 25 CheckBox {
//// text: qsTr("VHF Effects") id: cbVhfEffects
//// checked: true 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 { Map {
id: map id: map
@@ -269,19 +319,8 @@ ApplicationWindow {
center: QtPositioning.coordinate(48.50, 11.50) // Oslo center: QtPositioning.coordinate(48.50, 11.50) // Oslo
zoomLevel: 3 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 { MapItemView {
id: mapItemView
model: afvMapReader.atcStationModel model: afvMapReader.atcStationModel
delegate: atcDelegate delegate: atcDelegate
} }
@@ -323,6 +362,30 @@ ApplicationWindow {
anchors.verticalCenter: map.verticalCenter anchors.verticalCenter: map.verticalCenter
anchors.horizontalCenter: map.horizontalCenter 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 { Timer {

View File

@@ -44,6 +44,12 @@ namespace BlackCore
{ 1, 122800000, 48.5, 11.5, 1000.0, 1000.0 } { 1, 122800000, 48.5, 11.5, 1000.0, 1000.0 }
}; };
m_enabledTransceivers =
{
{ 0 },
{ 1 }
};
qDebug() << "UserClient instantiated"; qDebug() << "UserClient instantiated";
} }
@@ -61,11 +67,15 @@ namespace BlackCore
m_callsign = callsign; m_callsign = callsign;
m_connection->connectTo(cid, password, callsign); m_connection->connectTo(cid, password, callsign);
updateTransceivers(); updateTransceivers();
if (m_connection->isConnected()) { emit connectionStatusChanged(Connected); }
else { emit connectionStatusChanged(Disconnected); }
} }
void AFVClient::disconnectFrom() void AFVClient::disconnectFrom()
{ {
m_connection->disconnectFrom(); m_connection->disconnectFrom();
emit connectionStatusChanged(Disconnected);
} }
QStringList AFVClient::availableInputDevices() const QStringList AFVClient::availableInputDevices() const
@@ -177,6 +187,14 @@ namespace BlackCore
m_output->stop(); 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) void AFVClient::updateComFrequency(quint16 id, quint32 frequency)
{ {
if (id != 0 && id != 1) { return; } if (id != 0 && id != 1) { return; }
@@ -203,6 +221,7 @@ namespace BlackCore
transceiver.HeightAglM = height; transceiver.HeightAglM = height;
transceiver.HeightMslM = height; transceiver.HeightMslM = height;
} }
updateTransceivers();
} }
void AFVClient::updateTransceivers() void AFVClient::updateTransceivers()
@@ -219,7 +238,15 @@ namespace BlackCore
updateComFrequency(1, ownAircraft.getCom2System().getFrequencyActive().value(CFrequencyUnit::Hz())); updateComFrequency(1, ownAircraft.getCom2System().getFrequencyActive().value(CFrequencyUnit::Hz()));
} }
m_connection->updateTransceivers(m_callsign, m_transceivers); QVector<TransceiverDto> 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) if (soundcardSampleProvider)
{ {
@@ -388,6 +415,11 @@ namespace BlackCore
// m_outputVolume = (float)System.Math.Pow(10, value / 20); // m_outputVolume = (float)System.Math.Pow(10, value / 20);
// TODO outputSampleProvider.Volume = outputVolume; // TODO outputSampleProvider.Volume = outputVolume;
} }
AFVClient::ConnectionStatus AFVClient::getConnectionStatus() const
{
return m_connection->isConnected() ? Connected : Disconnected;
}
} // ns } // ns
} // ns } // ns
} // ns } // ns

View File

@@ -40,10 +40,14 @@ namespace BlackCore
Q_OBJECT Q_OBJECT
Q_PROPERTY(float inputVolumePeakVU READ getInputVolumePeakVU NOTIFY inputVolumePeakVU) Q_PROPERTY(float inputVolumePeakVU READ getInputVolumePeakVU NOTIFY inputVolumePeakVU)
Q_PROPERTY(float outputVolumePeakVU READ getOutputVolumePeakVU NOTIFY outputVolumePeakVU) 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 receivingCallsignsCom1 READ getReceivingCallsignsCom1 NOTIFY receivingCallsignsChanged)
Q_PROPERTY(QString receivingCallsignsCom2 READ getReceivingCallsignsCom2 NOTIFY receivingCallsignsChanged) Q_PROPERTY(QString receivingCallsignsCom2 READ getReceivingCallsignsCom2 NOTIFY receivingCallsignsChanged)
public: public:
enum ConnectionStatus { Disconnected, Connected };
Q_ENUM(ConnectionStatus)
//! Ctor //! Ctor
AFVClient(const QString &apiServer, QObject *parent = nullptr); AFVClient(const QString &apiServer, QObject *parent = nullptr);
@@ -65,7 +69,7 @@ namespace BlackCore
Q_INVOKABLE QStringList availableInputDevices() const; Q_INVOKABLE QStringList availableInputDevices() const;
Q_INVOKABLE QStringList availableOutputDevices() const; Q_INVOKABLE QStringList availableOutputDevices() const;
void setBypassEffects(bool value); Q_INVOKABLE void setBypassEffects(bool value);
bool isStarted() const { return m_isStarted; } bool isStarted() const { return m_isStarted; }
QDateTime getStartDateTimeUt() const { return m_startDateTimeUtc; } QDateTime getStartDateTimeUt() const { return m_startDateTimeUtc; }
@@ -74,15 +78,16 @@ namespace BlackCore
Q_INVOKABLE void start(const QString &inputDeviceName, const QString &outputDeviceName); Q_INVOKABLE void start(const QString &inputDeviceName, const QString &outputDeviceName);
void stop(); void stop();
Q_INVOKABLE void enableTransceiver(quint16 id, bool enable);
Q_INVOKABLE void updateComFrequency(quint16 id, quint32 frequency); Q_INVOKABLE void updateComFrequency(quint16 id, quint32 frequency);
Q_INVOKABLE void updatePosition(double latitude, double longitude, double height); Q_INVOKABLE void updatePosition(double latitude, double longitude, double height);
void setTransmittingTransceivers(quint16 transceiverID); void setTransmittingTransceivers(quint16 transceiverID);
void setTransmittingTransceivers(const QVector<TxTransceiverDto> &transceivers); void setTransmittingTransceivers(const QVector<TxTransceiverDto> &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 float inputVolumeDb() const
{ {
@@ -97,10 +102,13 @@ namespace BlackCore
float getInputVolumePeakVU() const { return m_inputVolumeStream.PeakVU; } float getInputVolumePeakVU() const { return m_inputVolumeStream.PeakVU; }
float getOutputVolumePeakVU() const { return m_outputVolumeStream.PeakVU; } float getOutputVolumePeakVU() const { return m_outputVolumeStream.PeakVU; }
ConnectionStatus getConnectionStatus() const;
signals: signals:
void receivingCallsignsChanged(const Audio::TransceiverReceivingCallsignsChangedArgs &args); void receivingCallsignsChanged(const Audio::TransceiverReceivingCallsignsChangedArgs &args);
void inputVolumePeakVU(float value); void inputVolumePeakVU(float value);
void outputVolumePeakVU(float value); void outputVolumePeakVU(float value);
void connectionStatusChanged(ConnectionStatus status);
private: private:
void opusDataAvailable(const Audio::OpusDataAvailableArgs &args); void opusDataAvailable(const Audio::OpusDataAvailableArgs &args);
@@ -146,6 +154,7 @@ namespace BlackCore
QTimer m_voiceServerPositionTimer; QTimer m_voiceServerPositionTimer;
QVector<TransceiverDto> m_transceivers; QVector<TransceiverDto> m_transceivers;
QSet<quint16> m_enabledTransceivers;
Audio::InputVolumeStreamArgs m_inputVolumeStream; Audio::InputVolumeStreamArgs m_inputVolumeStream;
Audio::OutputVolumeStreamArgs m_outputVolumeStream; Audio::OutputVolumeStreamArgs m_outputVolumeStream;