diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 1926c96..76a26a7 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -1236,7 +1236,7 @@ bool AppFrame::actionOnMenuSettings(wxCommandEvent& event) { menuIdx++; } } //end for - + return true; } diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index cabebee..b5ae9e5 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -395,8 +395,6 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event) { wxGetApp().setDeviceArgs(settingArgs); wxGetApp().setStreamArgs(streamArgs); wxGetApp().setDevice(dev,0); - wxGetApp().notifyMainUIOfDeviceChange(true); - Refresh(); Close(); } event.Skip(); @@ -495,7 +493,7 @@ void SDRDevicesDialog::OnRefreshDevices( wxMouseEvent& /* event */) { void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { - if (editId && event.GetProperty() == devSettings["name"]) { + if (event.GetProperty() == devSettings["name"]) { DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); wxString devName = event.GetPropertyValue().GetString(); @@ -550,7 +548,7 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { // nop } } - else if (editId && dev) { + else if (dev) { wxPGProperty *prop = event.GetProperty(); //change value of RuntimeProps for (std::map::iterator rtp = runtimeProps.begin(); rtp != runtimeProps.end(); rtp++) { @@ -570,14 +568,10 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) { if (dev->isActive()) { wxGetApp().getSDRThread()->writeSetting(rtp->first, settingValue); } - - wxGetApp().notifyMainUIOfDeviceChange(true); return; } } } - // general refresh. - wxGetApp().notifyMainUIOfDeviceChange(true); } void SDRDevicesDialog::OnPropGridFocus( wxFocusEvent& /* event */) { diff --git a/src/panel/MeterPanel.h b/src/panel/MeterPanel.h index c8c81f6..86a737d 100644 --- a/src/panel/MeterPanel.h +++ b/src/panel/MeterPanel.h @@ -32,7 +32,7 @@ protected: private: std::string name; float low, high, current; - bool changed; + bool changed = false; GLPanel bgPanel; GLPanel levelPanel; GLPanel highlightPanel; diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 7513612..3ca5f7b 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -153,13 +153,14 @@ bool SDRThread::init() { settingChanged.erase(settingChanged.begin(), settingChanged.end()); } + //apply settings. { //enter scoped-lock std::lock_guard < std::mutex > lock(setting_busy); for (settings_i = settingsInfo.begin(); settings_i != settingsInfo.end(); settings_i++) { SoapySDR::ArgInfo setting = (*settings_i); - if ((settingChanged.find(setting.key) != settingChanged.end()) && (settings.find(setting.key) != settings.end())) { - device->writeSetting(setting.key, settings[setting.key]); + if ((settingChanged.find(setting.key) != settingChanged.end()) && (settings.find(setting.key) != settings.end())) { + device->writeSetting(setting.key, settings[setting.key]); settingChanged[setting.key] = false; } else { settings[setting.key] = device->readSetting(setting.key); @@ -173,7 +174,10 @@ bool SDRThread::init() { updateSettings(); wxGetApp().sdrThreadNotify(SDRThread::SDR_THREAD_INITIALIZED, std::string("Device Initialized.")); - + + //rebuild menu now that settings are really been applied. + wxGetApp().notifyMainUIOfDeviceChange(true); + return true; } @@ -486,13 +490,12 @@ void SDRThread::updateSettings() { if (!agc_mode.load()) { updateGains(); + //re-apply the saved configuration gains: DeviceConfig *devConfig = deviceConfig.load(); ConfigGains gains = devConfig->getGains(); - if (gains.size()) { - for (ConfigGains::iterator gain_i = gains.begin(); gain_i != gains.end(); gain_i++) { - setGain(gain_i->first, gain_i->second); - } + for (ConfigGains::iterator gain_i = gains.begin(); gain_i != gains.end(); gain_i++) { + setGain(gain_i->first, gain_i->second); } } doUpdate = true; @@ -544,7 +547,7 @@ void SDRThread::run() { SDRDeviceInfo *activeDev = deviceInfo.load(); - if (activeDev != NULL) { + if (activeDev != nullptr) { std::cout << "device init()" << std::endl; if (!init()) { std::cout << "SDR Thread stream init error." << std::endl; diff --git a/src/visual/GainCanvas.cpp b/src/visual/GainCanvas.cpp index 83e2f50..70010cf 100644 --- a/src/visual/GainCanvas.cpp +++ b/src/visual/GainCanvas.cpp @@ -42,6 +42,8 @@ GainCanvas::GainCanvas(wxWindow *parent, std::vector dispAttrs) : startPos = spacing/2.0; barHeight = 0.8f; refreshCounter = 0; + + userGainAsChanged = false; } GainCanvas::~GainCanvas() { @@ -75,20 +77,33 @@ void GainCanvas::OnIdle(wxIdleEvent &event) { for (auto gi : gainPanels) { if (gi->getChanged()) { - areGainsChangedHere = true; - // Gain only displays integer gain values, so the applied gain + areGainsChangedHere = true; + // Gain only displays integer gain values, so set the applied gain //value to exactly that. wxGetApp().setGain(gi->getName(), (int)(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... + wxGetApp().notifyMainUIOfDeviceChange(false); //do not rebuild the gain UI gi->setChanged(false); } } - if (!areGainsChangedHere) { - if (updateGainValues()) { - Refresh(); + //User input has changed the gain, so schedule an update of values + //in 150ms in the future, else the device may not have taken the value into account. + if (areGainsChangedHere) { + userGainAsChanged = true; + userGainAsChangedDelayTimer.start(); + } + else { + userGainAsChangedDelayTimer.update(); + + if (!userGainAsChanged || (userGainAsChanged && userGainAsChangedDelayTimer.getMilliseconds() > 150)) { + + if (updateGainValues()) { + Refresh(); + } + + userGainAsChanged = false; } } } @@ -101,8 +116,7 @@ void GainCanvas::SetLevel() { float value = gi->getMeterHitValue(mpos); gi->setValue(value); - gi->setChanged(true); - + gi->setChanged(true); break; } } @@ -187,6 +201,7 @@ void GainCanvas::setHelpTip(std::string tip) { } void GainCanvas::updateGainUI() { + SDRDeviceInfo *devInfo = wxGetApp().getDevice(); //possible if we 'Refresh Devices' then devInfo becomes null @@ -196,9 +211,14 @@ void GainCanvas::updateGainUI() { } DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(devInfo->getDeviceId()); - + + //read the gains from the device. + //This may be wrong because the device is not started, or has yet + //to take into account a user gain change. Doesn't matter, + //UpdateGainValues() takes cares of updating the true value realtime. gains = devInfo->getGains(SOAPY_SDR_RX, 0); - SDRRangeMap::iterator gi; + + SDRRangeMap::iterator gi; numGains = gains.size(); float i = 0; @@ -218,7 +238,7 @@ void GainCanvas::updateGainUI() { bgPanel.removeChild(mDel); delete mDel; } - + for (auto gi : gains) { MeterPanel *mPanel = new MeterPanel(gi.first, gi.second.minimum(), gi.second.maximum(), devConfig->getGain(gi.first,wxGetApp().getGain(gi.first))); @@ -230,7 +250,7 @@ void GainCanvas::updateGainUI() { gainPanels.push_back(mPanel); i++; } - + setThemeColors(); } @@ -243,7 +263,8 @@ bool GainCanvas::updateGainValues() { //possible if we 'Refresh Devices' then devInfo becomes null //until a new device is selected. - if (devInfo == nullptr) { + //also, do not attempt an update with the device is not started. + if (devInfo == nullptr || !devInfo->isActive()) { return false; } diff --git a/src/visual/GainCanvas.h b/src/visual/GainCanvas.h index 9ef9f3f..323724b 100644 --- a/src/visual/GainCanvas.h +++ b/src/visual/GainCanvas.h @@ -8,6 +8,7 @@ #include #include +#include #include "InteractiveCanvas.h" #include "MouseTracker.h" @@ -25,7 +26,7 @@ public: void setHelpTip(std::string tip); void updateGainUI(); - void setThemeColors(); + void setThemeColors(); private: @@ -54,6 +55,9 @@ private: float spacing, barWidth, startPos, barHeight, numGains; int refreshCounter; wxSize clientSize; + + std::atomic_bool userGainAsChanged; + Timer userGainAsChangedDelayTimer; // wxDECLARE_EVENT_TABLE(); };