From 8e55a8c4e611a7ae2669b14e67071fa6d65d7aa0 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Thu, 12 Feb 2026 09:36:55 +0000 Subject: [PATCH] Freq Scanner: Don't unmute manually muted channels. #2636 --- plugins/channelrx/freqscanner/freqscanner.cpp | 73 +++++++++++++++++-- plugins/channelrx/freqscanner/freqscanner.h | 6 +- .../channelrx/freqscanner/freqscannergui.cpp | 26 ++++++- .../channelrx/freqscanner/freqscannergui.h | 1 + sdrbase/channel/channelwebapiutils.cpp | 32 ++++++++ sdrbase/channel/channelwebapiutils.h | 1 + 6 files changed, 129 insertions(+), 10 deletions(-) diff --git a/plugins/channelrx/freqscanner/freqscanner.cpp b/plugins/channelrx/freqscanner/freqscanner.cpp index f7d9cedc9..0228d18f8 100644 --- a/plugins/channelrx/freqscanner/freqscanner.cpp +++ b/plugins/channelrx/freqscanner/freqscanner.cpp @@ -240,7 +240,7 @@ bool FreqScanner::handleMessage(const Message& cmd) } else if (MsgStartScan::match(cmd)) { - muteAll(m_settings); + muteAll(); startScan(); return true; @@ -248,6 +248,7 @@ bool FreqScanner::handleMessage(const Message& cmd) else if (MsgStopScan::match(cmd)) { stopScan(); + unmuteAll(); return true; } @@ -304,7 +305,7 @@ void FreqScanner::initScan() // if (m_scanChannelIndex < 0) { // Always false // applyChannelSetting(m_settings.m_channel); // } - ChannelWebAPIUtils::setAudioMute(m_scanDeviceSetIndex, m_scanChannelIndex, true); + mute(m_scanDeviceSetIndex, m_scanChannelIndex); if (m_centerFrequency != m_stepStartFrequency) { setDeviceCenterFrequency(m_stepStartFrequency); @@ -529,7 +530,7 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList< ChannelWebAPIUtils::setFrequencyOffset(m_scanDeviceSetIndex, m_scanChannelIndex, offset + m_settings.m_channelShift); // Unmute the channel - ChannelWebAPIUtils::setAudioMute(m_scanDeviceSetIndex, m_scanChannelIndex, false); + unmute(m_scanDeviceSetIndex, m_scanChannelIndex); // Apply squelch if (!activeFrequencySettings->m_squelch.isEmpty()) @@ -706,30 +707,86 @@ void FreqScanner::setCenterFrequency(qint64 frequency) } } +// Ensure a channel is muted and remember if we muted it, as opposed to user having manually muted it +void FreqScanner::mute(unsigned int deviceSetIndex, unsigned int channelIndex) +{ + QString channel = QString("R%1:%2").arg(deviceSetIndex).arg(channelIndex); + + if (m_autoMutedChannels.contains(channel) && (m_autoMutedChannels[channel] == true)) { + return; // Already muted + } + + bool muted = false; + if (ChannelWebAPIUtils::getAudioMute(deviceSetIndex, channelIndex, muted)) + { + if (!muted) + { + ChannelWebAPIUtils::setAudioMute(deviceSetIndex, channelIndex, true); + m_autoMutedChannels.insert(channel, true); + } + else + { + m_autoMutedChannels.insert(channel, false); + } + } +} + +// Unmute channel if it was auto-muted +void FreqScanner::unmute(unsigned int deviceSetIndex, unsigned int channelIndex) +{ + QString channel = QString("R%1:%2").arg(deviceSetIndex).arg(channelIndex); + bool autoMuted = m_autoMutedChannels[channel]; + + if (autoMuted) + { + ChannelWebAPIUtils::setAudioMute(deviceSetIndex, channelIndex, false); + m_autoMutedChannels.insert(channel, false); + } +} + // Mute all channels -void FreqScanner::muteAll(const FreqScannerSettings& settings) +void FreqScanner::muteAll() { QStringList channels; - channels.append(settings.m_channel); - for (int i = 0; i < settings.m_frequencySettings.size(); i++) + channels.append(m_settings.m_channel); + for (int i = 0; i < m_settings.m_frequencySettings.size(); i++) { - QString channel = settings.m_frequencySettings[i].m_channel; + QString channel = m_settings.m_frequencySettings[i].m_channel; if (!channel.isEmpty() && !channels.contains(channel)) { channels.append(channel); } } + m_autoMutedChannels.clear(); for (const auto& channel : channels) { unsigned int deviceSetIndex, channelIndex; if (MainCore::getDeviceAndChannelIndexFromId(channel, deviceSetIndex, channelIndex)) { - ChannelWebAPIUtils::setAudioMute(deviceSetIndex, channelIndex, true); + mute(deviceSetIndex, channelIndex); } } } +// Unmute all channels that were auto-muted +void FreqScanner::unmuteAll() +{ + for (auto it = m_autoMutedChannels.begin(); it != m_autoMutedChannels.end(); ++it) + { + QString channel = it.key(); + bool autoMuted = it.value(); + if (autoMuted) + { + unsigned int deviceSetIndex, channelIndex; + if (MainCore::getDeviceAndChannelIndexFromId(channel, deviceSetIndex, channelIndex)) { + unmute(deviceSetIndex, channelIndex); + } + } + } + m_autoMutedChannels.clear(); +} + void FreqScanner::applyChannelSetting(const QString& channel) { if (!MainCore::getDeviceAndChannelIndexFromId(channel, m_scanDeviceSetIndex, m_scanChannelIndex)) { diff --git a/plugins/channelrx/freqscanner/freqscanner.h b/plugins/channelrx/freqscanner/freqscanner.h index 39c55e9ac..6cea330d6 100644 --- a/plugins/channelrx/freqscanner/freqscanner.h +++ b/plugins/channelrx/freqscanner/freqscanner.h @@ -363,7 +363,6 @@ public: uint32_t getNumberOfDeviceStreams() const; void calcScannerSampleRate(int channelBW, int basebandSampleRate, int& scannerSampleRate, int& fftSize, int& binsPerChannel); - static void muteAll(const FreqScannerSettings& settings); static const char * const m_channelIdURI; static const char * const m_channelId; @@ -404,6 +403,7 @@ private: } m_state; QTimer m_timeoutTimer; + QHash m_autoMutedChannels; // Whether we have muted this channel virtual bool handleMessage(const Message& cmd); void applySettings(const FreqScannerSettings& settings, const QStringList& settingsKeys, bool force = false); @@ -424,6 +424,10 @@ private: void processScanResults(const QDateTime& fftStartTime, const QList& results); void setDeviceCenterFrequency(qint64 frequency); void applyChannelSetting(const QString& channel); + void muteAll(); + void unmuteAll(); + void mute(unsigned int deviceSetIndex, unsigned int channelIndex); + void unmute(unsigned int deviceSetIndex, unsigned int channelIndex); static QList *createFrequencyList(const FreqScannerSettings& settings); diff --git a/plugins/channelrx/freqscanner/freqscannergui.cpp b/plugins/channelrx/freqscanner/freqscannergui.cpp index 2dc1a39c1..cf9b2e616 100644 --- a/plugins/channelrx/freqscanner/freqscannergui.cpp +++ b/plugins/channelrx/freqscanner/freqscannergui.cpp @@ -1052,6 +1052,30 @@ void FreqScannerGUI::setAllEnabled(bool enable) } } +// Mute all channels +void FreqScannerGUI::muteAll() +{ + QStringList channels; + + channels.append(m_settings.m_channel); + for (int i = 0; i < m_settings.m_frequencySettings.size(); i++) + { + QString channel = m_settings.m_frequencySettings[i].m_channel; + if (!channel.isEmpty() && !channels.contains(channel)) { + channels.append(channel); + } + } + + for (const auto& channel : channels) + { + unsigned int deviceSetIndex, channelIndex; + + if (MainCore::getDeviceAndChannelIndexFromId(channel, deviceSetIndex, channelIndex)) { + ChannelWebAPIUtils::setAudioMute(deviceSetIndex, channelIndex, true); + } + } +} + void FreqScannerGUI::table_customContextMenuRequested(QPoint pos) { QTableWidgetItem* item = ui->table->itemAt(pos); @@ -1120,7 +1144,7 @@ void FreqScannerGUI::table_customContextMenuRequested(QPoint pos) } // Mute all channels - m_freqScanner->muteAll(m_settings); + muteAll(); // Tune to frequency if ((frequency - m_settings.m_channelBandwidth / 2 < m_deviceCenterFrequency - m_basebandSampleRate / 2) diff --git a/plugins/channelrx/freqscanner/freqscannergui.h b/plugins/channelrx/freqscanner/freqscannergui.h index cafa7e0e9..6cbc08553 100644 --- a/plugins/channelrx/freqscanner/freqscannergui.h +++ b/plugins/channelrx/freqscanner/freqscannergui.h @@ -102,6 +102,7 @@ private: void updateChannelsCombo(QComboBox *combo, const AvailableChannelOrFeatureList& channels, const QString& channel, bool empty); void updateChannelsList(const AvailableChannelOrFeatureList& channels, const QStringList& renameFrom, const QStringList& renameTo); void setAllEnabled(bool enable); + void muteAll(); void leaveEvent(QEvent*); void enterEvent(EnterEventType*); diff --git a/sdrbase/channel/channelwebapiutils.cpp b/sdrbase/channel/channelwebapiutils.cpp index a5d49cee5..ec34ea163 100644 --- a/sdrbase/channel/channelwebapiutils.cpp +++ b/sdrbase/channel/channelwebapiutils.cpp @@ -966,6 +966,38 @@ bool ChannelWebAPIUtils::setFrequencyOffset(unsigned int deviceIndex, int channe return false; } +bool ChannelWebAPIUtils::getAudioMute(unsigned int deviceIndex, int channelIndex, bool& mute) +{ + SWGSDRangel::SWGChannelSettings channelSettingsResponse; + QString errorResponse; + int httpRC; + QJsonObject* jsonObj; + + ChannelAPI* channel = MainCore::instance()->getChannel(deviceIndex, channelIndex); + if (channel != nullptr) + { + httpRC = channel->webapiSettingsGet(channelSettingsResponse, errorResponse); + if (httpRC / 100 != 2) + { + qWarning("ChannelWebAPIUtils::getAudioMute: get channel settings error %d: %s", + httpRC, qPrintable(errorResponse)); + return false; + } + + jsonObj = channelSettingsResponse.asJsonObject(); + + int muteInt; + if (WebAPIUtils::getSubObjectInt(*jsonObj, "audioMute", muteInt)) + { + mute = (bool) muteInt; + delete jsonObj; + return true; + } + delete jsonObj; + } + return false; +} + bool ChannelWebAPIUtils::setAudioMute(unsigned int deviceIndex, int channelIndex, bool mute) { SWGSDRangel::SWGChannelSettings channelSettingsResponse; diff --git a/sdrbase/channel/channelwebapiutils.h b/sdrbase/channel/channelwebapiutils.h index c2dd35f2a..a13c9b24d 100644 --- a/sdrbase/channel/channelwebapiutils.h +++ b/sdrbase/channel/channelwebapiutils.h @@ -91,6 +91,7 @@ public: static bool stop(unsigned int deviceIndex, int subsystemIndex=0); static bool getFrequencyOffset(unsigned int deviceIndex, int channelIndex, int& offset); static bool setFrequencyOffset(unsigned int deviceIndex, int channelIndex, int offset); + static bool getAudioMute(unsigned int deviceIndex, int channelIndex, bool& mute); static bool setAudioMute(unsigned int deviceIndex, int channelIndex, bool mute); static bool startStopFileSinks(unsigned int deviceIndex, bool start); static bool satelliteAOS(const QString name, bool northToSouthPass, const QString &tle, QDateTime dateTime);