From e44af72b00938f015670ef364902a47a33ac9e04 Mon Sep 17 00:00:00 2001 From: vsonnier Date: Sat, 18 Nov 2017 22:38:05 +0100 Subject: [PATCH] Assure Gain control <==> Settings menu synchronization in case of mutually depdendent updates --- src/AppFrame.cpp | 4 -- src/CubicSDR.cpp | 6 ++- src/CubicSDR.h | 2 +- src/forms/SDRDevices/SDRDevices.cpp | 7 +-- src/sdr/SDRDeviceInfo.cpp | 21 +++++++++ src/sdr/SDRDeviceInfo.h | 4 ++ src/visual/GainCanvas.cpp | 70 ++++++++++++++++++++++++++++- src/visual/GainCanvas.h | 6 ++- 8 files changed, 108 insertions(+), 12 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 4864c0d..1926c96 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -941,7 +941,6 @@ void AppFrame::updateDeviceParams() { newSampleRateMenu->AppendSeparator(); sampleRateMenuItems[wxID_BANDWIDTH_MANUAL_DIALOG] = newSampleRateMenu->Append(wxID_BANDWIDTH_MANUAL_DIALOG, wxT("Manual Entry...")); - menuBar->Replace(2, newSampleRateMenu, wxT("Sample &Rate")); sampleRateMenu = newSampleRateMenu; @@ -950,9 +949,6 @@ void AppFrame::updateDeviceParams() { gainSizerItem->Show(true); gainSizerItem->SetMinSize(devInfo->getSoapyDevice()->listGains(SOAPY_SDR_RX,0).size()*50,0); demodTray->Layout(); - gainCanvas->updateGainUI(); - gainCanvas->Refresh(); - gainCanvas->Refresh(); } else { gainSpacerItem->Show(false); gainSizerItem->Show(false); diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index f4cb6aa..aface75 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -944,8 +944,12 @@ bool CubicSDR::areDevicesReady() { return devicesReady.load(); } -void CubicSDR::notifyMainUIOfDeviceChange() { +void CubicSDR::notifyMainUIOfDeviceChange(bool forceRefreshOfGains) { appframe->notifyDeviceChanged(); + + if (forceRefreshOfGains) { + appframe->refreshGainUI(); + } } bool CubicSDR::areDevicesEnumerating() { diff --git a/src/CubicSDR.h b/src/CubicSDR.h index c714ad7..798089e 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -143,7 +143,7 @@ public: bool areModulesMissing(); std::string getNotification(); - void notifyMainUIOfDeviceChange(); + void notifyMainUIOfDeviceChange(bool forceRefreshOfGains = false); void addRemote(std::string remoteAddr); void removeRemote(std::string remoteAddr); diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index ea50024..cabebee 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -395,7 +395,8 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event) { wxGetApp().setDeviceArgs(settingArgs); wxGetApp().setStreamArgs(streamArgs); wxGetApp().setDevice(dev,0); - wxGetApp().notifyMainUIOfDeviceChange(); + wxGetApp().notifyMainUIOfDeviceChange(true); + Refresh(); Close(); } event.Skip(); @@ -570,13 +571,13 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { wxGetApp().getSDRThread()->writeSetting(rtp->first, settingValue); } - wxGetApp().notifyMainUIOfDeviceChange(); + wxGetApp().notifyMainUIOfDeviceChange(true); return; } } } // general refresh. - wxGetApp().notifyMainUIOfDeviceChange(); + wxGetApp().notifyMainUIOfDeviceChange(true); } void SDRDevicesDialog::OnPropGridFocus( wxFocusEvent& /* event */) { diff --git a/src/sdr/SDRDeviceInfo.cpp b/src/sdr/SDRDeviceInfo.cpp index 6bf415b..2dbaf03 100644 --- a/src/sdr/SDRDeviceInfo.cpp +++ b/src/sdr/SDRDeviceInfo.cpp @@ -269,3 +269,24 @@ SDRRangeMap SDRDeviceInfo::getGains(int direction, size_t channel) { return gainMap; } + +//read the current gain of name gainName (must exit in getGains(), else return 0) +//in the device. +double SDRDeviceInfo::getCurrentGain(int direction, size_t channel, const std::string& gainName) { + + SoapySDR::Device *dev = getSoapyDevice(); + + if (dev) { + + std::vector gainNames = dev->listGains(direction, channel); + + auto itFoundName = std::find(gainNames.begin(), gainNames.end(), gainName); + + if (itFoundName != gainNames.end()) { + + return dev->getGain(direction, channel, gainName); + } + } + + return 0.0; +} diff --git a/src/sdr/SDRDeviceInfo.h b/src/sdr/SDRDeviceInfo.h index e5d9bc2..622d56f 100644 --- a/src/sdr/SDRDeviceInfo.h +++ b/src/sdr/SDRDeviceInfo.h @@ -92,6 +92,10 @@ public: SDRRangeMap getGains(int direction, size_t channel); + //read the current gain of name gainName (must exist in getGains(), else return 0) + //in the device. + double getCurrentGain(int direction, size_t channel, const std::string& gainName); + private: int index = 0; std::string name, serial, product, manufacturer, tuner; diff --git a/src/visual/GainCanvas.cpp b/src/visual/GainCanvas.cpp index c5a3bef..393fce7 100644 --- a/src/visual/GainCanvas.cpp +++ b/src/visual/GainCanvas.cpp @@ -69,13 +69,25 @@ void GainCanvas::OnIdle(wxIdleEvent &event) { } else { event.Skip(); } + + bool areGainsChangedHere = false; for (auto gi : gainPanels) { if (gi->getChanged()) { + areGainsChangedHere = true; wxGetApp().setGain(gi->getName(), gi->getValue()); + //A gain may be exposed as setting also so assure refresh of the menu also. + wxGetApp().notifyMainUIOfDeviceChange(false); //do not piggyback to us... + gi->setChanged(false); } } + + if (!areGainsChangedHere) { + if (updateGainValues()) { + Refresh(); + } + } } void GainCanvas::SetLevel() { @@ -167,8 +179,6 @@ void GainCanvas::OnMouseEnterWindow(wxMouseEvent& event) { #endif } - - void GainCanvas::setHelpTip(std::string tip) { helpTip = tip; } @@ -221,6 +231,62 @@ void GainCanvas::updateGainUI() { setThemeColors(); } +// call this to refresh the gain values only, not the whole UI. +bool GainCanvas::updateGainValues() { + + bool isRefreshNeeded = false; + + SDRDeviceInfo *devInfo = wxGetApp().getDevice(); + + //possible if we 'Refresh Devices' then devInfo becomes null + //until a new device is selected. + if (devInfo == nullptr) { + return false; + } + + DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(devInfo->getDeviceId()); + + gains = devInfo->getGains(SOAPY_SDR_RX, 0); + SDRRangeMap::iterator gi; + + size_t numGainsToRefresh = std::min(gains.size(), gainPanels.size()); + size_t panelIndex = 0; + + //actually the order of gains iteration should be constant because map of string, + //and gainPanels were built in that order in updateGainUI() + for (auto gi : gains) { + + if (panelIndex >= numGainsToRefresh) { + break; + } + + // do not update if a change is already pending. + if (!gainPanels[panelIndex]->getChanged()) { + + //read the actual gain from the device. + float actualGain = (float)devInfo->getCurrentGain(SOAPY_SDR_RX, 0, gi.first); + + //do nothing if the difference is less than 1.0, since the panel do not show it anyway. + if (std::abs(actualGain - gainPanels[panelIndex]->getValue()) > 1.0) { + + gainPanels[panelIndex]->setValue(actualGain); + + //update the config with this value : + //a consequence of such updates is that the use setting + // is overriden by the current one in AGC mode. + //TODO: if it not desirable, do not update in AGC mode. + devConfig->setGain(gi.first, actualGain); + + isRefreshNeeded = true; + } + } //end if no external change pending. + + panelIndex++; + } + + return isRefreshNeeded; +} + void GainCanvas::setThemeColors() { RGBA4f c1, c2; diff --git a/src/visual/GainCanvas.h b/src/visual/GainCanvas.h index 2e7a552..9ef9f3f 100644 --- a/src/visual/GainCanvas.h +++ b/src/visual/GainCanvas.h @@ -25,9 +25,13 @@ public: void setHelpTip(std::string tip); void updateGainUI(); - void setThemeColors(); + void setThemeColors(); private: + + // call this to refresh the gain values only, return true if refresh is needed + bool updateGainValues(); + void OnPaint(wxPaintEvent& event); void OnIdle(wxIdleEvent &event);