Stepped sliders

This commit is contained in:
cropinghigh 2020-12-26 21:00:09 +03:00
parent db279d2b36
commit 153b58fbbd
3 changed files with 113 additions and 6 deletions

View File

@ -481,6 +481,7 @@ namespace ImGui
// - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped and can go off-bounds.
// - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. Use power!=1.0 for power curve sliders
IMGUI_API bool SliderFloatWithSteps(const char* label, float* v, float v_min, float v_max, float v_step, const char* display_format = "%.3f");
IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);

View File

@ -2702,6 +2702,25 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power);
}
bool ImGui::SliderFloatWithSteps(const char* label, float* v, float v_min, float v_max, float v_step, const char* display_format)
{
if (!display_format)
display_format = "%.3f";
char text_buf[64] = {};
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), display_format, *v);
// Map from [v_min,v_max] to [0,N]
const int countValues = int((v_max-v_min)/v_step);
int v_i = int((*v - v_min)/v_step);
const bool value_changed = ImGui::SliderInt(label, &v_i, 0, countValues, text_buf);
// Remap from [0,N] to [v_min,v_max]
*v = v_min + float(v_i) * v_step;
return value_changed;
}
bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power)
{
return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power);

View File

@ -68,6 +68,14 @@ public:
return enabled;
}
template <typename T>
std::string to_string_with_precision(const T a_value, const int n = 6) {
std::ostringstream out;
out.precision(n);
out << std::fixed << a_value;
return out.str();
}
private:
void refresh() {
devList = SoapySDR::Device::enumerate();
@ -80,6 +88,21 @@ private:
}
}
float selectBwBySr(double samplerate) {
float cur = bandwidthList[1];
std::vector<float> bwListReversed = bandwidthList;
std::reverse(bwListReversed.begin(), bwListReversed.end());
for(auto bw : bwListReversed) {
if(bw >= samplerate) {
cur = bw;
} else {
break;
}
}
spdlog::info("Bandwidth for samplerate {0} is {1}", samplerate, cur);
return cur;
}
void selectSampleRate(double samplerate) {
spdlog::info("Setting sample rate to {0}", samplerate);
if (sampleRates.size() == 0) {
@ -131,19 +154,41 @@ private:
gainList = dev->listGains(SOAPY_SDR_RX, channelId);
delete[] uiGains;
uiGains = new float[gainList.size()];
for (auto gain : gainList) {
gainRanges.push_back(dev->getGainRange(SOAPY_SDR_RX, channelId, gain));
}
SoapySDR::RangeList bandwidthRange = dev->getBandwidthRange(SOAPY_SDR_RX, channelId);
txtBwList = "";
bandwidthList.push_back(-1);
txtBwList += "Auto";
txtBwList += '\0';
for(auto bwr : bandwidthRange) {
float bw = bwr.minimum();
bandwidthList.push_back(bw);
if (bw > 1.0e3 && bw <= 1.0e6) {
txtBwList += to_string_with_precision((bw / 1.0e3), 2) + " kHz";
} else if (bw > 1.0e6) {
txtBwList += to_string_with_precision((bw / 1.0e6), 2) + " MHz";
} else {
txtBwList += to_string_with_precision(bw, 0);
}
txtBwList += '\0';
}
sampleRates = dev->listSampleRates(SOAPY_SDR_RX, channelId);
txtSrList = "";
for (double sr : sampleRates) {
if (sr > 1.0e3 && sr <= 1.0e6) {
txtSrList += std::to_string((sr / 1.0e3)) + " kHz";
txtSrList += to_string_with_precision((sr / 1.0e3), 2) + " kHz";
} else if (sr > 1.0e6) {
txtSrList += std::to_string((sr / 1.0e6)) + " MHz";
txtSrList += to_string_with_precision((sr / 1.0e6), 2) + " MHz";
} else {
txtSrList += std::to_string((int) sr);
txtSrList += to_string_with_precision(sr, 0);
}
txtSrList += '\0';
}
@ -164,6 +209,11 @@ private:
}
i++;
}
if(config.conf["devices"][name].contains("bandwidth")) {
uiBandwidthId = config.conf["devices"][name]["bandwidth"];
} else if(bandwidthList.size() > 1) {
uiBandwidthId = bandwidthList[0];
}
if (hasAgc && config.conf["devices"][name].contains("agc")) {
agc = config.conf["devices"][name]["agc"];
}
@ -183,6 +233,8 @@ private:
uiGains[i] = gainRanges[i].minimum();
i++;
}
if(bandwidthList.size() > 1)
uiBandwidthId = bandwidthList[0];
if (hasAgc) {
agc = false;
}
@ -200,6 +252,8 @@ private:
conf["gains"][gain] = uiGains[i];
i++;
}
if(bandwidthList.size() > 1)
conf["bandwidth"] = uiBandwidthId;
if (hasAgc) {
conf["agc"] = agc;
}
@ -233,6 +287,12 @@ private:
_this->dev->setGain(SOAPY_SDR_RX, _this->channelId, gain, _this->uiGains[i]);
i++;
}
if(_this->bandwidthList.size() > 1) {
if(_this->bandwidthList[_this->uiBandwidthId] == -1)
_this->dev->setBandwidth(SOAPY_SDR_RX, _this->channelId, _this->selectBwBySr(_this->sampleRates[_this->srId]));
else
_this->dev->setBandwidth(SOAPY_SDR_RX, _this->channelId, _this->bandwidthList[_this->uiBandwidthId]);
}
if (_this->hasAgc) {
_this->dev->setGainMode(SOAPY_SDR_RX, _this->channelId, _this->agc);
@ -291,6 +351,8 @@ private:
if (ImGui::Combo(CONCAT("##_sr_select_", _this->name), &_this->srId, _this->txtSrList.c_str())) {
_this->selectSampleRate(_this->sampleRates[_this->srId]);
if(_this->bandwidthList.size() > 1 && _this->running && _this->bandwidthList[_this->uiBandwidthId] == -1)
_this->dev->setBandwidth(SOAPY_SDR_RX, _this->channelId, _this->selectBwBySr(_this->sampleRates[_this->srId]));
_this->saveCurrent();
}
@ -334,8 +396,13 @@ private:
ImGui::SameLine();
ImGui::SetCursorPosX(gainNameLen);
ImGui::SetNextItemWidth(menuWidth - gainNameLen);
if (ImGui::SliderFloat((gain + std::string("##_gain_sel_") + _this->name).c_str(), &_this->uiGains[i],
_this->gainRanges[i].minimum(), _this->gainRanges[i].maximum())) {
float step = _this->gainRanges[i].step();
bool res;
if(step == 0.0f)
res = ImGui::SliderFloat((std::string("##_gain_sel_") + _this->name + gain).c_str(), &_this->uiGains[i], _this->gainRanges[i].minimum(), _this->gainRanges[i].maximum());
else
res = ImGui::SliderFloatWithSteps((std::string("##_gain_sel_") + _this->name + gain).c_str(), &_this->uiGains[i], _this->gainRanges[i].minimum(), _this->gainRanges[i].maximum(), step);
if(res) {
if (_this->running) {
_this->dev->setGain(SOAPY_SDR_RX, _this->channelId, gain, _this->uiGains[i]);
}
@ -343,6 +410,23 @@ private:
}
i++;
}
if(_this->bandwidthList.size() > 1) {
float bwLen = ImGui::CalcTextSize("Bandwidth").x + 5.0f;
ImGui::Text("Bandwidth");
ImGui::SameLine();
ImGui::SetCursorPosX(bwLen);
ImGui::SetNextItemWidth(menuWidth - bwLen);
if (ImGui::Combo(CONCAT("##_bw_select_", _this->name), &_this->uiBandwidthId, _this->txtBwList.c_str())) {
if(_this->running) {
if(_this->bandwidthList[_this->uiBandwidthId] == -1)
_this->dev->setBandwidth(SOAPY_SDR_RX, _this->channelId, _this->selectBwBySr(_this->sampleRates[_this->srId]));
else
_this->dev->setBandwidth(SOAPY_SDR_RX, _this->channelId, _this->bandwidthList[_this->uiBandwidthId]);
}
_this->saveCurrent();
}
}
}
static void _worker(SoapyModule* _this) {
@ -383,6 +467,9 @@ private:
int channelId = 0;
std::vector<std::string> gainList;
std::vector<SoapySDR::Range> gainRanges;
int uiBandwidthId = 0;
std::vector<float> bandwidthList;
std::string txtBwList;
};
MOD_EXPORT void _INIT_() {