diff --git a/samples/afvclient/qml/LevelMeter.qml b/samples/afvclient/qml/LevelMeter.qml
new file mode 100644
index 000000000..f7a54df16
--- /dev/null
+++ b/samples/afvclient/qml/LevelMeter.qml
@@ -0,0 +1,84 @@
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+
+Item {
+ id: levelMeter
+
+ property double value: 0.97
+ property double peak: 0.0
+
+ width: 400
+ height: 20
+
+ onValueChanged: {
+ if(value < 0.0) {
+ value = 0.0
+ } else if (value > 1.0) {
+ value = 1.0;
+ }
+ if (value > peak) {
+ peak = value;
+ peakTimer.start()
+ }
+ }
+
+ Row {
+ anchors.fill: parent
+
+ Rectangle {
+ id: lowRangeDark
+ width: levelMeter.width * 0.68
+ height: parent.height
+ color: "#002366"
+
+ Rectangle {
+ id: lowRange
+ width: Math.min(lowRangeDark.width, value * levelMeter.width)
+ height: parent.height
+ color: "#4169E1"
+ }
+ }
+
+ Rectangle {
+ id: midRangeDark
+ width: levelMeter.width * 0.22
+ height: parent.height
+ color: "#114911"
+
+ Rectangle {
+ id: midRange
+ width: Math.min(midRangeDark.width, (value * levelMeter.width) - lowRangeDark.width)
+ height: parent.height
+ color: "#32CD32"
+ }
+ }
+
+ Rectangle {
+ id: highRangeDark
+ width: levelMeter.width * 0.1
+ height: parent.height
+ color: "#760e0e"
+
+ Rectangle {
+ id: highRange
+ width: Math.min(highRangeDark.width, (value * levelMeter.width) - lowRangeDark.width - midRangeDark.width)
+ height: parent.height
+ color: "#FF4500"
+ }
+ }
+ }
+
+ Rectangle {
+ id: peakBar
+ width: 3
+ height: parent.height
+ color: "#3edd9f"
+ x: peak * levelMeter.width
+ }
+
+ Timer {
+ id: peakTimer
+ onTriggered: peak = 0
+ }
+}
diff --git a/samples/afvclient/qml/Transceiver.qml b/samples/afvclient/qml/Transceiver.qml
index 0bba44095..6bc9d7f84 100644
--- a/samples/afvclient/qml/Transceiver.qml
+++ b/samples/afvclient/qml/Transceiver.qml
@@ -42,21 +42,7 @@ Row {
valueFromText: function(text, locale) {
return Number.fromLocaleString(locale, text) * 1000
}
-
- MouseArea {
- anchors.fill: parent
- onWheel: {
- if (wheel.angleDelta.y > 0)
- {
- sbFrequency.value += sbFrequency.stepSize
- }
- else
- {
- sbFrequency.value -= sbFrequency.stepSize
- }
- wheel.accepted=true
- }
- }
+ wheelEnabled: true
}
CheckBox {
@@ -71,7 +57,7 @@ Row {
CheckBox {
id: cbEnabled
height: 25
- text: qsTr("Enabled")
+ text: qsTr("RX")
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 6e6bab3bf..71a569da4 100644
--- a/samples/afvclient/qml/main.qml
+++ b/samples/afvclient/qml/main.qml
@@ -18,6 +18,8 @@ ApplicationWindow {
Grid {
id: leftGrid
+ anchors.bottom: column.bottom
+ anchors.bottomMargin: 0
columns: 2
rows: 6
spacing: 10
@@ -164,10 +166,11 @@ ApplicationWindow {
Grid {
id: rightGrid
- padding: 10
+ padding: 0
anchors.top: parent.top
anchors.left: leftGrid.right
anchors.right: parent.right
+ anchors.topMargin: 10
spacing: 10
rows: 3
columns: 3
@@ -188,6 +191,7 @@ ApplicationWindow {
to: 50000
from: 0
value: 1000
+ wheelEnabled: true
}
Label {
@@ -229,89 +233,119 @@ ApplicationWindow {
Column {
id: column
- spacing: 10
+ spacing: 5
anchors.top: rightGrid.bottom
anchors.left: leftGrid.right
anchors.right: parent.right
- ProgressBar {
- id: pbAudioInput
- width: 500
- height: 25
- anchors.left: parent.left
- anchors.leftMargin: 10
- value: voiceClient.inputVolumePeakVU
- }
+ Row {
+ id: row1
+ anchors.topMargin: 0
+ padding: 0
+ spacing: 10
- ProgressBar {
- id: pbAudioOutput
- width: 500
- height: 25
- anchors.left: parent.left
- anchors.leftMargin: 10
- value: voiceClient.outputVolumePeakVU
- }
- }
-
- 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"
- }
+ LevelMeter {
+ id: pbAudioInput
+ width: 400
+ height: 15
+ value: voiceClient.inputVolumePeakVU
+ anchors.verticalCenter: parent.verticalCenter
}
- id: lblStatus
- text: "Status: " + translateStatus(voiceClient.connectionStatus)
- verticalAlignment: Text.AlignVCenter
- anchors.verticalCenter: parent.verticalCenter
+ Slider {
+ id: slInputVolume
+ from: -18
+ to: 18
+ value: 0
+ anchors.verticalCenter: parent.verticalCenter
+ wheelEnabled: true
+ onMoved: voiceClient.setInputVolumeDb(value)
+ }
+ }
+
+ Row {
+ id: row2
+ anchors.topMargin: 0
+ padding: 0
+ spacing: 10
+
+ LevelMeter {
+ id: pbAudioOutput
+ width: 400
+ height: 15
+ value: voiceClient.outputVolumePeakVU
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Slider {
+ id: slOutputVolume
+ from: -18
+ to: 18
+ value: 0
+ anchors.verticalCenter: parent.verticalCenter
+ wheelEnabled: true
+ onMoved: voiceClient.setOutputVolumeDb(value)
+ }
+ }
+
+ Row {
+ id: row3
+ padding: 0
+ spacing: 10
+
+ 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
anchors.topMargin: 5
- anchors.top: leftGrid.bottom
+ anchors.top: column.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
diff --git a/samples/afvclient/qml/qml.qrc b/samples/afvclient/qml/qml.qrc
index 890755567..367b6f080 100644
--- a/samples/afvclient/qml/qml.qrc
+++ b/samples/afvclient/qml/qml.qrc
@@ -3,5 +3,6 @@
main.qml
AtcRing.qml
Transceiver.qml
+ LevelMeter.qml
diff --git a/src/blackcore/afv/clients/afvclient.cpp b/src/blackcore/afv/clients/afvclient.cpp
index 0a71d14c7..5105e17b4 100644
--- a/src/blackcore/afv/clients/afvclient.cpp
+++ b/src/blackcore/afv/clients/afvclient.cpp
@@ -50,6 +50,11 @@ namespace BlackCore
{ 1 }
};
+ m_transmittingTransceivers =
+ {
+ { 0 }
+ };
+
qDebug() << "UserClient instantiated";
}
@@ -406,7 +411,7 @@ namespace BlackCore
updateTransceivers();
}
- float AFVClient::getOutputVolumeDb() const
+ double AFVClient::getOutputVolumeDb() const
{
return m_outputVolume;
}
diff --git a/src/blackcore/afv/clients/afvclient.h b/src/blackcore/afv/clients/afvclient.h
index 05c674979..9c769ad9b 100644
--- a/src/blackcore/afv/clients/afvclient.h
+++ b/src/blackcore/afv/clients/afvclient.h
@@ -95,10 +95,10 @@ namespace BlackCore
return m_inputVolumeDb;
}
- void setInputVolumeDb(double value);
+ Q_INVOKABLE void setInputVolumeDb(double value);
- float getOutputVolumeDb() const;
- void setOutputVolumeDb(double outputVolume);
+ double getOutputVolumeDb() const;
+ Q_INVOKABLE void setOutputVolumeDb(double outputVolume);
float getInputVolumePeakVU() const { return m_inputVolumeStream.PeakVU; }
float getOutputVolumePeakVU() const { return m_outputVolumeStream.PeakVU; }