diff --git a/backend/NosonApp/player.cpp b/backend/NosonApp/player.cpp index 6ec3fdbeb..8fbf255cf 100644 --- a/backend/NosonApp/player.cpp +++ b/backend/NosonApp/player.cpp @@ -456,6 +456,13 @@ Future* Player::trySetBass(double val) return new Future(new PromiseSetBass(*this, val), m_sonos); } +Future* Player::trySetSubGain(double val) +{ + if (!m_sonos) + return nullptr; + return new Future(new PromiseSetSubGain(*this, val), m_sonos); +} + Future* Player::trySetVolumeGroup(double volume) { if (!m_sonos) @@ -976,6 +983,25 @@ bool Player::setBass(double val) } +bool Player::setSubGain(double val) +{ + SONOS::PlayerPtr p(m_player); + if (p) + { + bool ret = true; + for (RCTable::iterator it = m_RCTable.begin(); it != m_RCTable.end(); ++it) + { + if (p->SetSubGain(it->uuid, val)) + m_RCGroup.subGain = it->subGain = val; + else + ret = false; + } + return ret; + } + return false; + +} + bool Player::setVolumeGroup(double volume, bool forFake) { SONOS::PlayerPtr p(m_player); @@ -1323,6 +1349,7 @@ void Player::handleRenderingControlChange() item.volumeFake = it->property.VolumeMaster > 0 ? (double)it->property.VolumeMaster : 100.0 / 101.0; item.treble = it->property.Treble; item.bass = it->property.Bass; + item.subGain = it->property.SubGain; m_RCTable.push_back(item); if (!item.mute) mute = false; // exists active audio in group @@ -1341,6 +1368,7 @@ void Player::handleRenderingControlChange() m_RCGroup.loudness = item.loudness; m_RCGroup.treble = item.treble; m_RCGroup.bass = item.bass; + m_RCGroup.subGain = item.subGain; } ++it; @@ -1365,6 +1393,7 @@ void Player::handleRenderingControlChange() bool nightmode = false; bool loudness = false; int treble = 0, bass = 0; + int subGain = 0; SONOS::SRPList::const_iterator it = props.begin(); std::vector::iterator itz = m_RCTable.begin(); while (it != props.end()) @@ -1405,6 +1434,11 @@ void Player::handleRenderingControlChange() itz->bass = it->property.Bass; signalMask |= RENDERING_CHANGED; } + if (it->property.SubGain != itz->subGain) + { + itz->subGain = it->property.SubGain; + signalMask |= RENDERING_CHANGED; + } // As the sound settings relate the connected group and doesn't handle separately each subordinate, // i gatherer data from the master zone that is the first on the array. @@ -1414,6 +1448,7 @@ void Player::handleRenderingControlChange() loudness = LoudnessAsBool; treble = it->property.Treble; bass = it->property.Bass; + subGain = it->property.SubGain; } // And override data from the first subordinate updated accordinaly with sended values else @@ -1426,6 +1461,8 @@ void Player::handleRenderingControlChange() treble = it->property.Treble; if (it->property.Bass == m_RCGroup.bass) bass = it->property.Bass; + if (it->property.SubGain == m_RCGroup.subGain) + subGain = it->property.SubGain; } if (it->property.VolumeMaster != itz->volume) @@ -1476,6 +1513,7 @@ void Player::handleRenderingControlChange() m_RCGroup.loudness = loudness; m_RCGroup.treble = treble; m_RCGroup.bass = bass; + m_RCGroup.subGain = subGain; m_RCGroup.outputFixed = outputFixed; signalMask |= RENDERING_GROUP_CHANGED; // handles group update } @@ -1783,6 +1821,12 @@ void Player::PromiseSetBass::run() setResult(QVariant(r)); } +void Player::PromiseSetSubGain::run() +{ + bool r = m_player.setSubGain(m_val); + setResult(QVariant(r)); +} + void Player::PromiseSetVolumeGroup::run() { bool r = m_player.setVolumeGroup(m_volume); diff --git a/backend/NosonApp/player.h b/backend/NosonApp/player.h index 9ee956bea..d62796644 100644 --- a/backend/NosonApp/player.h +++ b/backend/NosonApp/player.h @@ -45,6 +45,7 @@ class Player : public QObject, public ContentProvider Q_PROPERTY(int volumeMaster READ volumeMaster NOTIFY renderingGroupChanged) Q_PROPERTY(int treble READ treble NOTIFY renderingGroupChanged) Q_PROPERTY(int bass READ bass NOTIFY renderingGroupChanged) + Q_PROPERTY(int subGain READ subGain NOTIFY renderingGroupChanged) // Read only Q_PROPERTY(int pid READ pid NOTIFY connectedChanged) @@ -136,6 +137,7 @@ class Player : public QObject, public ContentProvider Q_INVOKABLE Future* trySetTreble(double val); Q_INVOKABLE Future* trySetBass(double val); + Q_INVOKABLE Future* trySetSubGain(double val); Q_INVOKABLE Future* trySetVolumeGroup(double volume); Q_INVOKABLE Future* trySetVolume(const QString& uuid, double volume); @@ -213,6 +215,7 @@ class Player : public QObject, public ContentProvider int volumeRF() const { return m_RCGroup.volume; } int treble() const { return m_RCGroup.treble; } int bass() const { return m_RCGroup.bass; } + int subGain() const { return m_RCGroup.subGain; } struct RCProperty { @@ -225,6 +228,7 @@ class Player : public QObject, public ContentProvider int volume = 0; int treble = 0; int bass = 0; + int subGain = 0; double volumeFake = 0.; }; @@ -234,6 +238,7 @@ class Player : public QObject, public ContentProvider Q_INVOKABLE bool setTreble(double val); Q_INVOKABLE bool setBass(double val); + Q_INVOKABLE bool setSubGain(double val); Q_INVOKABLE bool setVolumeGroup(double volume, bool forFake = false); Q_INVOKABLE bool setVolume(const QString& uuid, double volume, bool forFake = false); @@ -746,6 +751,17 @@ private slots: double m_val; }; + class PromiseSetSubGain : public Promise + { + public: + PromiseSetSubGain(Player& player, double val) + : m_player(player), m_val(val) { } + void run() override; + private: + Player& m_player; + double m_val; + }; + class PromiseSetVolumeGroup : public Promise { public: diff --git a/gui/controls2/components/Dialog/DialogSoundSettings.qml b/gui/controls2/components/Dialog/DialogSoundSettings.qml index 17c18eeb6..41f15722a 100644 --- a/gui/controls2/components/Dialog/DialogSoundSettings.qml +++ b/gui/controls2/components/Dialog/DialogSoundSettings.qml @@ -59,7 +59,7 @@ Item { font.pointSize: units.fs("medium") verticalAlignment: Text.AlignVCenter height: trebleSlider.height - width: units.gu(10) + width: units.gu(12) } StyledSlider { @@ -120,7 +120,7 @@ Item { spacing: 0 Item { id: c0 - width: units.gu(11) + width: units.gu(13) height: units.gu(1) } Label { @@ -160,7 +160,7 @@ Item { font.pointSize: units.fs("medium") verticalAlignment: Text.AlignVCenter height: bassSlider.height - width: units.gu(10) + width: units.gu(12) } StyledSlider { id: bassSlider @@ -213,6 +213,71 @@ Item { } } } + + Row { + width: parent.width + spacing: units.gu(1) + + Label { + id: subGainLabel + text: qsTr("Subwoofer") + color: styleMusic.dialog.labelColor + font.pointSize: units.fs("medium") + verticalAlignment: Text.AlignVCenter + height: subGainSlider.height + width: units.gu(12) + } + StyledSlider { + id: subGainSlider + live: true + from: -10 + to: 10 + wheelEnabled: true + orientation: Qt.Horizontal + handleSize: units.gu(2) + handleColor: styleMusic.playerControls.volumeHandleColor + handleColorPressed: styleMusic.playerControls.backgroundColor + handleBorderColor: handleColor + backgroundColor: styleMusic.playerControls.volumeBackgroundColor + foregroundColor: styleMusic.playerControls.volumeForegroundColor + size: parent.width - trebleLabel.width - parent.spacing - units.gu(1) + stepSize: 1.0 + + value: player.subGain // load value at startup + + Connections { + target: player + onSubGainChanged:{ + if (!subGainSlider.pressed) { + subGainSlider.value = player.subGain; + } + } + } + + onMoved: { + setSubGain.start(); + } + + Timer { + id: setSubGain + interval: 300 + property bool ready: true // false: delay the call + onTriggered: { + if (!ready) { + restart(); + } else { + ready = false; + player.setSubGain(Math.round(subGainSlider.value), function(result) { + ready = true; + if (!result) { + customdebug("Set subGain failed"); + } + }); + } + } + } + } + } } Row { diff --git a/gui/controls2/components/Player.qml b/gui/controls2/components/Player.qml index 1c8815626..efb824e1f 100644 --- a/gui/controls2/components/Player.qml +++ b/gui/controls2/components/Player.qml @@ -51,6 +51,7 @@ Item { property int volumeMaster: 0 property int bass: 0 property int treble: 0 + property int subGain: 0 property bool repeat: false property bool shuffle: false property bool mute: false @@ -211,6 +212,12 @@ Item { return future.start(false); } + function setSubGain(value, onFinished) { + var future = zone.handle.trySetSubGain(value) + future.onFinished.connect(onFinished); + return future.start(false); + } + function setBass(value, onFinished) { var future = zone.handle.trySetBass(value) future.onFinished.connect(onFinished); @@ -491,6 +498,7 @@ Item { player.volumeMaster = zone.handle.volumeMaster; player.treble = zone.handle.treble; player.bass = zone.handle.bass; + player.subGain = zone.handle.subGain; player.mute = zone.handle.muteMaster; player.nightmodeEnabled = zone.handle.nightmode; player.loudnessEnabled = zone.handle.loudness;