mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-11-06 02:37:32 +01:00
SDR++ server beta :)
This commit is contained in:
parent
1185e4e114
commit
74b9d13360
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@ build/
|
||||
*.wav
|
||||
.DS_Store
|
||||
root_dev/
|
||||
root_dev_srv/
|
||||
Folder.DotSettings.user
|
||||
CMakeSettings.json
|
||||
poggers_decoder
|
||||
|
@ -18,6 +18,7 @@ option(OPT_BUILD_FILE_SOURCE "Wav file source" ON)
|
||||
option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON)
|
||||
option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF)
|
||||
option(OPT_BUILD_SDDC_SOURCE "Build SDDC Source Module (Dependencies: libusb-1.0)" OFF)
|
||||
option(OPT_BUILD_SDRPP_SERVER_SOURCE "Build SDR++ Server Source Module (no dependencies required)" ON)
|
||||
option(OPT_BUILD_RFSPACE_SOURCE "Build RFspace Source Module (no dependencies required)" ON)
|
||||
option(OPT_BUILD_RTL_SDR_SOURCE "Build RTL-SDR Source Module (Dependencies: librtlsdr)" ON)
|
||||
option(OPT_BUILD_RTL_TCP_SOURCE "Build RTL-TCP Source Module (no dependencies required)" ON)
|
||||
@ -83,6 +84,10 @@ if (OPT_BUILD_SDDC_SOURCE)
|
||||
add_subdirectory("source_modules/sddc_source")
|
||||
endif (OPT_BUILD_SDDC_SOURCE)
|
||||
|
||||
if (OPT_BUILD_SDRPP_SERVER_SOURCE)
|
||||
add_subdirectory("source_modules/sdrpp_server_source")
|
||||
endif (OPT_BUILD_SDRPP_SERVER_SOURCE)
|
||||
|
||||
if (OPT_BUILD_RFSPACE_SOURCE)
|
||||
add_subdirectory("source_modules/rfspace_source")
|
||||
endif (OPT_BUILD_RFSPACE_SOURCE)
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <server.h>
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
@ -18,7 +19,6 @@
|
||||
#include <options.h>
|
||||
#include <filesystem>
|
||||
#include <gui/menus/theme.h>
|
||||
#include <server.h>
|
||||
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include <stb_image_resize.h>
|
||||
@ -70,6 +70,9 @@ namespace core {
|
||||
GLFWwindow* window;
|
||||
|
||||
void setInputSampleRate(double samplerate) {
|
||||
// Forward this to the server
|
||||
if (options::opts.serverMode) { server::setInputSampleRate(samplerate); return; }
|
||||
|
||||
sigpath::signalPath.sourceSampleRate = samplerate;
|
||||
double effectiveSr = samplerate / ((double)(1 << sigpath::signalPath.decimation));
|
||||
// NOTE: Zoom controls won't work
|
||||
@ -297,7 +300,7 @@ int sdrpp_main(int argc, char* argv[]) {
|
||||
|
||||
core::configManager.release(true);
|
||||
|
||||
if (options::opts.serverMode) { return server_main(); }
|
||||
if (options::opts.serverMode) { return server::main(); }
|
||||
|
||||
core::configManager.acquire();
|
||||
int winWidth = core::configManager.conf["windowSize"]["w"];
|
||||
|
@ -2,16 +2,16 @@
|
||||
#include <dsp/block.h>
|
||||
|
||||
namespace dsp {
|
||||
enum PCMType {
|
||||
PCM_TYPE_I8,
|
||||
PCM_TYPE_I16,
|
||||
PCM_TYPE_F32
|
||||
};
|
||||
|
||||
class DynamicRangeCompressor : public generic_block<DynamicRangeCompressor> {
|
||||
public:
|
||||
DynamicRangeCompressor() {}
|
||||
|
||||
enum PCMType {
|
||||
PCM_TYPE_I8,
|
||||
PCM_TYPE_I16,
|
||||
PCM_TYPE_F32
|
||||
};
|
||||
|
||||
DynamicRangeCompressor(stream<complex_t>* in, PCMType pcmType) { init(in, pcmType); }
|
||||
|
||||
void init(stream<complex_t>* in, PCMType pcmType) {
|
||||
@ -41,44 +41,42 @@ namespace dsp {
|
||||
int run() {
|
||||
int count = _in->read();
|
||||
if (count < 0) { return -1; }
|
||||
PCMType type = _pcmType;
|
||||
|
||||
float* scaler = (float*)out.writeBuf;
|
||||
void* dataBuf = &out.writeBuf[4];
|
||||
uint16_t* compressionType = (uint16_t*)out.writeBuf;
|
||||
uint16_t* sampleType = (uint16_t*)&out.writeBuf[2];
|
||||
float* scaler = (float*)&out.writeBuf[4];
|
||||
void* dataBuf = &out.writeBuf[8];
|
||||
|
||||
// If no dynamic range compression is to be done, just pass the data to the output with a null scaler
|
||||
if (_pcmType == PCM_TYPE_F32) {
|
||||
// Write options and leave blank space for compression
|
||||
*compressionType = 0;
|
||||
*sampleType = type;
|
||||
|
||||
// If type is float32, no compression is needed
|
||||
if (type == PCM_TYPE_F32) {
|
||||
*scaler = 0;
|
||||
memcpy(dataBuf, _in->readBuf, count * sizeof(complex_t));
|
||||
_in->flush();
|
||||
if (!out.swap(4 + (count * sizeof(complex_t)))) { return -1; }
|
||||
if (!out.swap(8 + (count * sizeof(complex_t)))) { return -1; }
|
||||
return count;
|
||||
}
|
||||
|
||||
// Find maximum value
|
||||
complex_t val;
|
||||
float absre;
|
||||
float absim;
|
||||
float maxVal = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
val = _in->readBuf[i];
|
||||
absre = fabsf(val.re);
|
||||
absim = fabsf(val.im);
|
||||
if (absre > maxVal) { maxVal = absre; }
|
||||
if (absim > maxVal) { maxVal = absim; }
|
||||
}
|
||||
uint32_t maxIdx;
|
||||
volk_32f_index_max_32u(&maxIdx, (float*)_in->readBuf, count * 2);
|
||||
float maxVal = ((float*)_in->readBuf)[maxIdx];
|
||||
*scaler = maxVal;
|
||||
|
||||
// Convert to the right type and send it out (sign bit determins pcm type)
|
||||
if (_pcmType == PCM_TYPE_I8) {
|
||||
*scaler = maxVal;
|
||||
if (type == PCM_TYPE_I8) {
|
||||
volk_32f_s32f_convert_8i((int8_t*)dataBuf, (float*)_in->readBuf, 128.0f / maxVal, count * 2);
|
||||
_in->flush();
|
||||
if (!out.swap(4 + (count * sizeof(int8_t) * 2))) { return -1; }
|
||||
if (!out.swap(8 + (count * sizeof(int8_t) * 2))) { return -1; }
|
||||
}
|
||||
else if (_pcmType == PCM_TYPE_I16) {
|
||||
*scaler = -maxVal;
|
||||
else if (type == PCM_TYPE_I16) {
|
||||
volk_32f_s32f_convert_16i((int16_t*)dataBuf, (float*)_in->readBuf, 32768.0f / maxVal, count * 2);
|
||||
_in->flush();
|
||||
if (!out.swap(4 + (count * sizeof(int16_t) * 2))) { return -1; }
|
||||
if (!out.swap(8 + (count * sizeof(int16_t) * 2))) { return -1; }
|
||||
}
|
||||
else {
|
||||
_in->flush();
|
||||
@ -121,31 +119,29 @@ namespace dsp {
|
||||
int count = _in->read();
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
float* scaler = (float*)_in->readBuf;
|
||||
void* dataBuf = &_in->readBuf[4];
|
||||
uint16_t sampleType = *(uint16_t*)&_in->readBuf[2];
|
||||
float scaler = *(float*)&_in->readBuf[4];
|
||||
void* dataBuf = &_in->readBuf[8];
|
||||
|
||||
// If the scaler is null, data is F32
|
||||
if (*scaler == 0) {
|
||||
memcpy(out.writeBuf, dataBuf, count - 4);
|
||||
if (sampleType == PCM_TYPE_F32) {
|
||||
memcpy(out.writeBuf, dataBuf, count - 8);
|
||||
_in->flush();
|
||||
if (!out.swap((count - 4) / sizeof(complex_t))) { return -1; }
|
||||
return count;
|
||||
if (!out.swap((count - 8) / sizeof(complex_t))) { return -1; }
|
||||
}
|
||||
|
||||
// Convert back to f32 from the pcm type
|
||||
float absScale = fabsf(*scaler);
|
||||
if (*scaler > 0) {
|
||||
spdlog::warn("{0}", absScale);
|
||||
int outCount = (count - 4) / (sizeof(int8_t) * 2);
|
||||
volk_8i_s32f_convert_32f((float*)out.writeBuf, (int8_t*)dataBuf, 128.0f / absScale, outCount * 2);
|
||||
else if (sampleType == PCM_TYPE_I16) {
|
||||
int outCount = (count - 8) / (sizeof(int16_t) * 2);
|
||||
volk_16i_s32f_convert_32f((float*)out.writeBuf, (int16_t*)dataBuf, 32768.0f / scaler, outCount * 2);
|
||||
_in->flush();
|
||||
if (!out.swap(outCount)) { return -1; }
|
||||
}
|
||||
else if (sampleType == PCM_TYPE_I8) {
|
||||
int outCount = (count - 8) / (sizeof(int8_t) * 2);
|
||||
volk_8i_s32f_convert_32f((float*)out.writeBuf, (int8_t*)dataBuf, 128.0f / scaler, outCount * 2);
|
||||
_in->flush();
|
||||
if (!out.swap(outCount)) { return -1; }
|
||||
}
|
||||
else {
|
||||
int outCount = (count - 4) / (sizeof(int16_t) * 2);
|
||||
volk_16i_s32f_convert_32f((float*)out.writeBuf, (int16_t*)dataBuf, 32768.0f / absScale, outCount * 2);
|
||||
_in->flush();
|
||||
if (!out.swap(outCount)) { return -1; }
|
||||
}
|
||||
|
||||
return count;
|
||||
|
54
core/src/dsp/link.h
Normal file
54
core/src/dsp/link.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include <dsp/block.h>
|
||||
|
||||
namespace dsp {
|
||||
template <class T>
|
||||
class Link : public generic_block<Link<T>> {
|
||||
public:
|
||||
Link() {}
|
||||
|
||||
Link(stream<T>* a, stream<T>* b) { init(a, b); }
|
||||
|
||||
void init(stream<T>* in, stream<T>* out) {
|
||||
_in = in;
|
||||
_out = out;
|
||||
generic_block<Link<T>>::registerInput(_in);
|
||||
generic_block<Link<T>>::registerOutput(_out);
|
||||
generic_block<Link<T>>::_block_init = true;
|
||||
}
|
||||
|
||||
void setInput(stream<T>* in) {
|
||||
assert(generic_block<Link<T>>::_block_init);
|
||||
std::lock_guard<std::mutex> lck(generic_block<Link<T>>::ctrlMtx);
|
||||
generic_block<Link<T>>::tempStop();
|
||||
generic_block<Link<T>>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<Link<T>>::registerInput(_in);
|
||||
generic_block<Link<T>>::tempStart();
|
||||
}
|
||||
|
||||
void setOutput(stream<T>* out) {
|
||||
assert(generic_block<Link<T>>::_block_init);
|
||||
std::lock_guard<std::mutex> lck(generic_block<Link<T>>::ctrlMtx);
|
||||
generic_block<Link<T>>::tempStop();
|
||||
generic_block<Link<T>>::unregisterOutput(_out);
|
||||
_out = out;
|
||||
generic_block<Link<T>>::registerOutput(_out);
|
||||
generic_block<Link<T>>::tempStart();
|
||||
}
|
||||
|
||||
int run() {
|
||||
int count = _in->read();
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
memcpy(_out->writeBuf, _in->readBuf, count * sizeof(T));
|
||||
|
||||
_in->flush();
|
||||
return _out->swap(count) ? count : -1;
|
||||
}
|
||||
|
||||
private:
|
||||
stream<T>* _in;
|
||||
stream<T>* _out;
|
||||
};
|
||||
}
|
@ -516,7 +516,7 @@ void MainWindow::draw() {
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Debug")) {
|
||||
ImGui::Text("Frame time: %.3f ms/frame", 1000.0 / ImGui::GetIO().Framerate);
|
||||
ImGui::Text("Frame time: %.3f ms/frame", ImGui::GetIO().DeltaTime * 1000.0f);
|
||||
ImGui::Text("Framerate: %.1f FPS", ImGui::GetIO().Framerate);
|
||||
ImGui::Text("Center Frequency: %.0f Hz", gui::waterfall.getCenterFrequency());
|
||||
ImGui::Text("Source name: %s", sourceName.c_str());
|
||||
|
745
core/src/gui/smgui.cpp
Normal file
745
core/src/gui/smgui.cpp
Normal file
@ -0,0 +1,745 @@
|
||||
#include "smgui.h"
|
||||
#include "style.h"
|
||||
#include <options.h>
|
||||
#include <gui/widgets/stepped_slider.h>
|
||||
#include <gui/gui.h>
|
||||
|
||||
namespace SmGui {
|
||||
std::map<FormatString, const char*> fmtStr = {
|
||||
{ FMT_STR_NONE, "" },
|
||||
{ FMT_STR_INT_DEFAULT, "%d" },
|
||||
{ FMT_STR_INT_DB, "%d dB" },
|
||||
{ FMT_STR_FLOAT_DEFAULT, "%f" },
|
||||
{ FMT_STR_FLOAT_NO_DECIMAL, "%.0f" },
|
||||
{ FMT_STR_FLOAT_ONE_DECIMAL, "%.1f" },
|
||||
{ FMT_STR_FLOAT_TWO_DECIMAL, "%.2f" },
|
||||
{ FMT_STR_FLOAT_THREE_DECIMAL, "%.3f" },
|
||||
{ FMT_STR_FLOAT_DB_NO_DECIMAL, "%.0f dB" },
|
||||
{ FMT_STR_FLOAT_DB_ONE_DECIMAL, "%.1f dB" },
|
||||
{ FMT_STR_FLOAT_DB_TWO_DECIMAL, "%.2f dB" },
|
||||
{ FMT_STR_FLOAT_DB_THREE_DECIMAL, "%.3f dB" }
|
||||
};
|
||||
|
||||
DrawList* rdl = NULL;
|
||||
bool forceSyncForNext = false;
|
||||
std::string diffId = "";
|
||||
DrawListElem diffValue;
|
||||
bool nextItemFillWidth = false;
|
||||
|
||||
std::string ImStrToString(const char* imstr) {
|
||||
int len = 0;
|
||||
const char* end = imstr;
|
||||
while (*end) { end += strlen(end) + 1; }
|
||||
return std::string(imstr, end);
|
||||
}
|
||||
|
||||
// Rec/Play functions
|
||||
void setDiff(std::string id, SmGui::DrawListElem value) {
|
||||
diffId = id;
|
||||
diffValue = value;
|
||||
}
|
||||
|
||||
// TODO: Add getDiff function for client
|
||||
|
||||
void startRecord(DrawList* dl) {
|
||||
rdl = dl;
|
||||
}
|
||||
|
||||
void stopRecord() {
|
||||
rdl = NULL;
|
||||
}
|
||||
|
||||
#define SET_DIFF_VOID(id) diffId = id; syncRequired = elem.forceSync;
|
||||
#define SET_DIFF_BOOL(id, bo) diffId = id; diffValue.type = DRAW_LIST_ELEM_TYPE_BOOL; diffValue.b = bo; syncRequired = elem.forceSync;
|
||||
#define SET_DIFF_INT(id, in) diffId = id; diffValue.type = DRAW_LIST_ELEM_TYPE_INT; diffValue.i = in; syncRequired = elem.forceSync;
|
||||
#define SET_DIFF_FLOAT(id, fl) diffId = id; diffValue.type = DRAW_LIST_ELEM_TYPE_FLOAT; diffValue.f = fl; syncRequired = elem.forceSync;
|
||||
#define SET_DIFF_STRING(id, st) diffId = id; diffValue.type = DRAW_LIST_ELEM_TYPE_STRING; diffValue.str = st; syncRequired = elem.forceSync;
|
||||
|
||||
void DrawList::draw(std::string& diffId, DrawListElem& diffValue, bool& syncRequired) {
|
||||
int elemCount = elements.size();
|
||||
nextItemFillWidth = false;
|
||||
|
||||
for (int i = 0; i < elemCount;) {
|
||||
// Get element
|
||||
DrawListElem& elem = elements[i++];
|
||||
if (elem.type != DRAW_LIST_ELEM_TYPE_DRAW_STEP) { continue; }
|
||||
|
||||
// Format calls
|
||||
if (elem.step == DRAW_STEP_FILL_WIDTH) { FillWidth(); }
|
||||
else if (elem.step == DRAW_STEP_SAME_LINE) { SameLine(); }
|
||||
else if (elem.step == DRAW_STEP_BEGIN_DISABLED) { BeginDisabled(); }
|
||||
else if (elem.step == DRAW_STEP_END_DISABLED) { EndDisabled(); }
|
||||
|
||||
// Widget Calls
|
||||
else if (elem.step == DRAW_STEP_COMBO) {
|
||||
if (Combo(elements[i].str.c_str(), &elements[i+1].i, elements[i+2].str.c_str(), elements[i+3].i)) {
|
||||
SET_DIFF_INT(elements[i].str, elements[i+1].i);
|
||||
}
|
||||
i += 4;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_BUTTON) {
|
||||
if (Button(elements[i].str.c_str(), ImVec2(elements[i+1].f, elements[i+2].f))) {
|
||||
SET_DIFF_VOID(elements[i].str);
|
||||
}
|
||||
i += 3;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_COLUMNS) {
|
||||
Columns(elements[i].i, elements[i+1].str.c_str(), elements[i+2].b);
|
||||
i += 3;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_NEXT_COLUMN) { NextColumn(); }
|
||||
else if (elem.step == DRAW_STEP_RADIO_BUTTON) {
|
||||
if (RadioButton(elements[i].str.c_str(), elements[i+1].b)) {
|
||||
SET_DIFF_VOID(elements[i].str);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_BEGIN_GROUP) { BeginGroup(); }
|
||||
else if (elem.step == DRAW_STEP_END_GROUP) { EndGroup(); }
|
||||
else if (elem.step == DRAW_STEP_LEFT_LABEL) {
|
||||
LeftLabel(elements[i].str.c_str());
|
||||
i++;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_SLIDER_INT) {
|
||||
if (SliderInt(elements[i].str.c_str(), &elements[i+1].i, elements[i+2].i, elements[i+3].i, (FormatString)elements[i+4].i, elements[i+5].i)) {
|
||||
SET_DIFF_INT(elements[i].str, elements[i+1].i);
|
||||
}
|
||||
i += 6;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_SLIDER_FLOAT_WITH_STEPS) {
|
||||
if (SliderFloatWithSteps(elements[i].str.c_str(), &elements[i+1].f, elements[i+2].f, elements[i+3].f, elements[i+4].f, (FormatString)elements[i+5].i)) {
|
||||
SET_DIFF_FLOAT(elements[i].str, elements[i+1].f);
|
||||
}
|
||||
i += 6;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_INPUT_INT) {
|
||||
if (InputInt(elements[i].str.c_str(), &elements[i+1].i, elements[i+2].i, elements[i+3].i, elements[i+4].i)) {
|
||||
SET_DIFF_INT(elements[i].str, elements[i+1].i);
|
||||
}
|
||||
i += 5;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_CHECKBOX) {
|
||||
if (Checkbox(elements[i].str.c_str(), &elements[i+1].b)) {
|
||||
SET_DIFF_BOOL(elements[i].str, elements[i+1].b);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_SLIDER_FLOAT) {
|
||||
if (SliderFloat(elements[i].str.c_str(), &elements[i+1].f, elements[i+2].f, elements[i+3].f, (FormatString)elements[i+4].i, elements[i+5].i)) {
|
||||
SET_DIFF_FLOAT(elements[i].str, elements[i+1].f);
|
||||
}
|
||||
i += 6;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_INPUT_TEXT) {
|
||||
char tmpBuf[4096];
|
||||
strcpy(tmpBuf, elements[i+1].str.c_str());
|
||||
if (InputText(elements[i].str.c_str(), tmpBuf, elements[i+2].i, elements[i+3].i)) {
|
||||
elements[i+1].str = tmpBuf;
|
||||
SET_DIFF_STRING(elements[i].str, tmpBuf);
|
||||
}
|
||||
i += 4;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_TEXT) {
|
||||
Text(elements[i].str.c_str());
|
||||
i++;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_TEXT_COLORED) {
|
||||
TextColored(ImVec4(elements[i].f, elements[i+1].f, elements[i+2].f, elements[i+3].f), elements[i+4].str.c_str());
|
||||
i += 5;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_OPEN_POPUP) {
|
||||
OpenPopup(elements[i].str.c_str(), elements[i+1].i);
|
||||
i += 2;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_BEGIN_POPUP) {
|
||||
gui::mainWindow.lockWaterfallControls = true;
|
||||
if (!BeginPopup(elements[i].str.c_str(), elements[i+1].i)) {
|
||||
i += 2;
|
||||
while (i < elemCount && !(elements[i].type == DRAW_LIST_ELEM_TYPE_DRAW_STEP && elements[i].step == DRAW_STEP_END_POPUP)) { i++; }
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_END_POPUP) {
|
||||
EndPopup();
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_BEGIN_TABLE) {
|
||||
if (!BeginTable(elements[i].str.c_str(), elements[i+1].i, elements[i+2].i, ImVec2(elements[i+3].f, elements[i+4].f), elements[i+5].f)) {
|
||||
i += 6;
|
||||
while (i < elemCount && !(elements[i].type == DRAW_LIST_ELEM_TYPE_DRAW_STEP && elements[i].step == DRAW_STEP_END_TABLE)) { i++; }
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
i += 6;
|
||||
}
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_END_TABLE) {
|
||||
EndTable();
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_TABLE_NEXT_ROW) {
|
||||
TableNextRow(elements[i].i, elements[i+1].f);
|
||||
i += 2;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_TABLE_SET_COLUMN_INDEX) {
|
||||
TableSetColumnIndex(elements[i].i);
|
||||
i++;
|
||||
}
|
||||
else if (elem.step == DRAW_STEP_SET_NEXT_ITEM_WIDTH) {
|
||||
SetNextItemWidth(elements[i].f);
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
spdlog::error("Invalid widget in Drawlist");
|
||||
}
|
||||
|
||||
if (elem.step != DRAW_STEP_FILL_WIDTH) { nextItemFillWidth = false; }
|
||||
}
|
||||
}
|
||||
|
||||
// Drawlist stuff
|
||||
void DrawList::pushStep(DrawStep step, bool forceSync) {
|
||||
DrawListElem elem;
|
||||
elem.type = DRAW_LIST_ELEM_TYPE_DRAW_STEP;
|
||||
elem.step = step;
|
||||
elem.forceSync = forceSync;
|
||||
elements.push_back(elem);
|
||||
}
|
||||
|
||||
void DrawList::pushBool(bool b) {
|
||||
DrawListElem elem;
|
||||
elem.type = DRAW_LIST_ELEM_TYPE_BOOL;
|
||||
elem.b = b;
|
||||
elements.push_back(elem);
|
||||
}
|
||||
|
||||
void DrawList::pushInt(int i) {
|
||||
DrawListElem elem;
|
||||
elem.type = DRAW_LIST_ELEM_TYPE_INT;
|
||||
elem.i = i;
|
||||
elements.push_back(elem);
|
||||
}
|
||||
|
||||
void DrawList::pushFloat(float f) {
|
||||
DrawListElem elem;
|
||||
elem.type = DRAW_LIST_ELEM_TYPE_FLOAT;
|
||||
elem.f = f;
|
||||
elements.push_back(elem);
|
||||
}
|
||||
|
||||
void DrawList::pushString(std::string str) {
|
||||
DrawListElem elem;
|
||||
elem.type = DRAW_LIST_ELEM_TYPE_STRING;
|
||||
elem.str = str;
|
||||
elements.push_back(elem);
|
||||
}
|
||||
|
||||
int DrawList::loadItem(DrawListElem& elem, uint8_t* data, int len) {
|
||||
// Get type
|
||||
int i = 0;
|
||||
elem.type = (DrawListElemType)data[i++];
|
||||
|
||||
// Read data depending on type
|
||||
if (elem.type == DRAW_LIST_ELEM_TYPE_DRAW_STEP && len >= 2) {
|
||||
elem.step = (DrawStep)data[i++];
|
||||
elem.forceSync = data[i++];
|
||||
}
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_BOOL && len-- >= 1) {
|
||||
elem.b = data[i++];
|
||||
}
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_INT && len >= 4) {
|
||||
elem.i = *(int*)&data[i];
|
||||
i += 4;
|
||||
}
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_FLOAT && len >= 4) {
|
||||
elem.f = *(float*)&data[i];
|
||||
i += 4;
|
||||
}
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_STRING && len >= 2) {
|
||||
uint16_t slen = *(uint16_t*)&data[i];
|
||||
if (len < slen + 2) { return -1; }
|
||||
elem.str = std::string(&data[i + 2], &data[i + 2 + slen]);
|
||||
i += slen + 2;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int DrawList::load(void* data, int len) {
|
||||
uint8_t* buf = (uint8_t*)data;
|
||||
elements.clear();
|
||||
int i = 0;
|
||||
|
||||
// Load all entries
|
||||
while (len > 0) {
|
||||
// Load entry type
|
||||
DrawListElem elem;
|
||||
int consumed = loadItem(elem, &buf[i], len);
|
||||
if (consumed < 0) { return -1; }
|
||||
i += consumed;
|
||||
len -= consumed;
|
||||
|
||||
// Add element to list
|
||||
elements.push_back(elem);
|
||||
}
|
||||
|
||||
// Validate and clear if invalid
|
||||
if (!validate()) {
|
||||
spdlog::error("Drawlist validation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int DrawList::storeItem(DrawListElem& elem, void* data, int len) {
|
||||
// Check size requirement
|
||||
uint8_t* buf = (uint8_t*)data;
|
||||
if (len < 1) { return -1; }
|
||||
int i = 0;
|
||||
len--;
|
||||
|
||||
// Save entry type
|
||||
buf[i++] = elem.type;
|
||||
|
||||
// Check type and save data accordingly
|
||||
if (elem.type == DRAW_LIST_ELEM_TYPE_DRAW_STEP && len >= 2) {
|
||||
buf[i++] = elem.step;
|
||||
buf[i++] = elem.forceSync;
|
||||
}
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_BOOL && len >= 1) {
|
||||
buf[i++] = elem.b;
|
||||
}
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_INT && len >= 4) {
|
||||
*(int*)&buf[i] = elem.i;
|
||||
i += 4;
|
||||
}
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_FLOAT && len >= 4) {
|
||||
*(float*)&buf[i] = elem.f;
|
||||
i += 4;
|
||||
}
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_STRING) {
|
||||
int slen = elem.str.size();
|
||||
if (len < slen + 2) { return -1; }
|
||||
*(uint16_t*)&buf[i] = slen;
|
||||
memcpy(&buf[i + 2], elem.str.c_str(), slen);
|
||||
i += slen + 2;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int DrawList::store(void* data, int len) {
|
||||
uint8_t* buf = (uint8_t*)data;
|
||||
int i = 0;
|
||||
|
||||
// Iterate through all element and write the data in the buffer
|
||||
for (auto& elem : elements) {
|
||||
int count = storeItem(elem, &buf[i], len);
|
||||
if (count < 0) { return -1; }
|
||||
i += count;
|
||||
len -= count;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int DrawList::getItemSize(DrawListElem& elem) {
|
||||
if (elem.type == DRAW_LIST_ELEM_TYPE_DRAW_STEP) { return 3; }
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_BOOL) { return 2; }
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_INT) { return 5; }
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_FLOAT) { return 5; }
|
||||
else if (elem.type == DRAW_LIST_ELEM_TYPE_STRING) { return 3 + elem.str.size(); }
|
||||
return -1;
|
||||
}
|
||||
|
||||
int DrawList::getSize() {
|
||||
int size = 0;
|
||||
|
||||
// Iterate through all element to add up the total size
|
||||
for (auto& elem : elements) {
|
||||
size += getItemSize(elem);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool DrawList::checkTypes(int firstId, int n, ...) {
|
||||
va_list args;
|
||||
va_start(args, n);
|
||||
|
||||
// Check if enough elements are left
|
||||
if (elements.size() - firstId < n) { return false; }
|
||||
|
||||
// Check the type of each element
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (va_arg(args, DrawListElemType) != elements[firstId + i].type) {
|
||||
va_end(args);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define VALIDATE_WIDGET(n, ws, ...) if (step == ws) { if (!checkTypes(i, n, __VA_ARGS__)) { return false; }; i += n; }
|
||||
#define E_VALIDATE_WIDGET(n, ws, ...) else VALIDATE_WIDGET(n, ws, __VA_ARGS__)
|
||||
|
||||
bool DrawList::validate() {
|
||||
int count = elements.size();
|
||||
for (int i = 0; i < count;) {
|
||||
if (elements[i].type != DRAW_LIST_ELEM_TYPE_DRAW_STEP) { return false; }
|
||||
DrawStep step = elements[i++].step;
|
||||
|
||||
VALIDATE_WIDGET(4, DRAW_STEP_COMBO, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(3, DRAW_STEP_BUTTON, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_FLOAT)
|
||||
E_VALIDATE_WIDGET(3, DRAW_STEP_COLUMNS, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_BOOL)
|
||||
E_VALIDATE_WIDGET(2, DRAW_STEP_RADIO_BUTTON, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_BOOL)
|
||||
E_VALIDATE_WIDGET(1, DRAW_STEP_LEFT_LABEL, DRAW_LIST_ELEM_TYPE_STRING)
|
||||
E_VALIDATE_WIDGET(6, DRAW_STEP_SLIDER_INT, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_INT,
|
||||
DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(6, DRAW_STEP_SLIDER_FLOAT_WITH_STEPS, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_FLOAT,
|
||||
DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(5, DRAW_STEP_INPUT_INT, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_INT,
|
||||
DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(2, DRAW_STEP_CHECKBOX, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_BOOL)
|
||||
E_VALIDATE_WIDGET(6, DRAW_STEP_SLIDER_FLOAT, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_FLOAT,
|
||||
DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(4, DRAW_STEP_INPUT_TEXT, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(1, DRAW_STEP_TEXT, DRAW_LIST_ELEM_TYPE_STRING)
|
||||
E_VALIDATE_WIDGET(5, DRAW_STEP_TEXT_COLORED, DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_FLOAT,
|
||||
DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_STRING)
|
||||
E_VALIDATE_WIDGET(2, DRAW_STEP_OPEN_POPUP, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(2, DRAW_STEP_BEGIN_POPUP, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(6, DRAW_STEP_BEGIN_TABLE, DRAW_LIST_ELEM_TYPE_STRING, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_INT,
|
||||
DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_FLOAT, DRAW_LIST_ELEM_TYPE_FLOAT)
|
||||
E_VALIDATE_WIDGET(2, DRAW_STEP_TABLE_NEXT_ROW, DRAW_LIST_ELEM_TYPE_INT, DRAW_LIST_ELEM_TYPE_FLOAT)
|
||||
E_VALIDATE_WIDGET(1, DRAW_STEP_TABLE_SET_COLUMN_INDEX, DRAW_LIST_ELEM_TYPE_INT)
|
||||
E_VALIDATE_WIDGET(1, DRAW_STEP_SET_NEXT_ITEM_WIDTH, DRAW_LIST_ELEM_TYPE_FLOAT)
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Signaling functions
|
||||
void ForceSync() {
|
||||
forceSyncForNext = true;
|
||||
}
|
||||
|
||||
// Format functions
|
||||
void FillWidth() {
|
||||
if (!options::opts.serverMode) {
|
||||
nextItemFillWidth = true;
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth());
|
||||
return;
|
||||
}
|
||||
if (rdl) { rdl->pushStep(DRAW_STEP_FILL_WIDTH, false); }
|
||||
}
|
||||
|
||||
void SameLine() {
|
||||
if (!options::opts.serverMode) { ImGui::SameLine(); return; }
|
||||
if (rdl) { rdl->pushStep(DRAW_STEP_SAME_LINE, false); }
|
||||
}
|
||||
|
||||
void BeginDisabled() {
|
||||
if (!options::opts.serverMode) { style::beginDisabled(); return; }
|
||||
if (rdl) { rdl->pushStep(DRAW_STEP_BEGIN_DISABLED, false); }
|
||||
}
|
||||
|
||||
void EndDisabled() {
|
||||
if (!options::opts.serverMode) { style::endDisabled(); return; }
|
||||
if (rdl) { rdl->pushStep(DRAW_STEP_END_DISABLED, false); }
|
||||
}
|
||||
|
||||
|
||||
// Widget functions
|
||||
bool Combo(const char *label, int *current_item, const char *items_separated_by_zeros, int popup_max_height_in_items) {
|
||||
if (!options::opts.serverMode) { return ImGui::Combo(label, current_item, items_separated_by_zeros, popup_max_height_in_items); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_COMBO, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushInt(*current_item);
|
||||
rdl->pushString(ImStrToString(items_separated_by_zeros));
|
||||
rdl->pushInt(popup_max_height_in_items);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
if (diffId == label && diffValue.type == DRAW_LIST_ELEM_TYPE_INT) {
|
||||
*current_item = diffValue.i;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Button(const char *label, ImVec2 size) {
|
||||
if (!options::opts.serverMode) {
|
||||
if (nextItemFillWidth) { size.x = ImGui::GetContentRegionAvailWidth(); }
|
||||
return ImGui::Button(label, size);
|
||||
}
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_BUTTON, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushFloat(size.x);
|
||||
rdl->pushFloat(size.y);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
return (diffId == label);
|
||||
}
|
||||
|
||||
void Columns(int count, const char *id, bool border) {
|
||||
if (!options::opts.serverMode) { ImGui::Columns(count, id, border); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_COLUMNS, forceSyncForNext);
|
||||
rdl->pushInt(count);
|
||||
rdl->pushString(id);
|
||||
rdl->pushBool(border);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
}
|
||||
|
||||
void NextColumn() {
|
||||
if (!options::opts.serverMode) { ImGui::NextColumn(); return; }
|
||||
if (rdl) { rdl->pushStep(DRAW_STEP_NEXT_COLUMN, false); }
|
||||
}
|
||||
|
||||
bool RadioButton(const char *label, bool active) {
|
||||
if (!options::opts.serverMode) { return ImGui::RadioButton(label, active); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_RADIO_BUTTON, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushBool(active);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
return (diffId == label);
|
||||
}
|
||||
|
||||
void BeginGroup() {
|
||||
if (!options::opts.serverMode) { ImGui::BeginGroup(); return; }
|
||||
if (rdl) { rdl->pushStep(DRAW_STEP_BEGIN_GROUP, false); }
|
||||
}
|
||||
|
||||
void EndGroup() {
|
||||
if (!options::opts.serverMode) { ImGui::EndGroup(); return; }
|
||||
if (rdl) { rdl->pushStep(DRAW_STEP_END_GROUP, false); }
|
||||
}
|
||||
|
||||
void LeftLabel(const char *text) {
|
||||
if (!options::opts.serverMode) { ImGui::LeftLabel(text); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_LEFT_LABEL, forceSyncForNext);
|
||||
rdl->pushString(text);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SliderInt(const char *label, int *v, int v_min, int v_max, FormatString format, ImGuiSliderFlags flags) {
|
||||
if (!options::opts.serverMode) { return ImGui::SliderInt(label, v, v_min, v_max, fmtStr[format], flags); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_SLIDER_INT, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushInt(*v);
|
||||
rdl->pushInt(v_min);
|
||||
rdl->pushInt(v_max);
|
||||
rdl->pushInt(format);
|
||||
rdl->pushInt(flags);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
if (diffId == label && diffValue.type == DRAW_LIST_ELEM_TYPE_INT) {
|
||||
*v = diffValue.i;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SliderFloatWithSteps(const char *label, float *v, float v_min, float v_max, float v_step, FormatString display_format) {
|
||||
if (!options::opts.serverMode) { return ImGui::SliderFloatWithSteps(label, v, v_min, v_max, v_step, fmtStr[display_format]); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_SLIDER_FLOAT_WITH_STEPS, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushFloat(*v);
|
||||
rdl->pushFloat(v_min);
|
||||
rdl->pushFloat(v_max);
|
||||
rdl->pushFloat(v_step);
|
||||
rdl->pushInt(display_format);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
if (diffId == label && diffValue.type == DRAW_LIST_ELEM_TYPE_FLOAT) {
|
||||
*v = diffValue.f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputInt(const char *label, int *v, int step, int step_fast, ImGuiInputTextFlags flags) {
|
||||
if (!options::opts.serverMode) { return ImGui::InputInt(label, v, step, step_fast, flags); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_INPUT_INT, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushInt(*v);
|
||||
rdl->pushInt(step);
|
||||
rdl->pushInt(step_fast);
|
||||
rdl->pushInt(flags);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
if (diffId == label && diffValue.type == DRAW_LIST_ELEM_TYPE_INT) {
|
||||
*v = diffValue.i;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Checkbox(const char *label, bool *v) {
|
||||
if (!options::opts.serverMode) { return ImGui::Checkbox(label, v); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_CHECKBOX, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushBool(*v);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
if (diffId == label && diffValue.type == DRAW_LIST_ELEM_TYPE_BOOL) {
|
||||
*v = diffValue.b;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SliderFloat(const char *label, float *v, float v_min, float v_max, FormatString format, ImGuiSliderFlags flags) {
|
||||
if (!options::opts.serverMode) { return ImGui::SliderFloat(label, v, v_min, v_max, fmtStr[format], flags); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_SLIDER_FLOAT, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushFloat(*v);
|
||||
rdl->pushFloat(v_min);
|
||||
rdl->pushFloat(v_max);
|
||||
rdl->pushInt(format);
|
||||
rdl->pushInt(flags);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
if (diffId == label && diffValue.type == DRAW_LIST_ELEM_TYPE_FLOAT) {
|
||||
*v = diffValue.f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags) {
|
||||
if (!options::opts.serverMode) { return ImGui::InputText(label, buf, buf_size, flags); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_INPUT_TEXT, forceSyncForNext);
|
||||
rdl->pushString(label);
|
||||
rdl->pushString(buf);
|
||||
rdl->pushInt(buf_size);
|
||||
rdl->pushInt(flags);
|
||||
forceSyncForNext = false;
|
||||
}
|
||||
if (diffId == label && diffValue.type == DRAW_LIST_ELEM_TYPE_STRING && diffValue.str.size() <= buf_size) {
|
||||
strcpy(buf, diffValue.str.c_str());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Text(const char* str) {
|
||||
if (!options::opts.serverMode) { ImGui::Text("%s", str); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_TEXT, false);
|
||||
rdl->pushString(str);
|
||||
}
|
||||
}
|
||||
|
||||
void TextColored(const ImVec4 &col, const char *str) {
|
||||
if (!options::opts.serverMode) { ImGui::TextColored(col, "%s", str); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_TEXT_COLORED, false);
|
||||
rdl->pushFloat(col.x);
|
||||
rdl->pushFloat(col.y);
|
||||
rdl->pushFloat(col.z);
|
||||
rdl->pushFloat(col.w);
|
||||
rdl->pushString(str);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenPopup(const char *str_id, ImGuiPopupFlags popup_flags) {
|
||||
if (!options::opts.serverMode) { ImGui::OpenPopup(str_id, popup_flags); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_OPEN_POPUP, false);
|
||||
rdl->pushString(str_id);
|
||||
rdl->pushInt(popup_flags);
|
||||
}
|
||||
}
|
||||
|
||||
bool BeginPopup(const char *str_id, ImGuiWindowFlags flags) {
|
||||
if (!options::opts.serverMode) { return ImGui::BeginPopup(str_id, flags); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_BEGIN_POPUP, false);
|
||||
rdl->pushString(str_id);
|
||||
rdl->pushInt(flags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void EndPopup() {
|
||||
if (!options::opts.serverMode) { ImGui::EndPopup(); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_END_POPUP, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool BeginTable(const char *str_id, int column, ImGuiTableFlags flags, const ImVec2 &outer_size, float inner_width) {
|
||||
if (!options::opts.serverMode) { return ImGui::BeginTable(str_id, column, flags, outer_size, inner_width); }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_BEGIN_TABLE, false);
|
||||
rdl->pushString(str_id);
|
||||
rdl->pushInt(column);
|
||||
rdl->pushInt(flags);
|
||||
rdl->pushFloat(outer_size.x);
|
||||
rdl->pushFloat(outer_size.y);
|
||||
rdl->pushFloat(inner_width);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void EndTable() {
|
||||
if (!options::opts.serverMode) { ImGui::EndTable(); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_END_TABLE, false);
|
||||
}
|
||||
}
|
||||
|
||||
void TableNextRow(ImGuiTableRowFlags row_flags, float min_row_height) {
|
||||
if (!options::opts.serverMode) { ImGui::TableNextRow(row_flags, min_row_height); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_TABLE_NEXT_ROW, false);
|
||||
rdl->pushInt(row_flags);
|
||||
rdl->pushFloat(min_row_height);
|
||||
}
|
||||
}
|
||||
|
||||
void TableSetColumnIndex(int column_n) {
|
||||
if (!options::opts.serverMode) { ImGui::TableSetColumnIndex(column_n); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_TABLE_SET_COLUMN_INDEX, false);
|
||||
rdl->pushInt(column_n);
|
||||
}
|
||||
}
|
||||
|
||||
void SetNextItemWidth(float item_width) {
|
||||
if (!options::opts.serverMode) { ImGui::SetNextItemWidth(item_width); return; }
|
||||
if (rdl) {
|
||||
rdl->pushStep(DRAW_STEP_SET_NEXT_ITEM_WIDTH, false);
|
||||
rdl->pushFloat(item_width);
|
||||
}
|
||||
}
|
||||
|
||||
// Config configs
|
||||
void ForceSyncForNext() {
|
||||
forceSyncForNext = true;
|
||||
}
|
||||
}
|
146
core/src/gui/smgui.h
Normal file
146
core/src/gui/smgui.h
Normal file
@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
#include <imgui.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace SmGui {
|
||||
enum DrawStep {
|
||||
// Format calls
|
||||
DRAW_STEP_FILL_WIDTH = 0x00,
|
||||
DRAW_STEP_SAME_LINE,
|
||||
DRAW_STEP_BEGIN_DISABLED,
|
||||
DRAW_STEP_END_DISABLED,
|
||||
|
||||
// Widget calls
|
||||
DRAW_STEP_COMBO = 0x80,
|
||||
DRAW_STEP_BUTTON,
|
||||
DRAW_STEP_COLUMNS,
|
||||
DRAW_STEP_NEXT_COLUMN,
|
||||
DRAW_STEP_RADIO_BUTTON,
|
||||
DRAW_STEP_BEGIN_GROUP,
|
||||
DRAW_STEP_END_GROUP,
|
||||
DRAW_STEP_LEFT_LABEL,
|
||||
DRAW_STEP_SLIDER_INT,
|
||||
DRAW_STEP_SLIDER_FLOAT_WITH_STEPS,
|
||||
DRAW_STEP_INPUT_INT,
|
||||
DRAW_STEP_CHECKBOX,
|
||||
DRAW_STEP_SLIDER_FLOAT,
|
||||
DRAW_STEP_INPUT_TEXT,
|
||||
DRAW_STEP_TEXT,
|
||||
DRAW_STEP_TEXT_COLORED,
|
||||
DRAW_STEP_OPEN_POPUP,
|
||||
DRAW_STEP_BEGIN_POPUP,
|
||||
DRAW_STEP_END_POPUP,
|
||||
DRAW_STEP_BEGIN_TABLE,
|
||||
DRAW_STEP_END_TABLE,
|
||||
DRAW_STEP_TABLE_NEXT_ROW,
|
||||
DRAW_STEP_TABLE_SET_COLUMN_INDEX,
|
||||
DRAW_STEP_SET_NEXT_ITEM_WIDTH
|
||||
};
|
||||
|
||||
enum DrawListElemType {
|
||||
DRAW_LIST_ELEM_TYPE_DRAW_STEP,
|
||||
DRAW_LIST_ELEM_TYPE_BOOL,
|
||||
DRAW_LIST_ELEM_TYPE_INT,
|
||||
DRAW_LIST_ELEM_TYPE_FLOAT,
|
||||
DRAW_LIST_ELEM_TYPE_STRING,
|
||||
};
|
||||
|
||||
struct DrawListElem {
|
||||
DrawListElemType type;
|
||||
DrawStep step;
|
||||
bool forceSync;
|
||||
bool b;
|
||||
int i;
|
||||
float f;
|
||||
std::string str;
|
||||
};
|
||||
|
||||
enum FormatString {
|
||||
FMT_STR_NONE,
|
||||
FMT_STR_INT_DEFAULT,
|
||||
FMT_STR_INT_DB,
|
||||
FMT_STR_FLOAT_DEFAULT,
|
||||
FMT_STR_FLOAT_NO_DECIMAL,
|
||||
FMT_STR_FLOAT_ONE_DECIMAL,
|
||||
FMT_STR_FLOAT_TWO_DECIMAL,
|
||||
FMT_STR_FLOAT_THREE_DECIMAL,
|
||||
FMT_STR_FLOAT_DB_NO_DECIMAL,
|
||||
FMT_STR_FLOAT_DB_ONE_DECIMAL,
|
||||
FMT_STR_FLOAT_DB_TWO_DECIMAL,
|
||||
FMT_STR_FLOAT_DB_THREE_DECIMAL
|
||||
};
|
||||
|
||||
extern std::map<FormatString, const char*> fmtStr;
|
||||
|
||||
std::string ImStrToString(const char* imstr);
|
||||
|
||||
class DrawList {
|
||||
public:
|
||||
void pushStep(DrawStep step, bool forceSync);
|
||||
void pushBool(bool b);
|
||||
void pushInt(int i);
|
||||
void pushFloat(float f);
|
||||
void pushString(std::string str);
|
||||
|
||||
void draw(std::string& diffId, DrawListElem& diffValue, bool& syncRequired);
|
||||
|
||||
static int loadItem(DrawListElem& elem, uint8_t* data, int len);
|
||||
int load(void* data, int len);
|
||||
static int storeItem(DrawListElem& elem, void* data, int len);
|
||||
int store(void* data, int len);
|
||||
static int getItemSize(DrawListElem& elem);
|
||||
int getSize();
|
||||
bool checkTypes(int firstId, int n, ...);
|
||||
bool validate();
|
||||
|
||||
std::vector<DrawListElem> elements;
|
||||
};
|
||||
|
||||
// Rec/Play functions
|
||||
// TODO: Maybe move verification to the load function instead of checking in drawFrame
|
||||
void setDiff(std::string id, SmGui::DrawListElem value);
|
||||
void startRecord(DrawList* dl);
|
||||
void stopRecord();
|
||||
|
||||
// Signaling Functions
|
||||
void ForceSync();
|
||||
|
||||
// Format functions
|
||||
void FillWidth();
|
||||
void SameLine();
|
||||
void BeginDisabled();
|
||||
void EndDisabled();
|
||||
|
||||
// Widget functions
|
||||
bool Combo(const char *label, int *current_item, const char *items_separated_by_zeros, int popup_max_height_in_items = -1);
|
||||
bool Button(const char *label, ImVec2 size = ImVec2(0, 0));
|
||||
void Columns(int count = 1, const char *id = (const char *)0, bool border = true);
|
||||
void NextColumn();
|
||||
bool RadioButton(const char *label, bool active);
|
||||
void BeginGroup();
|
||||
void EndGroup();
|
||||
void LeftLabel(const char *text);
|
||||
bool SliderInt(const char *label, int *v, int v_min, int v_max, FormatString format = FMT_STR_INT_DEFAULT, ImGuiSliderFlags flags = 0);
|
||||
bool SliderFloatWithSteps(const char *label, float *v, float v_min, float v_max, float v_step, FormatString display_format = FMT_STR_FLOAT_THREE_DECIMAL);
|
||||
bool InputInt(const char *label, int *v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0);
|
||||
bool Checkbox(const char *label, bool *v);
|
||||
bool SliderFloat(const char *label, float *v, float v_min, float v_max, FormatString format = FMT_STR_FLOAT_THREE_DECIMAL, ImGuiSliderFlags flags = 0);
|
||||
bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags = 0);
|
||||
void Text(const char* str);
|
||||
void TextColored(const ImVec4 &col, const char *str);
|
||||
void OpenPopup(const char *str_id, ImGuiPopupFlags popup_flags = 0);
|
||||
bool BeginPopup(const char *str_id, ImGuiWindowFlags flags = 0);
|
||||
void EndPopup();
|
||||
|
||||
bool BeginTable(const char *str_id, int column, ImGuiTableFlags flags = 0, const ImVec2 &outer_size = ImVec2((0.0F), (0.0F)), float inner_width = (0.0F));
|
||||
void EndTable();
|
||||
void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = (0.0F));
|
||||
void TableSetColumnIndex(int column_n);
|
||||
void SetNextItemWidth(float item_width);
|
||||
|
||||
// Config configs
|
||||
void ForceSyncForNext();
|
||||
|
||||
}
|
@ -53,4 +53,8 @@ namespace ImGui {
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(vpos);
|
||||
}
|
||||
|
||||
void FillWidth() {
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth());
|
||||
}
|
||||
}
|
@ -16,4 +16,5 @@ namespace style {
|
||||
|
||||
namespace ImGui {
|
||||
void LeftLabel(const char* text);
|
||||
void FillWidth();
|
||||
}
|
@ -18,6 +18,8 @@ namespace options {
|
||||
opts.root = homedir + "/.config/sdrpp";
|
||||
#endif
|
||||
opts.root = std::filesystem::absolute(opts.root).string();
|
||||
opts.serverHost = "0.0.0.0";
|
||||
opts.serverPort = 5259;
|
||||
}
|
||||
|
||||
bool parse(int argc, char* argv[]) {
|
||||
@ -33,6 +35,16 @@ namespace options {
|
||||
else if (!strcmp(arg, "--server")) {
|
||||
opts.serverMode = true;
|
||||
}
|
||||
else if (!strcmp(arg, "-a") || !strcmp(arg, "--addr")) {
|
||||
if (i == argc - 1) { return false; }
|
||||
opts.serverHost = argv[++i];
|
||||
opts.showConsole = true;
|
||||
}
|
||||
else if (!strcmp(arg, "-p") || !strcmp(arg, "--port")) {
|
||||
if (i == argc - 1) { return false; }
|
||||
sscanf(argv[++i], "%d", &opts.serverPort);
|
||||
opts.showConsole = true;
|
||||
}
|
||||
else {
|
||||
spdlog::error("Invalid command line option: {0}", arg);
|
||||
return false;
|
||||
|
@ -7,6 +7,8 @@ namespace options {
|
||||
std::string root;
|
||||
bool showConsole;
|
||||
bool serverMode;
|
||||
std::string serverHost;
|
||||
int serverPort;
|
||||
};
|
||||
|
||||
SDRPP_EXPORT CMDLineOptions opts;
|
||||
|
@ -1,7 +1,354 @@
|
||||
#include <server.h>
|
||||
#include "server.h"
|
||||
#include "core.h"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <version.h>
|
||||
#include <config.h>
|
||||
#include <options.h>
|
||||
#include <filesystem>
|
||||
#include <dsp/types.h>
|
||||
#include <signal_path/signal_path.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <utils/optionlist.h>
|
||||
#include <dsp/compression.h>
|
||||
|
||||
int server_main() {
|
||||
spdlog::error("Server mode is not implemented yet.");
|
||||
return 0;
|
||||
}
|
||||
namespace server {
|
||||
dsp::stream<dsp::complex_t> dummyInput;
|
||||
dsp::DynamicRangeCompressor comp;
|
||||
dsp::HandlerSink<uint8_t> hnd;
|
||||
net::Conn client;
|
||||
uint8_t* rbuf = NULL;
|
||||
uint8_t* sbuf = NULL;
|
||||
uint8_t* bbuf = NULL;
|
||||
|
||||
PacketHeader* r_pkt_hdr = NULL;
|
||||
uint8_t* r_pkt_data = NULL;
|
||||
CommandHeader* r_cmd_hdr = NULL;
|
||||
uint8_t* r_cmd_data = NULL;
|
||||
|
||||
PacketHeader* s_pkt_hdr = NULL;
|
||||
uint8_t* s_pkt_data = NULL;
|
||||
CommandHeader* s_cmd_hdr = NULL;
|
||||
uint8_t* s_cmd_data = NULL;
|
||||
|
||||
PacketHeader* bb_pkt_hdr = NULL;
|
||||
uint8_t* bb_pkt_data = NULL;
|
||||
|
||||
SmGui::DrawListElem dummyElem;
|
||||
|
||||
net::Listener listener;
|
||||
|
||||
OptionList<std::string, std::string> sourceList;
|
||||
int sourceId = 0;
|
||||
bool running = false;
|
||||
double sampleRate = 1000000.0;
|
||||
|
||||
int main() {
|
||||
spdlog::info("=====| SERVER MODE |=====");
|
||||
|
||||
// Init DSP
|
||||
comp.init(&dummyInput, dsp::PCM_TYPE_I8);
|
||||
hnd.init(&comp.out, _testServerHandler, NULL);
|
||||
rbuf = new uint8_t[SERVER_MAX_PACKET_SIZE];
|
||||
sbuf = new uint8_t[SERVER_MAX_PACKET_SIZE];
|
||||
bbuf = new uint8_t[SERVER_MAX_PACKET_SIZE];
|
||||
comp.start();
|
||||
hnd.start();
|
||||
|
||||
// Initialize headers
|
||||
r_pkt_hdr = (PacketHeader*)rbuf;
|
||||
r_pkt_data = &rbuf[sizeof(PacketHeader)];
|
||||
r_cmd_hdr = (CommandHeader*)r_pkt_data;
|
||||
r_cmd_data = &rbuf[sizeof(PacketHeader) + sizeof(CommandHeader)];
|
||||
|
||||
s_pkt_hdr = (PacketHeader*)sbuf;
|
||||
s_pkt_data = &sbuf[sizeof(PacketHeader)];
|
||||
s_cmd_hdr = (CommandHeader*)s_pkt_data;
|
||||
s_cmd_data = &sbuf[sizeof(PacketHeader) + sizeof(CommandHeader)];
|
||||
|
||||
bb_pkt_hdr = (PacketHeader*)bbuf;
|
||||
bb_pkt_data = &bbuf[sizeof(PacketHeader)];
|
||||
|
||||
// Terminate config manager
|
||||
core::configManager.disableAutoSave();
|
||||
core::configManager.save();
|
||||
|
||||
core::configManager.acquire();
|
||||
std::string modulesDir = core::configManager.conf["modulesDirectory"];
|
||||
std::vector<std::string> modules = core::configManager.conf["modules"];
|
||||
auto modList = core::configManager.conf["moduleInstances"].items();
|
||||
core::configManager.release();
|
||||
modulesDir = std::filesystem::absolute(modulesDir).string();
|
||||
|
||||
spdlog::info("Loading modules");
|
||||
|
||||
// Load modules and check type to only load sources ( TODO: Have a proper type parameter int the info )
|
||||
// TODO LATER: Add whitelist/blacklist stuff
|
||||
if (std::filesystem::is_directory(modulesDir)) {
|
||||
for (const auto& file : std::filesystem::directory_iterator(modulesDir)) {
|
||||
std::string path = file.path().generic_string();
|
||||
std::string fn = file.path().filename().string();
|
||||
if (file.path().extension().generic_string() != SDRPP_MOD_EXTENTSION) {
|
||||
continue;
|
||||
}
|
||||
if (!file.is_regular_file()) { continue; }
|
||||
if (fn.find("source") == std::string::npos) { continue; }
|
||||
|
||||
spdlog::info("Loading {0}", path);
|
||||
core::moduleManager.loadModule(path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
spdlog::warn("Module directory {0} does not exist, not loading modules from directory", modulesDir);
|
||||
}
|
||||
|
||||
// Load additional modules through the config ( TODO: Have a proper type parameter int the info )
|
||||
// TODO LATER: Add whitelist/blacklist stuff
|
||||
for (auto const& apath : modules) {
|
||||
std::filesystem::path file = std::filesystem::absolute(apath);
|
||||
std::string path = file.generic_string();
|
||||
std::string fn = file.filename().string();
|
||||
if (file.extension().generic_string() != SDRPP_MOD_EXTENTSION) {
|
||||
continue;
|
||||
}
|
||||
if (!std::filesystem::is_regular_file(file)) { continue; }
|
||||
if (fn.find("source") == std::string::npos) { continue; }
|
||||
|
||||
spdlog::info("Loading {0}", path);
|
||||
core::moduleManager.loadModule(path);
|
||||
}
|
||||
|
||||
// Create module instances
|
||||
for (auto const& [name, _module] : modList) {
|
||||
std::string mod = _module["module"];
|
||||
bool enabled = _module["enabled"];
|
||||
if (core::moduleManager.modules.find(mod) == core::moduleManager.modules.end()) { continue; }
|
||||
spdlog::info("Initializing {0} ({1})", name, mod);
|
||||
core::moduleManager.createInstance(name, mod);
|
||||
if (!enabled) { core::moduleManager.disableInstance(name); }
|
||||
}
|
||||
|
||||
// Do post-init
|
||||
core::moduleManager.doPostInitAll();
|
||||
|
||||
// Generate source list
|
||||
auto list = sigpath::sourceManager.getSourceNames();
|
||||
for (auto& name : list) {
|
||||
sourceList.define(name, name);
|
||||
}
|
||||
|
||||
// TODO: Load sourceId from config
|
||||
|
||||
sigpath::sourceManager.selectSource(sourceList[sourceId]);
|
||||
|
||||
// TODO: Use command line option
|
||||
listener = net::listen(options::opts.serverHost, options::opts.serverPort);
|
||||
listener->acceptAsync(_clientHandler, NULL);
|
||||
|
||||
spdlog::info("Ready, listening on {0}:{1}", options::opts.serverHost, options::opts.serverPort);
|
||||
while(1) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _clientHandler(net::Conn conn, void* ctx) {
|
||||
spdlog::info("Connection from {0}:{1}", "TODO", "TODO");
|
||||
client = std::move(conn);
|
||||
client->readAsync(sizeof(PacketHeader), rbuf, _packetHandler, NULL);
|
||||
|
||||
// Perform settings reset
|
||||
sigpath::sourceManager.stop();
|
||||
comp.setPCMType(dsp::PCM_TYPE_I16);
|
||||
|
||||
sendSampleRate(sampleRate);
|
||||
|
||||
// TODO: Wait otherwise someone else could connect
|
||||
|
||||
listener->acceptAsync(_clientHandler, NULL);
|
||||
}
|
||||
|
||||
void _packetHandler(int count, uint8_t* buf, void* ctx) {
|
||||
PacketHeader* hdr = (PacketHeader*)buf;
|
||||
|
||||
// Read the rest of the data (TODO: CHECK SIZE OR SHIT WILL BE FUCKED + ADD TIMEOUT)
|
||||
int len = 0;
|
||||
int read = 0;
|
||||
int goal = hdr->size - sizeof(PacketHeader);
|
||||
while (len < goal) {
|
||||
read = client->read(goal - len, &buf[sizeof(PacketHeader) + len]);
|
||||
if (read < 0) { return; };
|
||||
len += read;
|
||||
}
|
||||
|
||||
// Parse and process
|
||||
if (hdr->type == PACKET_TYPE_COMMAND && hdr->size >= sizeof(PacketHeader) + sizeof(CommandHeader)) {
|
||||
CommandHeader* chdr = (CommandHeader*)&buf[sizeof(PacketHeader)];
|
||||
commandHandler((Command)chdr->cmd, &buf[sizeof(PacketHeader) + sizeof(CommandHeader)], hdr->size - sizeof(PacketHeader) - sizeof(CommandHeader));
|
||||
}
|
||||
else {
|
||||
sendError(ERROR_INVALID_PACKET);
|
||||
}
|
||||
|
||||
// Start another async read
|
||||
client->readAsync(sizeof(PacketHeader), rbuf, _packetHandler, NULL);
|
||||
}
|
||||
|
||||
// void _testServerHandler(dsp::complex_t* data, int count, void* ctx) {
|
||||
// // Build data packet
|
||||
// PacketHeader* hdr = (PacketHeader*)bbuf;
|
||||
// hdr->type = PACKET_TYPE_BASEBAND;
|
||||
// hdr->size = sizeof(PacketHeader) + (count * sizeof(dsp::complex_t));
|
||||
// memcpy(&bbuf[sizeof(PacketHeader)], data, count * sizeof(dsp::complex_t));
|
||||
|
||||
// // Write to network
|
||||
// if (client && client->isOpen()) { client->write(hdr->size, bbuf); }
|
||||
// }
|
||||
|
||||
void _testServerHandler(uint8_t* data, int count, void* ctx) {
|
||||
// Build data packet
|
||||
PacketHeader* hdr = (PacketHeader*)bbuf;
|
||||
hdr->type = PACKET_TYPE_BASEBAND;
|
||||
hdr->size = sizeof(PacketHeader) + count;
|
||||
memcpy(&bbuf[sizeof(PacketHeader)], data, count);
|
||||
|
||||
// Write to network
|
||||
if (client && client->isOpen()) { client->write(hdr->size, bbuf); }
|
||||
}
|
||||
|
||||
void setInput(dsp::stream<dsp::complex_t>* stream) {
|
||||
comp.setInput(stream);
|
||||
}
|
||||
|
||||
void commandHandler(Command cmd, uint8_t* data, int len) {
|
||||
if (cmd == COMMAND_GET_UI) {
|
||||
sendUI(COMMAND_GET_UI, "", dummyElem);
|
||||
}
|
||||
else if (cmd == COMMAND_UI_ACTION && len >= 3) {
|
||||
// Check if sending back data is needed
|
||||
int i = 0;
|
||||
bool sendback = data[i++];
|
||||
len--;
|
||||
|
||||
// Load id
|
||||
SmGui::DrawListElem diffId;
|
||||
int count = SmGui::DrawList::loadItem(diffId, &data[i], len);
|
||||
if (count < 0) { sendError(ERROR_INVALID_ARGUMENT); return; }
|
||||
if (diffId.type != SmGui::DRAW_LIST_ELEM_TYPE_STRING) { sendError(ERROR_INVALID_ARGUMENT); return; }
|
||||
i += count;
|
||||
len -= count;
|
||||
|
||||
// Load value
|
||||
SmGui::DrawListElem diffValue;
|
||||
count = SmGui::DrawList::loadItem(diffValue, &data[i], len);
|
||||
if (count < 0) { sendError(ERROR_INVALID_ARGUMENT); return; }
|
||||
i += count;
|
||||
len -= count;
|
||||
|
||||
// Render and send back
|
||||
if (sendback) {
|
||||
sendUI(COMMAND_UI_ACTION, diffId.str, diffValue);
|
||||
}
|
||||
else {
|
||||
renderUI(NULL, diffId.str, diffValue);
|
||||
}
|
||||
}
|
||||
else if (cmd == COMMAND_START) {
|
||||
sigpath::sourceManager.start();
|
||||
running = true;
|
||||
}
|
||||
else if (cmd == COMMAND_STOP) {
|
||||
sigpath::sourceManager.stop();
|
||||
running = false;
|
||||
}
|
||||
else if (cmd == COMMAND_SET_FREQUENCY && len == 8) {
|
||||
sigpath::sourceManager.tune(*(double*)data);
|
||||
sendCommandAck(COMMAND_SET_FREQUENCY, 0);
|
||||
}
|
||||
else if (cmd == COMMAND_SET_SAMPLE_TYPE && len == 1) {
|
||||
dsp::PCMType type = (dsp::PCMType)*(uint8_t*)data;
|
||||
comp.setPCMType(type);
|
||||
}
|
||||
else {
|
||||
spdlog::error("Invalid Command: {0} (len = {1})", cmd, len);
|
||||
sendError(ERROR_INVALID_COMMAND);
|
||||
}
|
||||
}
|
||||
|
||||
void drawMenu() {
|
||||
if (running) { SmGui::BeginDisabled(); }
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo("##sdrpp_server_src_sel", &sourceId, sourceList.txt)) {
|
||||
sigpath::sourceManager.selectSource(sourceList[sourceId]);
|
||||
// TODO: Save config
|
||||
}
|
||||
if (running) { SmGui::EndDisabled(); }
|
||||
|
||||
sigpath::sourceManager.showSelectedMenu();
|
||||
}
|
||||
|
||||
void renderUI(SmGui::DrawList* dl, std::string diffId, SmGui::DrawListElem diffValue) {
|
||||
// If we're recording and there's an action, render once with the action and record without
|
||||
|
||||
if (dl && !diffId.empty()) {
|
||||
SmGui::setDiff(diffId, diffValue);
|
||||
drawMenu();
|
||||
|
||||
SmGui::setDiff("", dummyElem);
|
||||
SmGui::startRecord(dl);
|
||||
drawMenu();
|
||||
SmGui::stopRecord();
|
||||
}
|
||||
else {
|
||||
SmGui::setDiff(diffId, diffValue);
|
||||
SmGui::startRecord(dl);
|
||||
drawMenu();
|
||||
SmGui::stopRecord();
|
||||
}
|
||||
}
|
||||
|
||||
void sendUI(Command originCmd, std::string diffId, SmGui::DrawListElem diffValue) {
|
||||
// Render UI
|
||||
SmGui::DrawList dl;
|
||||
renderUI(&dl, diffId, diffValue);
|
||||
|
||||
// Create response
|
||||
int size = dl.getSize();
|
||||
dl.store(s_cmd_data, size);
|
||||
|
||||
// Send to network
|
||||
sendCommandAck(originCmd, size);
|
||||
}
|
||||
|
||||
void sendError(Error err) {
|
||||
PacketHeader* hdr = (PacketHeader*)sbuf;
|
||||
s_pkt_data[0] = err;
|
||||
sendPacket(PACKET_TYPE_ERROR, 1);
|
||||
}
|
||||
|
||||
void sendSampleRate(double sampleRate) {
|
||||
*(double*)s_cmd_data = sampleRate;
|
||||
sendCommand(COMMAND_SET_SAMPLERATE, sizeof(double));
|
||||
}
|
||||
|
||||
void setInputSampleRate(double samplerate) {
|
||||
sampleRate = samplerate;
|
||||
if (!client || !client->isOpen()) { return; }
|
||||
sendSampleRate(sampleRate);
|
||||
}
|
||||
|
||||
void sendPacket(PacketType type, int len) {
|
||||
s_pkt_hdr->type = type;
|
||||
s_pkt_hdr->size = sizeof(PacketHeader) + len;
|
||||
client->write(s_pkt_hdr->size, sbuf);
|
||||
}
|
||||
|
||||
void sendCommand(Command cmd, int len) {
|
||||
s_cmd_hdr->cmd = cmd;
|
||||
sendPacket(PACKET_TYPE_COMMAND, sizeof(CommandHeader) + len);
|
||||
}
|
||||
|
||||
void sendCommandAck(Command cmd, int len) {
|
||||
s_cmd_hdr->cmd = cmd;
|
||||
sendPacket(PACKET_TYPE_COMMAND_ACK, sizeof(CommandHeader) + len);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,27 @@
|
||||
#pragma once
|
||||
#include <utils/networking.h>
|
||||
#include <dsp/stream.h>
|
||||
#include <dsp/types.h>
|
||||
#include <server_protocol.h>
|
||||
|
||||
int server_main();
|
||||
namespace server {
|
||||
void setInput(dsp::stream<dsp::complex_t>* stream);
|
||||
int main();
|
||||
|
||||
void _clientHandler(net::Conn conn, void* ctx);
|
||||
void _packetHandler(int count, uint8_t* buf, void* ctx);
|
||||
void _testServerHandler(uint8_t* data, int count, void* ctx);
|
||||
|
||||
void drawMenu();
|
||||
|
||||
void commandHandler(Command cmd, uint8_t* data, int len);
|
||||
void renderUI(SmGui::DrawList* dl, std::string diffId, SmGui::DrawListElem diffValue);
|
||||
void sendUI(Command originCmd, std::string diffId, SmGui::DrawListElem diffValue);
|
||||
void sendError(Error err);
|
||||
void sendSampleRate(double sampleRate);
|
||||
void setInputSampleRate(double samplerate);
|
||||
|
||||
void sendPacket(PacketType type, int len);
|
||||
void sendCommand(Command cmd, int len);
|
||||
void sendCommandAck(Command cmd, int len);
|
||||
}
|
||||
|
49
core/src/server_protocol.h
Normal file
49
core/src/server_protocol.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <dsp/types.h>
|
||||
|
||||
#define SERVER_MAX_PACKET_SIZE (STREAM_BUFFER_SIZE * sizeof(dsp::complex_t) * 2)
|
||||
|
||||
namespace server {
|
||||
enum PacketType {
|
||||
// Client to Server
|
||||
PACKET_TYPE_COMMAND,
|
||||
PACKET_TYPE_COMMAND_ACK,
|
||||
PACKET_TYPE_BASEBAND,
|
||||
PACKET_TYPE_VFO,
|
||||
PACKET_TYPE_FFT,
|
||||
PACKET_TYPE_ERROR
|
||||
};
|
||||
|
||||
enum Command {
|
||||
// Client to Server
|
||||
COMMAND_GET_UI = 0x00,
|
||||
COMMAND_UI_ACTION,
|
||||
COMMAND_START,
|
||||
COMMAND_STOP,
|
||||
COMMAND_SET_FREQUENCY,
|
||||
COMMAND_GET_SAMPLERATE,
|
||||
COMMAND_SET_SAMPLE_TYPE,
|
||||
|
||||
// Server to client
|
||||
COMMAND_SET_SAMPLERATE = 0x80
|
||||
};
|
||||
|
||||
enum Error {
|
||||
ERROR_NONE = 0x00,
|
||||
ERROR_INVALID_PACKET,
|
||||
ERROR_INVALID_COMMAND,
|
||||
ERROR_INVALID_ARGUMENT
|
||||
};
|
||||
|
||||
// TODO: Pack
|
||||
struct PacketHeader {
|
||||
uint32_t type;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
struct CommandHeader {
|
||||
uint32_t cmd;
|
||||
};
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
#include <server.h>
|
||||
#include <signal_path/source.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <signal_path/signal_path.h>
|
||||
#include <options.h>
|
||||
|
||||
SourceManager::SourceManager() {
|
||||
}
|
||||
@ -48,7 +50,13 @@ void SourceManager::selectSource(std::string name) {
|
||||
selectedHandler = sources[name];
|
||||
selectedHandler->selectHandler(selectedHandler->ctx);
|
||||
selectedName = name;
|
||||
sigpath::signalPath.setInput(selectedHandler->stream);
|
||||
if (options::opts.serverMode) {
|
||||
server::setInput(selectedHandler->stream);
|
||||
}
|
||||
else {
|
||||
sigpath::signalPath.setInput(selectedHandler->stream);
|
||||
}
|
||||
// Set server input here
|
||||
}
|
||||
|
||||
void SourceManager::showSelectedMenu() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <utils/networking.h>
|
||||
#include <assert.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace net {
|
||||
|
||||
@ -70,19 +71,34 @@ namespace net {
|
||||
if (_udp) {
|
||||
socklen_t fromLen = sizeof(remoteAddr);
|
||||
ret = recvfrom(_sock, (char*)buf, count, 0, (struct sockaddr*)&remoteAddr, &fromLen);
|
||||
}
|
||||
else {
|
||||
ret = recv(_sock, (char*)buf, count, 0);
|
||||
if (ret <= 0) {
|
||||
{
|
||||
std::lock_guard lck(connectionOpenMtx);
|
||||
connectionOpen = false;
|
||||
}
|
||||
connectionOpenCnd.notify_all();
|
||||
return -1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
{
|
||||
std::lock_guard lck(connectionOpenMtx);
|
||||
connectionOpen = false;
|
||||
int beenRead = 0;
|
||||
while (beenRead < count) {
|
||||
ret = recv(_sock, (char*)&buf[beenRead], count - beenRead, 0);
|
||||
|
||||
if (ret <= 0) {
|
||||
{
|
||||
std::lock_guard lck(connectionOpenMtx);
|
||||
connectionOpen = false;
|
||||
}
|
||||
connectionOpenCnd.notify_all();
|
||||
return -1;
|
||||
}
|
||||
connectionOpenCnd.notify_all();
|
||||
|
||||
beenRead += ret;
|
||||
}
|
||||
return ret;
|
||||
|
||||
return beenRead;
|
||||
}
|
||||
|
||||
bool ConnClass::write(int count, uint8_t* buf) {
|
||||
@ -93,19 +109,31 @@ namespace net {
|
||||
if (_udp) {
|
||||
int fromLen = sizeof(remoteAddr);
|
||||
ret = sendto(_sock, (char*)buf, count, 0, (struct sockaddr*)&remoteAddr, sizeof(remoteAddr));
|
||||
}
|
||||
else {
|
||||
ret = send(_sock, (char*)buf, count, 0);
|
||||
if (ret <= 0) {
|
||||
{
|
||||
std::lock_guard lck(connectionOpenMtx);
|
||||
connectionOpen = false;
|
||||
}
|
||||
connectionOpenCnd.notify_all();
|
||||
}
|
||||
return (ret > 0);
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
{
|
||||
std::lock_guard lck(connectionOpenMtx);
|
||||
connectionOpen = false;
|
||||
int beenWritten = 0;
|
||||
while (beenWritten < count) {
|
||||
ret = send(_sock, (char*)buf, count, 0);
|
||||
if (ret <= 0) {
|
||||
{
|
||||
std::lock_guard lck(connectionOpenMtx);
|
||||
connectionOpen = false;
|
||||
}
|
||||
connectionOpenCnd.notify_all();
|
||||
return false;
|
||||
}
|
||||
connectionOpenCnd.notify_all();
|
||||
beenWritten += ret;
|
||||
}
|
||||
return (ret > 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConnClass::readAsync(int count, uint8_t* buf, void (*handler)(int count, uint8_t* buf, void* ctx), void* ctx) {
|
||||
|
2
core/src/utils/new_networking.cpp
Normal file
2
core/src/utils/new_networking.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#include "new_networking.h"
|
||||
|
95
core/src/utils/new_networking.h
Normal file
95
core/src/utils/new_networking.h
Normal file
@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
/*
|
||||
Ryzerth's Epic Networking Functins
|
||||
*/
|
||||
|
||||
namespace net {
|
||||
enum SocketType {
|
||||
SOCK_TYPE_TCP,
|
||||
SOCK_TYPE_UDP
|
||||
};
|
||||
|
||||
struct ReadHandler {
|
||||
int count;
|
||||
void* buf;
|
||||
void (*handle)(int count, void* buf, void* ctx);
|
||||
void* ctx;
|
||||
};
|
||||
|
||||
class SocketClass {
|
||||
public:
|
||||
SocketClass(struct addrinfo* localAddr, struct addrinfo* remoteAddr, SocketType sockType);
|
||||
~SocketClass();
|
||||
|
||||
int read(int count, void* buf, int timeout);
|
||||
int write(int count, void* buf);
|
||||
|
||||
void readAsync(int count, void* buf, void (*handle)(int count, void* buf, void* ctx), void* ctx);
|
||||
|
||||
bool isOpen();
|
||||
void close();
|
||||
|
||||
private:
|
||||
void readWorker();
|
||||
|
||||
bool open = false;
|
||||
|
||||
struct addrinfo* laddr;
|
||||
struct addrinfo* raddr;
|
||||
SocketType type;
|
||||
|
||||
std::queue<ReadHandler> readQueue;
|
||||
std::thread readThread;
|
||||
std::mutex readMtx;
|
||||
std::condition_variable readCnd;
|
||||
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<SocketClass> Socket;
|
||||
|
||||
namespace tcp {
|
||||
struct AcceptHandler {
|
||||
void (*handle)(Socket client, void* ctx);
|
||||
void* ctx;
|
||||
};
|
||||
|
||||
class ListenerClass {
|
||||
public:
|
||||
ListenerClass(struct addrinfo* addr);
|
||||
~ListenerClass();
|
||||
|
||||
Socket accept(int count, void* buf, int timeout);
|
||||
void acceptAsync(void (*handle)(int count, void* buf, void* ctx), void* ctx);
|
||||
|
||||
bool isOpen();
|
||||
void close();
|
||||
|
||||
private:
|
||||
void acceptWorker();
|
||||
|
||||
bool open = false;
|
||||
|
||||
struct addrinfo* addr;
|
||||
|
||||
std::queue<AcceptHandler> acceptQueue;
|
||||
std::thread acceptThread;
|
||||
std::mutex acceptMtx;
|
||||
std::condition_variable acceptCnd;
|
||||
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<ListenerClass> Listener;
|
||||
|
||||
Socket connect(std::string host, int port);
|
||||
Listener listen(std::string host, int port);
|
||||
}
|
||||
|
||||
namespace udp {
|
||||
Socket open(std::string remoteHost, int remotePort, std::string localHost = "", int localPort = -1);
|
||||
}
|
||||
}
|
@ -7,9 +7,9 @@
|
||||
#include <gui/style.h>
|
||||
#include <config.h>
|
||||
#include <options.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <airspy.h>
|
||||
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
SDRPP_MOD_INFO{
|
||||
@ -313,12 +313,12 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
AirspySourceModule* _this = (AirspySourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo(CONCAT("##_airspy_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_airspy_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
_this->selectBySerial(_this->devList[_this->devId]);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
if (_this->selectedSerStr != "") {
|
||||
@ -328,7 +328,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Combo(CONCAT("##_airspy_sr_sel_", _this->name), &_this->srId, _this->sampleRateListTxt.c_str())) {
|
||||
if (SmGui::Combo(CONCAT("##_airspy_sr_sel_", _this->name), &_this->srId, _this->sampleRateListTxt.c_str())) {
|
||||
_this->sampleRate = _this->sampleRateList[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
if (_this->selectedSerStr != "") {
|
||||
@ -338,9 +338,10 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX();
|
||||
if (ImGui::Button(CONCAT("Refresh##_airspy_refr_", _this->name), ImVec2(refreshBtnWdith, 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##_airspy_refr_", _this->name))) {
|
||||
_this->refresh();
|
||||
config.acquire();
|
||||
std::string devSerial = config.conf["device"];
|
||||
@ -349,11 +350,12 @@ private:
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Columns(3, CONCAT("AirspyGainModeColumns##_", _this->name), false);
|
||||
if (ImGui::RadioButton(CONCAT("Sensitive##_airspy_gm_", _this->name), _this->gainMode == 0)) {
|
||||
SmGui::BeginGroup();
|
||||
SmGui::Columns(3, CONCAT("AirspyGainModeColumns##_", _this->name), false);
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::RadioButton(CONCAT("Sensitive##_airspy_gm_", _this->name), _this->gainMode == 0)) {
|
||||
_this->gainMode = 0;
|
||||
if (_this->running) {
|
||||
airspy_set_lna_agc(_this->openDev, 0);
|
||||
@ -366,8 +368,9 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton(CONCAT("Linear##_airspy_gm_", _this->name), _this->gainMode == 1)) {
|
||||
SmGui::NextColumn();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::RadioButton(CONCAT("Linear##_airspy_gm_", _this->name), _this->gainMode == 1)) {
|
||||
_this->gainMode = 1;
|
||||
if (_this->running) {
|
||||
airspy_set_lna_agc(_this->openDev, 0);
|
||||
@ -380,8 +383,9 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton(CONCAT("Free##_airspy_gm_", _this->name), _this->gainMode == 2)) {
|
||||
SmGui::NextColumn();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::RadioButton(CONCAT("Free##_airspy_gm_", _this->name), _this->gainMode == 2)) {
|
||||
_this->gainMode = 2;
|
||||
if (_this->running) {
|
||||
if (_this->lnaAgc) {
|
||||
@ -406,15 +410,15 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
ImGui::Columns(1, CONCAT("EndAirspyGainModeColumns##_", _this->name), false);
|
||||
ImGui::EndGroup();
|
||||
SmGui::Columns(1, CONCAT("EndAirspyGainModeColumns##_", _this->name), false);
|
||||
SmGui::EndGroup();
|
||||
|
||||
// Gain menus
|
||||
|
||||
if (_this->gainMode == 0) {
|
||||
ImGui::LeftLabel("Gain");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderInt(CONCAT("##_airspy_sens_gain_", _this->name), &_this->sensitiveGain, 0, 21)) {
|
||||
SmGui::LeftLabel("Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt(CONCAT("##_airspy_sens_gain_", _this->name), &_this->sensitiveGain, 0, 21)) {
|
||||
if (_this->running) {
|
||||
airspy_set_sensitivity_gain(_this->openDev, _this->sensitiveGain);
|
||||
}
|
||||
@ -426,9 +430,9 @@ private:
|
||||
}
|
||||
}
|
||||
else if (_this->gainMode == 1) {
|
||||
ImGui::LeftLabel("Gain");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderInt(CONCAT("##_airspy_lin_gain_", _this->name), &_this->linearGain, 0, 21)) {
|
||||
SmGui::LeftLabel("Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt(CONCAT("##_airspy_lin_gain_", _this->name), &_this->linearGain, 0, 21)) {
|
||||
if (_this->running) {
|
||||
airspy_set_linearity_gain(_this->openDev, _this->linearGain);
|
||||
}
|
||||
@ -440,14 +444,11 @@ private:
|
||||
}
|
||||
}
|
||||
else if (_this->gainMode == 2) {
|
||||
// Calculate position of sliders
|
||||
float pos = ImGui::CalcTextSize("Mixer Gain").x + 10;
|
||||
|
||||
if (_this->lnaAgc) { style::beginDisabled(); }
|
||||
ImGui::LeftLabel("LNA Gain");
|
||||
ImGui::SetCursorPosX(pos);
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderInt(CONCAT("##_airspy_lna_gain_", _this->name), &_this->lnaGain, 0, 15)) {
|
||||
// TODO: Switch to a table for alignement
|
||||
if (_this->lnaAgc) { SmGui::BeginDisabled(); }
|
||||
SmGui::LeftLabel("LNA Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt(CONCAT("##_airspy_lna_gain_", _this->name), &_this->lnaGain, 0, 15)) {
|
||||
if (_this->running) {
|
||||
airspy_set_lna_gain(_this->openDev, _this->lnaGain);
|
||||
}
|
||||
@ -457,13 +458,12 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
if (_this->lnaAgc) { style::endDisabled(); }
|
||||
if (_this->lnaAgc) { SmGui::EndDisabled(); }
|
||||
|
||||
if (_this->mixerAgc) { style::beginDisabled(); }
|
||||
ImGui::LeftLabel("Mixer Gain");
|
||||
ImGui::SetCursorPosX(pos);
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderInt(CONCAT("##_airspy_mix_gain_", _this->name), &_this->mixerGain, 0, 15)) {
|
||||
if (_this->mixerAgc) { SmGui::BeginDisabled(); }
|
||||
SmGui::LeftLabel("Mixer Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt(CONCAT("##_airspy_mix_gain_", _this->name), &_this->mixerGain, 0, 15)) {
|
||||
if (_this->running) {
|
||||
airspy_set_mixer_gain(_this->openDev, _this->mixerGain);
|
||||
}
|
||||
@ -473,12 +473,11 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
if (_this->mixerAgc) { style::endDisabled(); }
|
||||
if (_this->mixerAgc) { SmGui::EndDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("VGA Gain");
|
||||
ImGui::SetCursorPosX(pos);
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderInt(CONCAT("##_airspy_vga_gain_", _this->name), &_this->vgaGain, 0, 15)) {
|
||||
SmGui::LeftLabel("VGA Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt(CONCAT("##_airspy_vga_gain_", _this->name), &_this->vgaGain, 0, 15)) {
|
||||
if (_this->running) {
|
||||
airspy_set_vga_gain(_this->openDev, _this->vgaGain);
|
||||
}
|
||||
@ -490,7 +489,8 @@ private:
|
||||
}
|
||||
|
||||
// AGC Control
|
||||
if (ImGui::Checkbox(CONCAT("LNA AGC##_airspy_", _this->name), &_this->lnaAgc)) {
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Checkbox(CONCAT("LNA AGC##_airspy_", _this->name), &_this->lnaAgc)) {
|
||||
if (_this->running) {
|
||||
if (_this->lnaAgc) {
|
||||
airspy_set_lna_agc(_this->openDev, 1);
|
||||
@ -506,7 +506,8 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("Mixer AGC##_airspy_", _this->name), &_this->mixerAgc)) {
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Checkbox(CONCAT("Mixer AGC##_airspy_", _this->name), &_this->mixerAgc)) {
|
||||
if (_this->running) {
|
||||
if (_this->mixerAgc) {
|
||||
airspy_set_mixer_agc(_this->openDev, 1);
|
||||
@ -525,8 +526,7 @@ private:
|
||||
}
|
||||
|
||||
// Bias T
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("Bias T##_airspy_", _this->name), &_this->biasT)) {
|
||||
if (SmGui::Checkbox(CONCAT("Bias T##_airspy_", _this->name), &_this->biasT)) {
|
||||
if (_this->running) {
|
||||
airspy_set_rf_bias(_this->openDev, _this->biasT);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <module.h>
|
||||
#include <gui/gui.h>
|
||||
@ -7,6 +6,7 @@
|
||||
#include <gui/style.h>
|
||||
#include <config.h>
|
||||
#include <options.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <airspyhf.h>
|
||||
#include <gui/widgets/stepped_slider.h>
|
||||
|
||||
@ -265,12 +265,12 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
AirspyHFSourceModule* _this = (AirspyHFSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo(CONCAT("##_airspyhf_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_airspyhf_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
_this->selectBySerial(_this->devList[_this->devId]);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
if (_this->selectedSerStr != "") {
|
||||
@ -280,7 +280,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Combo(CONCAT("##_airspyhf_sr_sel_", _this->name), &_this->srId, _this->sampleRateListTxt.c_str())) {
|
||||
if (SmGui::Combo(CONCAT("##_airspyhf_sr_sel_", _this->name), &_this->srId, _this->sampleRateListTxt.c_str())) {
|
||||
_this->sampleRate = _this->sampleRateList[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
if (_this->selectedSerStr != "") {
|
||||
@ -290,9 +290,10 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX();
|
||||
if (ImGui::Button(CONCAT("Refresh##_airspyhf_refr_", _this->name), ImVec2(refreshBtnWdith, 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##_airspyhf_refr_", _this->name))) {
|
||||
_this->refresh();
|
||||
config.acquire();
|
||||
std::string devSerial = config.conf["device"];
|
||||
@ -301,11 +302,11 @@ private:
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("AGC Mode");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_airspyhf_agc_", _this->name), &_this->agcMode, AGG_MODES_STR)) {
|
||||
SmGui::LeftLabel("AGC Mode");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_airspyhf_agc_", _this->name), &_this->agcMode, AGG_MODES_STR)) {
|
||||
if (_this->running) {
|
||||
airspyhf_set_hf_agc(_this->openDev, (_this->agcMode != 0));
|
||||
if (_this->agcMode > 0) {
|
||||
@ -319,9 +320,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("Attenuation");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloatWithSteps(CONCAT("##_airspyhf_attn_", _this->name), &_this->atten, 0, 48, 6, "%.0f dB")) {
|
||||
SmGui::LeftLabel("Attenuation");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderFloatWithSteps(CONCAT("##_airspyhf_attn_", _this->name), &_this->atten, 0, 48, 6, SmGui::FMT_STR_FLOAT_DB_NO_DECIMAL)) {
|
||||
if (_this->running) {
|
||||
airspyhf_set_hf_att(_this->openDev, _this->atten / 6.0f);
|
||||
}
|
||||
@ -332,7 +333,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("HF LNA##_airspyhf_lna_", _this->name), &_this->hfLNA)) {
|
||||
if (SmGui::Checkbox(CONCAT("HF LNA##_airspyhf_lna_", _this->name), &_this->hfLNA)) {
|
||||
if (_this->running) {
|
||||
airspyhf_set_hf_lna(_this->openDev, _this->hfLNA);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <gui/widgets/stepped_slider.h>
|
||||
#include <libbladeRF.h>
|
||||
#include <dsp/processing.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <algorithm>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
@ -426,12 +427,12 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
BladeRFSourceModule* _this = (BladeRFSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo(CONCAT("##_balderf_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_balderf_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
bladerf_devinfo info = _this->devInfoList[_this->devId];
|
||||
_this->selectByInfo(&info);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
@ -440,7 +441,7 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Combo(CONCAT("##_balderf_sr_sel_", _this->name), &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
if (SmGui::Combo(CONCAT("##_balderf_sr_sel_", _this->name), &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
_this->sampleRate = _this->sampleRates[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
if (_this->selectedSerial != "") {
|
||||
@ -451,9 +452,10 @@ private:
|
||||
}
|
||||
|
||||
// Refresh button
|
||||
ImGui::SameLine();
|
||||
float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX();
|
||||
if (ImGui::Button(CONCAT("Refresh##_balderf_refr_", _this->name), ImVec2(refreshBtnWdith, 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##_balderf_refr_", _this->name))) {
|
||||
_this->refresh();
|
||||
_this->selectBySerial(_this->selectedSerial, false);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
@ -461,9 +463,9 @@ private:
|
||||
|
||||
// Channel selection (only show if more than one channel)
|
||||
if (_this->channelCount > 1) {
|
||||
ImGui::LeftLabel("RX Channel");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
ImGui::Combo(CONCAT("##_balderf_ch_sel_", _this->name), &_this->chanId, _this->channelNamesTxt.c_str());
|
||||
SmGui::LeftLabel("RX Channel");
|
||||
SmGui::FillWidth();
|
||||
SmGui::Combo(CONCAT("##_balderf_ch_sel_", _this->name), &_this->chanId, _this->channelNamesTxt.c_str());
|
||||
if (_this->selectedSerial != "") {
|
||||
config.acquire();
|
||||
config.conf["devices"][_this->selectedSerial]["channelId"] = _this->chanId;
|
||||
@ -471,11 +473,11 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("Bandwidth");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_balderf_bw_sel_", _this->name), &_this->bwId, _this->bandwidthsTxt.c_str())) {
|
||||
SmGui::LeftLabel("Bandwidth");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_balderf_bw_sel_", _this->name), &_this->bwId, _this->bandwidthsTxt.c_str())) {
|
||||
if (_this->running) {
|
||||
bladerf_set_bandwidth(_this->openDev, BLADERF_CHANNEL_RX(_this->chanId), (_this->bwId == _this->bandwidths.size()) ? std::clamp<uint64_t>(_this->sampleRate, _this->bwRange->min, _this->bwRange->max) : _this->bandwidths[_this->bwId], NULL);
|
||||
}
|
||||
@ -487,9 +489,10 @@ private:
|
||||
}
|
||||
|
||||
// General config BS
|
||||
ImGui::LeftLabel("Gain control mode");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_balderf_gm_sel_", _this->name), &_this->gainMode, _this->gainModesTxt.c_str()) && _this->selectedSerial != "") {
|
||||
SmGui::LeftLabel("Gain control mode");
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_balderf_gm_sel_", _this->name), &_this->gainMode, _this->gainModesTxt.c_str()) && _this->selectedSerial != "") {
|
||||
if (_this->running) {
|
||||
bladerf_set_gain_mode(_this->openDev, BLADERF_CHANNEL_RX(_this->chanId), _this->gainModes[_this->gainMode].mode);
|
||||
}
|
||||
@ -505,11 +508,11 @@ private:
|
||||
}
|
||||
|
||||
if (_this->selectedSerial != "") {
|
||||
if (_this->gainModes[_this->gainMode].mode != BLADERF_GAIN_MANUAL) { style::beginDisabled(); }
|
||||
if (_this->gainModes[_this->gainMode].mode != BLADERF_GAIN_MANUAL) { SmGui::BeginDisabled(); }
|
||||
}
|
||||
ImGui::LeftLabel("Gain");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderInt("##_balderf_oag_sel_", &_this->overallGain, (_this->gainRange != NULL) ? _this->gainRange->min : 0, (_this->gainRange != NULL) ? _this->gainRange->max : 60)) {
|
||||
SmGui::LeftLabel("Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt("##_balderf_oag_sel_", &_this->overallGain, (_this->gainRange != NULL) ? _this->gainRange->min : 0, (_this->gainRange != NULL) ? _this->gainRange->max : 60)) {
|
||||
if (_this->running) {
|
||||
spdlog::info("Setting gain to {0}", _this->overallGain);
|
||||
bladerf_set_gain(_this->openDev, BLADERF_CHANNEL_RX(_this->chanId), _this->overallGain);
|
||||
@ -521,11 +524,11 @@ private:
|
||||
}
|
||||
}
|
||||
if (_this->selectedSerial != "") {
|
||||
if (_this->gainModes[_this->gainMode].mode != BLADERF_GAIN_MANUAL) { style::endDisabled(); }
|
||||
if (_this->gainModes[_this->gainMode].mode != BLADERF_GAIN_MANUAL) { SmGui::EndDisabled(); }
|
||||
}
|
||||
|
||||
if (_this->selectedBladeType == BLADERF_TYPE_V2) {
|
||||
if (ImGui::Checkbox("Bias-T##_balderf_biast_", &_this->biasT)) {
|
||||
if (SmGui::Checkbox("Bias-T##_balderf_biast_", &_this->biasT)) {
|
||||
if (_this->running) {
|
||||
bladerf_set_bias_tee(_this->openDev, BLADERF_CHANNEL_RX(_this->chanId), _this->biasT);
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ public:
|
||||
FileSourceModule(std::string name) : fileSelect("", { "Wav IQ Files (*.wav)", "*.wav", "All Files", "*" }) {
|
||||
this->name = name;
|
||||
|
||||
if (options::opts.serverMode) { return; }
|
||||
|
||||
config.acquire();
|
||||
fileSelect.setPath(config.conf["path"], true);
|
||||
config.release();
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <module.h>
|
||||
#include <gui/gui.h>
|
||||
@ -9,6 +8,7 @@
|
||||
#include <libhackrf/hackrf.h>
|
||||
#include <gui/widgets/stepped_slider.h>
|
||||
#include <options.h>
|
||||
#include <gui/smgui.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
@ -275,19 +275,18 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
HackRFSourceModule* _this = (HackRFSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo(CONCAT("##_hackrf_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
_this->selectedSerial = _this->devList[_this->devId];
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_hackrf_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
_this->selectBySerial(_this->devList[_this->devId]);
|
||||
config.acquire();
|
||||
config.conf["device"] = _this->selectedSerial;
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Combo(CONCAT("##_hackrf_sr_sel_", _this->name), &_this->srId, sampleRatesTxt)) {
|
||||
if (SmGui::Combo(CONCAT("##_hackrf_sr_sel_", _this->name), &_this->srId, sampleRatesTxt)) {
|
||||
_this->sampleRate = sampleRates[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
config.acquire();
|
||||
@ -295,19 +294,20 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX();
|
||||
if (ImGui::Button(CONCAT("Refresh##_hackrf_refr_", _this->name), ImVec2(refreshBtnWdith, 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##_hackrf_refr_", _this->name))) {
|
||||
_this->refresh();
|
||||
_this->selectBySerial(_this->selectedSerial);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("Bandwidth");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_hackrf_bw_sel_", _this->name), &_this->bwId, bandwidthsTxt)) {
|
||||
SmGui::LeftLabel("Bandwidth");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_hackrf_bw_sel_", _this->name), &_this->bwId, bandwidthsTxt)) {
|
||||
if (_this->running) {
|
||||
hackrf_set_baseband_filter_bandwidth(_this->openDev, _this->bandwidthIdToBw(_this->bwId));
|
||||
}
|
||||
@ -316,9 +316,9 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("LNA Gain");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloatWithSteps(CONCAT("##_hackrf_lna_", _this->name), &_this->lna, 0, 40, 8, "%.0fdB")) {
|
||||
SmGui::LeftLabel("LNA Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderFloatWithSteps(CONCAT("##_hackrf_lna_", _this->name), &_this->lna, 0, 40, 8, SmGui::FMT_STR_FLOAT_DB_NO_DECIMAL)) {
|
||||
if (_this->running) {
|
||||
hackrf_set_lna_gain(_this->openDev, _this->lna);
|
||||
}
|
||||
@ -327,9 +327,9 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("VGA Gain");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloatWithSteps(CONCAT("##_hackrf_vga_", _this->name), &_this->vga, 0, 62, 2, "%.0fdB")) {
|
||||
SmGui::LeftLabel("VGA Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderFloatWithSteps(CONCAT("##_hackrf_vga_", _this->name), &_this->vga, 0, 62, 2, SmGui::FMT_STR_FLOAT_DB_NO_DECIMAL)) {
|
||||
if (_this->running) {
|
||||
hackrf_set_vga_gain(_this->openDev, _this->vga);
|
||||
}
|
||||
@ -338,7 +338,7 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("Bias-T##_hackrf_bt_", _this->name), &_this->biasT)) {
|
||||
if (SmGui::Checkbox(CONCAT("Bias-T##_hackrf_bt_", _this->name), &_this->biasT)) {
|
||||
if (_this->running) {
|
||||
hackrf_set_antenna_enable(_this->openDev, _this->biasT);
|
||||
}
|
||||
@ -347,7 +347,7 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("Amp Enabled##_hackrf_amp_", _this->name), &_this->amp)) {
|
||||
if (SmGui::Checkbox(CONCAT("Amp Enabled##_hackrf_amp_", _this->name), &_this->amp)) {
|
||||
if (_this->running) {
|
||||
hackrf_set_amp_enable(_this->openDev, _this->amp);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <module.h>
|
||||
#include <gui/gui.h>
|
||||
@ -7,6 +6,7 @@
|
||||
#include <gui/style.h>
|
||||
#include <config.h>
|
||||
#include <options.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <lime/LimeSuite.h>
|
||||
|
||||
|
||||
@ -382,12 +382,12 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
LimeSDRSourceModule* _this = (LimeSDRSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo("##limesdr_dev_sel", &_this->devId, _this->devListTxt.c_str())) {
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo("##limesdr_dev_sel", &_this->devId, _this->devListTxt.c_str())) {
|
||||
_this->selectByInfoStr(_this->devList[_this->devId]);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
config.acquire();
|
||||
@ -395,7 +395,7 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Combo(CONCAT("##_limesdr_sr_sel_", _this->name), &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
if (SmGui::Combo(CONCAT("##_limesdr_sr_sel_", _this->name), &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
_this->sampleRate = _this->sampleRates[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
if (_this->selectedDevName != "") {
|
||||
@ -406,29 +406,30 @@ private:
|
||||
}
|
||||
|
||||
// Refresh button
|
||||
ImGui::SameLine();
|
||||
float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX();
|
||||
if (ImGui::Button(CONCAT("Refresh##_limesdr_refr_", _this->name), ImVec2(refreshBtnWdith, 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##_limesdr_refr_", _this->name))) {
|
||||
_this->refresh();
|
||||
_this->selectByName(_this->selectedDevName);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
}
|
||||
|
||||
if (_this->channelCount > 1) {
|
||||
ImGui::LeftLabel("RX Channel");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##limesdr_ch_sel", &_this->chanId, _this->channelNamesTxt.c_str()) && _this->selectedDevName != "") {
|
||||
SmGui::LeftLabel("RX Channel");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo("##limesdr_ch_sel", &_this->chanId, _this->channelNamesTxt.c_str()) && _this->selectedDevName != "") {
|
||||
config.acquire();
|
||||
config.conf["devices"][_this->selectedDevName]["channel"] = _this->chanId;
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("Antenna");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##limesdr_ant_sel", &_this->antennaId, _this->antennaListTxt.c_str())) {
|
||||
SmGui::LeftLabel("Antenna");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo("##limesdr_ant_sel", &_this->antennaId, _this->antennaListTxt.c_str())) {
|
||||
if (_this->running) {
|
||||
LMS_SetAntenna(_this->openDev, false, _this->chanId, _this->antennaId);
|
||||
}
|
||||
@ -439,9 +440,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("Bandwidth");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##limesdr_bw_sel", &_this->bwId, _this->bandwidthsTxt.c_str())) {
|
||||
SmGui::LeftLabel("Bandwidth");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo("##limesdr_bw_sel", &_this->bwId, _this->bandwidthsTxt.c_str())) {
|
||||
if (_this->running) {
|
||||
LMS_SetLPFBW(_this->openDev, false, _this->chanId, (_this->bwId == _this->bandwidths.size()) ? _this->getBestBandwidth(_this->sampleRate) : _this->bandwidths[_this->bwId]);
|
||||
}
|
||||
@ -452,9 +453,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("Gain");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderInt("##limesdr_gain_sel", &_this->gain, 0, 73, "%ddB")) {
|
||||
SmGui::LeftLabel("Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt("##limesdr_gain_sel", &_this->gain, 0, 73, SmGui::FMT_STR_INT_DB)) {
|
||||
if (_this->running) {
|
||||
LMS_SetGaindB(_this->openDev, false, _this->chanId, _this->gain);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <module.h>
|
||||
#include <gui/gui.h>
|
||||
#include <signal_path/signal_path.h>
|
||||
#include <core.h>
|
||||
#include <gui/style.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <iio.h>
|
||||
#include <ad9361.h>
|
||||
#include <options.h>
|
||||
@ -185,32 +185,31 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
ImGui::LeftLabel("IP");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::InputText(CONCAT("##_pluto_ip_", _this->name), &_this->ip[3], 16)) {
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
SmGui::LeftLabel("IP");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::InputText(CONCAT("##_pluto_ip_", _this->name), &_this->ip[3], 16)) {
|
||||
config.acquire();
|
||||
config.conf["IP"] = &_this->ip[3];
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("Samplerate");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
|
||||
if (ImGui::Combo(CONCAT("##_pluto_sr_", _this->name), &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
SmGui::LeftLabel("Samplerate");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_pluto_sr_", _this->name), &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
_this->sampleRate = _this->sampleRates[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
config.acquire();
|
||||
config.conf["sampleRate"] = _this->sampleRate;
|
||||
config.release(true);
|
||||
}
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("Gain Mode");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_gainmode_select_", _this->name), &_this->gainMode, gainModesTxt)) {
|
||||
SmGui::LeftLabel("Gain Mode");
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_gainmode_select_", _this->name), &_this->gainMode, gainModesTxt)) {
|
||||
if (_this->running) {
|
||||
iio_channel_attr_write(iio_device_find_channel(_this->phy, "voltage0", false), "gain_control_mode", gainModes[_this->gainMode]);
|
||||
}
|
||||
@ -219,10 +218,10 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("PGA Gain");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (_this->gainMode) { style::beginDisabled(); }
|
||||
if (ImGui::SliderFloat(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 76)) {
|
||||
SmGui::LeftLabel("PGA Gain");
|
||||
if (_this->gainMode) { SmGui::BeginDisabled(); }
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderFloat(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 76)) {
|
||||
if (_this->running) {
|
||||
iio_channel_attr_write_longlong(iio_device_find_channel(_this->phy, "voltage0", false), "hardwaregain", round(_this->gain));
|
||||
}
|
||||
@ -230,7 +229,7 @@ private:
|
||||
config.conf["gain"] = _this->gain;
|
||||
config.release(true);
|
||||
}
|
||||
if (_this->gainMode) { style::endDisabled(); }
|
||||
if (_this->gainMode) { SmGui::EndDisabled(); }
|
||||
}
|
||||
|
||||
static void worker(void* ctx) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <options.h>
|
||||
#include <gui/widgets/stepped_slider.h>
|
||||
#include <utils/optionlist.h>
|
||||
#include <gui/smgui.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
@ -23,9 +24,9 @@ SDRPP_MOD_INFO{
|
||||
|
||||
ConfigManager config;
|
||||
|
||||
class RFSpaceSource : public ModuleManager::Instance {
|
||||
class RFSpaceSourceModule : public ModuleManager::Instance {
|
||||
public:
|
||||
RFSpaceSource(std::string name) {
|
||||
RFSpaceSourceModule(std::string name) {
|
||||
this->name = name;
|
||||
|
||||
handler.ctx = this;
|
||||
@ -47,7 +48,7 @@ public:
|
||||
sigpath::sourceManager.registerSource("RFspace", &handler);
|
||||
}
|
||||
|
||||
~RFSpaceSource() {
|
||||
~RFSpaceSourceModule() {
|
||||
stop(this);
|
||||
sigpath::sourceManager.unregisterSource("RFspace");
|
||||
}
|
||||
@ -82,72 +83,73 @@ private:
|
||||
}
|
||||
|
||||
static void menuSelected(void* ctx) {
|
||||
RFSpaceSource* _this = (RFSpaceSource*)ctx;
|
||||
RFSpaceSourceModule* _this = (RFSpaceSourceModule*)ctx;
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
gui::mainWindow.playButtonLocked = !(_this->client && _this->client->isOpen());
|
||||
spdlog::info("RFSpaceSource '{0}': Menu Select!", _this->name);
|
||||
spdlog::info("RFSpaceSourceModule '{0}': Menu Select!", _this->name);
|
||||
}
|
||||
|
||||
static void menuDeselected(void* ctx) {
|
||||
RFSpaceSource* _this = (RFSpaceSource*)ctx;
|
||||
RFSpaceSourceModule* _this = (RFSpaceSourceModule*)ctx;
|
||||
gui::mainWindow.playButtonLocked = false;
|
||||
spdlog::info("RFSpaceSource '{0}': Menu Deselect!", _this->name);
|
||||
spdlog::info("RFSpaceSourceModule '{0}': Menu Deselect!", _this->name);
|
||||
}
|
||||
|
||||
static void start(void* ctx) {
|
||||
RFSpaceSource* _this = (RFSpaceSource*)ctx;
|
||||
RFSpaceSourceModule* _this = (RFSpaceSourceModule*)ctx;
|
||||
if (_this->running) { return; }
|
||||
|
||||
// TODO: Set configuration here
|
||||
if (_this->client) { _this->client->start(rfspace::RFSPACE_SAMP_FORMAT_COMPLEX, rfspace::RFSPACE_SAMP_FORMAT_16BIT); }
|
||||
|
||||
_this->running = true;
|
||||
spdlog::info("RFSpaceSource '{0}': Start!", _this->name);
|
||||
spdlog::info("RFSpaceSourceModule '{0}': Start!", _this->name);
|
||||
}
|
||||
|
||||
static void stop(void* ctx) {
|
||||
RFSpaceSource* _this = (RFSpaceSource*)ctx;
|
||||
RFSpaceSourceModule* _this = (RFSpaceSourceModule*)ctx;
|
||||
if (!_this->running) { return; }
|
||||
|
||||
if (_this->client) { _this->client->stop(); }
|
||||
|
||||
_this->running = false;
|
||||
spdlog::info("RFSpaceSource '{0}': Stop!", _this->name);
|
||||
spdlog::info("RFSpaceSourceModule '{0}': Stop!", _this->name);
|
||||
}
|
||||
|
||||
static void tune(double freq, void* ctx) {
|
||||
RFSpaceSource* _this = (RFSpaceSource*)ctx;
|
||||
RFSpaceSourceModule* _this = (RFSpaceSourceModule*)ctx;
|
||||
if (_this->running && _this->client) {
|
||||
_this->client->setFrequency(freq);
|
||||
}
|
||||
_this->freq = freq;
|
||||
spdlog::info("RFSpaceSource '{0}': Tune: {1}!", _this->name, freq);
|
||||
spdlog::info("RFSpaceSourceModule '{0}': Tune: {1}!", _this->name, freq);
|
||||
}
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
RFSpaceSource* _this = (RFSpaceSource*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
RFSpaceSourceModule* _this = (RFSpaceSourceModule*)ctx;
|
||||
|
||||
bool connected = (_this->client && _this->client->isOpen());
|
||||
gui::mainWindow.playButtonLocked = !connected;
|
||||
|
||||
if (connected) { style::beginDisabled(); }
|
||||
if (ImGui::InputText(CONCAT("##_rfspace_srv_host_", _this->name), _this->hostname, 1023)) {
|
||||
if (connected) { SmGui::BeginDisabled(); }
|
||||
if (SmGui::InputText(CONCAT("##_rfspace_srv_host_", _this->name), _this->hostname, 1023)) {
|
||||
config.acquire();
|
||||
config.conf["hostname"] = _this->hostname;
|
||||
config.release(true);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::InputInt(CONCAT("##_rfspace_srv_port_", _this->name), &_this->port, 0, 0)) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::InputInt(CONCAT("##_rfspace_srv_port_", _this->name), &_this->port, 0, 0)) {
|
||||
config.acquire();
|
||||
config.conf["port"] = _this->port;
|
||||
config.release(true);
|
||||
}
|
||||
if (connected) { style::endDisabled(); }
|
||||
if (connected) { SmGui::EndDisabled(); }
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (!connected && ImGui::Button("Connect##rfspace_source", ImVec2(menuWidth, 0))) {
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (!connected && SmGui::Button("Connect##rfspace_source")) {
|
||||
try {
|
||||
if (_this->client) { _this->client.reset(); }
|
||||
_this->client = rfspace::connect(_this->hostname, _this->port, &_this->stream);
|
||||
@ -157,18 +159,18 @@ private:
|
||||
spdlog::error("Could not connect to SDR: {0}", e.what());
|
||||
}
|
||||
}
|
||||
else if (connected && ImGui::Button("Disconnect##rfspace_source", ImVec2(menuWidth, 0))) {
|
||||
else if (connected && SmGui::Button("Disconnect##rfspace_source")) {
|
||||
_this->client->close();
|
||||
}
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
|
||||
if (connected) {
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("Samplerate");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##rfspace_source_samp_rate", &_this->srId, _this->sampleRates.txt)) {
|
||||
SmGui::LeftLabel("Samplerate");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo("##rfspace_source_samp_rate", &_this->srId, _this->sampleRates.txt)) {
|
||||
_this->sampleRate = _this->sampleRates[_this->srId];
|
||||
_this->client->setSampleRate(_this->sampleRate);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
@ -178,12 +180,12 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
if (_this->client->deviceId == rfspace::RFSPACE_DEV_ID_CLOUD_IQ) {
|
||||
ImGui::LeftLabel("Antenna Port");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##rfspace_source_rf_port", &_this->rfPortId, _this->rfPorts.txt)) {
|
||||
SmGui::LeftLabel("Antenna Port");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo("##rfspace_source_rf_port", &_this->rfPortId, _this->rfPorts.txt)) {
|
||||
_this->client->setPort(_this->rfPorts[_this->rfPortId]);
|
||||
|
||||
config.acquire();
|
||||
@ -192,9 +194,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("Gain");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloatWithSteps("##rfspace_source_gain", &_this->gain, -30, 0, 10, "%.0f dB")) {
|
||||
SmGui::LeftLabel("Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderFloatWithSteps("##rfspace_source_gain", &_this->gain, -30, 0, 10, SmGui::FMT_STR_FLOAT_DB_NO_DECIMAL)) {
|
||||
_this->client->setGain(_this->gain);
|
||||
|
||||
config.acquire();
|
||||
@ -202,14 +204,14 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("Status:");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "Connected (%s)", _this->deviceName.c_str());
|
||||
SmGui::Text("Status:");
|
||||
SmGui::SameLine();
|
||||
SmGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), _this->connectedStr.c_str());
|
||||
}
|
||||
else {
|
||||
ImGui::Text("Status:");
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Not connected");
|
||||
SmGui::Text("Status:");
|
||||
SmGui::SameLine();
|
||||
SmGui::Text("Not connected");
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,6 +220,8 @@ private:
|
||||
char buf[4096];
|
||||
sprintf(buf, "%s:%05d", hostname, port);
|
||||
devConfName = buf;
|
||||
sprintf(buf, "Connected (%s:%05d)", hostname, port);
|
||||
connectedStr = buf;
|
||||
|
||||
// Get device name
|
||||
if (deviceNames.find(client->deviceId) != deviceNames.end()) {
|
||||
@ -301,6 +305,7 @@ private:
|
||||
char hostname[1024];
|
||||
int port = 50000;
|
||||
std::string devConfName = "";
|
||||
std::string connectedStr = "";
|
||||
|
||||
std::string deviceName = "Unknown";
|
||||
std::map<rfspace::DeviceID, std::string> deviceNames = {
|
||||
@ -321,7 +326,7 @@ MOD_EXPORT void _INIT_() {
|
||||
def["hostname"] = "192.168.0.111";
|
||||
def["port"] = 50000;
|
||||
def["devices"] = json::object();
|
||||
config.setPath(options::opts.root + "/rfspace_config.json");
|
||||
config.setPath(options::opts.root + "/rfspace_source_config.json");
|
||||
config.load(def);
|
||||
config.enableAutoSave();
|
||||
|
||||
@ -336,11 +341,11 @@ MOD_EXPORT void _INIT_() {
|
||||
}
|
||||
|
||||
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
|
||||
return new RFSpaceSource(name);
|
||||
return new RFSpaceSourceModule(name);
|
||||
}
|
||||
|
||||
MOD_EXPORT void _DELETE_INSTANCE_(ModuleManager::Instance* instance) {
|
||||
delete (RFSpaceSource*)instance;
|
||||
delete (RFSpaceSourceModule*)instance;
|
||||
}
|
||||
|
||||
MOD_EXPORT void _END_() {
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <module.h>
|
||||
#include <gui/gui.h>
|
||||
@ -7,6 +6,7 @@
|
||||
#include <gui/style.h>
|
||||
#include <config.h>
|
||||
#include <options.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <rtl-sdr.h>
|
||||
|
||||
|
||||
@ -315,12 +315,11 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
RTLSDRSourceModule* _this = (RTLSDRSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo(CONCAT("##_rtlsdr_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_rtlsdr_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
_this->selectById(_this->devId);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
if (_this->selectedDevName != "") {
|
||||
@ -330,7 +329,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Combo(CONCAT("##_rtlsdr_sr_sel_", _this->name), &_this->srId, _this->sampleRateListTxt.c_str())) {
|
||||
if (SmGui::Combo(CONCAT("##_rtlsdr_sr_sel_", _this->name), &_this->srId, _this->sampleRateListTxt.c_str())) {
|
||||
_this->sampleRate = sampleRates[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
if (_this->selectedDevName != "") {
|
||||
@ -340,20 +339,21 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX();
|
||||
if (ImGui::Button(CONCAT("Refresh##_rtlsdr_refr_", _this->name), ImVec2(refreshBtnWdith, 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##_rtlsdr_refr_", _this->name)/*, ImVec2(refreshBtnWdith, 0)*/)) {
|
||||
_this->refresh();
|
||||
_this->selectByName(_this->selectedDevName);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
// Rest of rtlsdr config here
|
||||
ImGui::LeftLabel("Direct Sampling");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_rtlsdr_ds_", _this->name), &_this->directSamplingMode, directSamplingModesTxt)) {
|
||||
SmGui::LeftLabel("Direct Sampling");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_rtlsdr_ds_", _this->name), &_this->directSamplingMode, directSamplingModesTxt)) {
|
||||
if (_this->running) {
|
||||
rtlsdr_set_direct_sampling(_this->openDev, _this->directSamplingMode);
|
||||
|
||||
@ -376,9 +376,9 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("PPM Correction");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::InputInt(CONCAT("##_rtlsdr_ppm_", _this->name), &_this->ppm, 1, 10)) {
|
||||
SmGui::LeftLabel("PPM Correction");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::InputInt(CONCAT("##_rtlsdr_ppm_", _this->name), &_this->ppm, 1, 10)) {
|
||||
_this->ppm = std::clamp<int>(_this->ppm, -1000000, 1000000);
|
||||
if (_this->running) {
|
||||
rtlsdr_set_freq_correction(_this->openDev, _this->ppm);
|
||||
@ -390,22 +390,42 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->tunerAgc || _this->gainList.size() == 0) { style::beginDisabled(); }
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::SliderInt(CONCAT("##_rtlsdr_gain_", _this->name), &_this->gainId, 0, _this->gainList.size() - 1, _this->dbTxt)) {
|
||||
_this->updateGainTxt();
|
||||
if (_this->running) {
|
||||
rtlsdr_set_tuner_gain(_this->openDev, _this->gainList[_this->gainId]);
|
||||
}
|
||||
if (_this->selectedDevName != "") {
|
||||
config.acquire();
|
||||
config.conf["devices"][_this->selectedDevName]["gain"] = _this->gainId;
|
||||
config.release(true);
|
||||
if (_this->tunerAgc || _this->gainList.size() == 0) { SmGui::BeginDisabled(); }
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
|
||||
// TODO: FIND ANOTHER WAY
|
||||
if (options::opts.serverMode) {
|
||||
if (SmGui::SliderInt(CONCAT("##_rtlsdr_gain_", _this->name), &_this->gainId, 0, _this->gainList.size() - 1, SmGui::FMT_STR_NONE)) {
|
||||
_this->updateGainTxt();
|
||||
if (_this->running) {
|
||||
rtlsdr_set_tuner_gain(_this->openDev, _this->gainList[_this->gainId]);
|
||||
}
|
||||
if (_this->selectedDevName != "") {
|
||||
config.acquire();
|
||||
config.conf["devices"][_this->selectedDevName]["gain"] = _this->gainId;
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ImGui::SliderInt(CONCAT("##_rtlsdr_gain_", _this->name), &_this->gainId, 0, _this->gainList.size() - 1, _this->dbTxt)) {
|
||||
_this->updateGainTxt();
|
||||
if (_this->running) {
|
||||
rtlsdr_set_tuner_gain(_this->openDev, _this->gainList[_this->gainId]);
|
||||
}
|
||||
if (_this->selectedDevName != "") {
|
||||
config.acquire();
|
||||
config.conf["devices"][_this->selectedDevName]["gain"] = _this->gainId;
|
||||
config.release(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_this->tunerAgc || _this->gainList.size() == 0) { style::endDisabled(); }
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("Bias T##_rtlsdr_rtl_biast_", _this->name), &_this->biasT)) {
|
||||
|
||||
if (_this->tunerAgc || _this->gainList.size() == 0) { SmGui::EndDisabled(); }
|
||||
|
||||
if (SmGui::Checkbox(CONCAT("Bias T##_rtlsdr_rtl_biast_", _this->name), &_this->biasT)) {
|
||||
if (_this->running) {
|
||||
rtlsdr_set_bias_tee(_this->openDev, _this->biasT);
|
||||
}
|
||||
@ -416,7 +436,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("Offset Tuning##_rtlsdr_rtl_ofs_", _this->name), &_this->offsetTuning)) {
|
||||
if (SmGui::Checkbox(CONCAT("Offset Tuning##_rtlsdr_rtl_ofs_", _this->name), &_this->offsetTuning)) {
|
||||
if (_this->running) {
|
||||
rtlsdr_set_offset_tuning(_this->openDev, _this->offsetTuning);
|
||||
}
|
||||
@ -427,7 +447,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("RTL AGC##_rtlsdr_rtl_agc_", _this->name), &_this->rtlAgc)) {
|
||||
if (SmGui::Checkbox(CONCAT("RTL AGC##_rtlsdr_rtl_agc_", _this->name), &_this->rtlAgc)) {
|
||||
if (_this->running) {
|
||||
rtlsdr_set_agc_mode(_this->openDev, _this->rtlAgc);
|
||||
}
|
||||
@ -438,7 +458,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("Tuner AGC##_rtlsdr_tuner_agc_", _this->name), &_this->tunerAgc)) {
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Checkbox(CONCAT("Tuner AGC##_rtlsdr_tuner_agc_", _this->name), &_this->tunerAgc)) {
|
||||
if (_this->running) {
|
||||
if (_this->tunerAgc) {
|
||||
rtlsdr_set_tuner_gain_mode(_this->openDev, 0);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <signal_path/signal_path.h>
|
||||
#include <core.h>
|
||||
#include <options.h>
|
||||
#include <gui/smgui.h>
|
||||
#include <gui/style.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
@ -188,27 +189,24 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
RTLTCPSourceModule* _this = (RTLTCPSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
float portWidth = ImGui::CalcTextSize("00000").x + 20;
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth - portWidth);
|
||||
if (ImGui::InputText(CONCAT("##_ip_select_", _this->name), _this->ip, 1024)) {
|
||||
if (SmGui::InputText(CONCAT("##_ip_select_", _this->name), _this->ip, 1024)) {
|
||||
config.acquire();
|
||||
config.conf["host"] = std::string(_this->ip);
|
||||
config.release(true);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(portWidth);
|
||||
if (ImGui::InputInt(CONCAT("##_port_select_", _this->name), &_this->port, 0)) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::InputInt(CONCAT("##_port_select_", _this->name), &_this->port, 0)) {
|
||||
config.acquire();
|
||||
config.conf["port"] = _this->port;
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo(CONCAT("##_rtltcp_sr_", _this->name), &_this->srId, _this->srTxt.c_str())) {
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_rtltcp_sr_", _this->name), &_this->srId, _this->srTxt.c_str())) {
|
||||
_this->sampleRate = sampleRates[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
config.acquire();
|
||||
@ -216,11 +214,11 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("Direct Sampling");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_rtltcp_ds_", _this->name), &_this->directSamplingMode, "Disabled\0I branch\0Q branch\0")) {
|
||||
SmGui::LeftLabel("Direct Sampling");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_rtltcp_ds_", _this->name), &_this->directSamplingMode, "Disabled\0I branch\0Q branch\0")) {
|
||||
if (_this->running) {
|
||||
_this->client.setDirectSampling(_this->directSamplingMode);
|
||||
_this->client.setGainIndex(_this->gain);
|
||||
@ -230,9 +228,9 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::LeftLabel("PPM Correction");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::InputInt(CONCAT("##_rtltcp_ppm_", _this->name), &_this->ppm, 1, 10)) {
|
||||
SmGui::LeftLabel("PPM Correction");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::InputInt(CONCAT("##_rtltcp_ppm_", _this->name), &_this->ppm, 1, 10)) {
|
||||
if (_this->running) {
|
||||
_this->client.setPPM(_this->ppm);
|
||||
}
|
||||
@ -241,9 +239,9 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (_this->tunerAGC) { style::beginDisabled(); }
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::SliderInt(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 28, "")) {
|
||||
if (_this->tunerAGC) { SmGui::BeginDisabled(); }
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 28, SmGui::FMT_STR_NONE)) {
|
||||
if (_this->running) {
|
||||
_this->client.setGainIndex(_this->gain);
|
||||
}
|
||||
@ -251,9 +249,9 @@ private:
|
||||
config.conf["gainIndex"] = _this->gain;
|
||||
config.release(true);
|
||||
}
|
||||
if (_this->tunerAGC) { style::endDisabled(); }
|
||||
if (_this->tunerAGC) { SmGui::EndDisabled(); }
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("Bias-T##_biast_select_", _this->name), &_this->biasTee)) {
|
||||
if (SmGui::Checkbox(CONCAT("Bias-T##_biast_select_", _this->name), &_this->biasTee)) {
|
||||
if (_this->running) {
|
||||
_this->client.setBiasTee(_this->biasTee);
|
||||
}
|
||||
@ -262,7 +260,7 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("Offset Tuning##_biast_select_", _this->name), &_this->offsetTuning)) {
|
||||
if (SmGui::Checkbox(CONCAT("Offset Tuning##_biast_select_", _this->name), &_this->offsetTuning)) {
|
||||
if (_this->running) {
|
||||
_this->client.setOffsetTuning(_this->offsetTuning);
|
||||
}
|
||||
@ -271,7 +269,7 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("RTL AGC", &_this->rtlAGC)) {
|
||||
if (SmGui::Checkbox("RTL AGC", &_this->rtlAGC)) {
|
||||
if (_this->running) {
|
||||
_this->client.setAGCMode(_this->rtlAGC);
|
||||
if (!_this->rtlAGC) {
|
||||
@ -283,7 +281,8 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("Tuner AGC", &_this->tunerAGC)) {
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Checkbox("Tuner AGC", &_this->tunerAGC)) {
|
||||
if (_this->running) {
|
||||
_this->client.setGainMode(!_this->tunerAGC);
|
||||
if (!_this->tunerAGC) {
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
AirspyHFSourceModule(std::string name) {
|
||||
this->name = name;
|
||||
|
||||
if (options::opts.serverMode) { return; }
|
||||
|
||||
sampleRate = 768000.0;
|
||||
|
||||
handler.ctx = this;
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <config.h>
|
||||
#include <options.h>
|
||||
#include <sdrplay_api.h>
|
||||
|
||||
#include <gui/smgui.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
@ -697,14 +697,12 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
SDRPlaySourceModule* _this = (SDRPlaySourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
|
||||
|
||||
if (ImGui::Combo(CONCAT("##sdrplay_dev", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##sdrplay_dev", _this->name), &_this->devId, _this->devListTxt.c_str())) {
|
||||
_this->selectById(_this->devId);
|
||||
config.acquire();
|
||||
config.conf["device"] = _this->devNameList[_this->devId];
|
||||
@ -712,7 +710,7 @@ private:
|
||||
}
|
||||
|
||||
if (_this->ifModeId == 0) {
|
||||
if (ImGui::Combo(CONCAT("##sdrplay_sr", _this->name), &_this->srId, sampleRatesTxt)) {
|
||||
if (SmGui::Combo(CONCAT("##sdrplay_sr", _this->name), &_this->srId, sampleRatesTxt)) {
|
||||
_this->sampleRate = sampleRates[_this->srId];
|
||||
if (_this->bandwidthId == 8) {
|
||||
_this->bandwidth = preferedBandwidth[_this->srId];
|
||||
@ -723,15 +721,16 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX();
|
||||
if (ImGui::Button(CONCAT("Refresh##sdrplay_refresh", _this->name), ImVec2(refreshBtnWdith, 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##sdrplay_refresh", _this->name))) {
|
||||
_this->refresh();
|
||||
_this->selectByName(_this->selectedName);
|
||||
}
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo(CONCAT("##sdrplay_bw", _this->name), &_this->bandwidthId, bandwidthsTxt)) {
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##sdrplay_bw", _this->name), &_this->bandwidthId, bandwidthsTxt)) {
|
||||
_this->bandwidth = (_this->bandwidthId == 8) ? preferedBandwidth[_this->srId] : bandwidths[_this->bandwidthId];
|
||||
if (_this->running) {
|
||||
_this->channelParams->tunerParams.bwType = _this->bandwidth;
|
||||
@ -743,16 +742,18 @@ private:
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ImGui::Button(CONCAT("Refresh##sdrplay_refresh", _this->name), ImVec2(menuWidth, 0))) {
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##sdrplay_refresh", _this->name))) {
|
||||
_this->refresh();
|
||||
_this->selectByName(_this->selectedName);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Text("IF Mode");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##sdrplay_ifmode", _this->name), &_this->ifModeId, ifModeTxt)) {
|
||||
SmGui::LeftLabel("IF Mode");
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##sdrplay_ifmode", _this->name), &_this->ifModeId, ifModeTxt)) {
|
||||
if (_this->ifModeId != 0) {
|
||||
_this->bandwidth = ifModes[_this->ifModeId].bw;
|
||||
_this->sampleRate = ifModes[_this->ifModeId].effectiveSamplerate;
|
||||
@ -770,13 +771,12 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
if (_this->selectedName != "") {
|
||||
ImGui::PushItemWidth(menuWidth - ImGui::CalcTextSize("LNA Gain").x - 10);
|
||||
ImGui::LeftLabel("LNA Gain");
|
||||
float pos = ImGui::GetCursorPosX();
|
||||
if (ImGui::SliderInt(CONCAT("##sdrplay_lna_gain", _this->name), &_this->lnaGain, _this->lnaSteps - 1, 0, "")) {
|
||||
SmGui::LeftLabel("LNA Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt(CONCAT("##sdrplay_lna_gain", _this->name), &_this->lnaGain, _this->lnaSteps - 1, 0, SmGui::FMT_STR_NONE)) {
|
||||
if (_this->running) {
|
||||
_this->channelParams->tunerParams.gain.LNAstate = _this->lnaGain;
|
||||
sdrplay_api_Update(_this->openDev.dev, _this->openDev.tuner, sdrplay_api_Update_Tuner_Gr, sdrplay_api_Update_Ext1_None);
|
||||
@ -786,10 +786,10 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (_this->agc > 0) { style::beginDisabled(); }
|
||||
ImGui::LeftLabel("IF Gain");
|
||||
ImGui::SetCursorPosX(pos);
|
||||
if (ImGui::SliderInt(CONCAT("##sdrplay_gain", _this->name), &_this->gain, 59, 20, "")) {
|
||||
if (_this->agc > 0) { SmGui::BeginDisabled(); }
|
||||
SmGui::LeftLabel("IF Gain");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt(CONCAT("##sdrplay_gain", _this->name), &_this->gain, 59, 20, SmGui::FMT_STR_NONE)) {
|
||||
if (_this->running) {
|
||||
_this->channelParams->tunerParams.gain.gRdB = _this->gain;
|
||||
sdrplay_api_Update(_this->openDev.dev, _this->openDev.tuner, sdrplay_api_Update_Tuner_Gr, sdrplay_api_Update_Ext1_None);
|
||||
@ -798,8 +798,7 @@ private:
|
||||
config.conf["devices"][_this->selectedName]["ifGain"] = _this->gain;
|
||||
config.release(true);
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
if (_this->agc > 0) { style::endDisabled(); }
|
||||
if (_this->agc > 0) { SmGui::EndDisabled(); }
|
||||
|
||||
|
||||
if (_this->agcParamEdit) {
|
||||
@ -831,7 +830,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("IF AGC##sdrplay_agc", _this->name), &_this->agc)) {
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Checkbox(CONCAT("IF AGC##sdrplay_agc", _this->name), &_this->agc)) {
|
||||
if (_this->running) {
|
||||
_this->channelParams->ctrlParams.agc.enable = _this->agc ? sdrplay_api_AGC_CTRL_EN : sdrplay_api_AGC_DISABLE;
|
||||
if (_this->agc) {
|
||||
@ -852,8 +852,10 @@ private:
|
||||
config.conf["devices"][_this->selectedName]["agc"] = _this->agc;
|
||||
config.release(true);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(CONCAT("Parameters##sdrplay_agc_edit_btn", _this->name), ImVec2(menuWidth - ImGui::GetCursorPosX(), 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Parameters##sdrplay_agc_edit_btn", _this->name))) {
|
||||
_this->agcParamEdit = true;
|
||||
_this->_agcAttack = _this->agcAttack;
|
||||
_this->_agcDecay = _this->agcDecay;
|
||||
@ -864,100 +866,101 @@ private:
|
||||
|
||||
switch (_this->openDev.hwVer) {
|
||||
case SDRPLAY_RSP1_ID:
|
||||
_this->RSP1Menu(menuWidth);
|
||||
_this->RSP1Menu();
|
||||
break;
|
||||
case SDRPLAY_RSP1A_ID:
|
||||
_this->RSP1AMenu(menuWidth);
|
||||
_this->RSP1AMenu();
|
||||
break;
|
||||
case SDRPLAY_RSP2_ID:
|
||||
_this->RSP2Menu(menuWidth);
|
||||
_this->RSP2Menu();
|
||||
break;
|
||||
case SDRPLAY_RSPduo_ID:
|
||||
_this->RSPduoMenu(menuWidth);
|
||||
_this->RSPduoMenu();
|
||||
break;
|
||||
case SDRPLAY_RSPdx_ID:
|
||||
_this->RSPdxMenu(menuWidth);
|
||||
_this->RSPdxMenu();
|
||||
break;
|
||||
default:
|
||||
_this->RSPUnsupportedMenu(menuWidth);
|
||||
_this->RSPUnsupportedMenu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "No device available");
|
||||
SmGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "No device available");
|
||||
}
|
||||
}
|
||||
|
||||
bool agcParamMenu(bool& valid) {
|
||||
bool open = true;
|
||||
gui::mainWindow.lockWaterfallControls = true;
|
||||
ImGui::OpenPopup("Edit##sdrplay_source_edit_agc_params_");
|
||||
if (ImGui::BeginPopup("Edit##sdrplay_source_edit_agc_params_", ImGuiWindowFlags_NoResize)) {
|
||||
SmGui::OpenPopup("Edit##sdrplay_source_edit_agc_params_");
|
||||
if (SmGui::BeginPopup("Edit##sdrplay_source_edit_agc_params_", ImGuiWindowFlags_NoResize)) {
|
||||
if (SmGui::BeginTable(("sdrplay_source_agc_param_tbl" + name).c_str(), 2)) {
|
||||
SmGui::TableNextRow();
|
||||
SmGui::TableSetColumnIndex(0);
|
||||
SmGui::LeftLabel("Attack");
|
||||
SmGui::TableSetColumnIndex(1);
|
||||
SmGui::SetNextItemWidth(100);
|
||||
SmGui::InputInt("ms##sdrplay_source_agc_attack", &_agcAttack);
|
||||
_agcAttack = std::clamp<int>(_agcAttack, 0, 65535);
|
||||
|
||||
ImGui::BeginTable(("sdrplay_source_agc_param_tbl" + name).c_str(), 2);
|
||||
SmGui::TableNextRow();
|
||||
SmGui::TableSetColumnIndex(0);
|
||||
SmGui::LeftLabel("Decay");
|
||||
SmGui::TableSetColumnIndex(1);
|
||||
SmGui::SetNextItemWidth(100);
|
||||
SmGui::InputInt("ms##sdrplay_source_agc_decay", &_agcDecay);
|
||||
_agcDecay = std::clamp<int>(_agcDecay, 0, 65535);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::LeftLabel("Attack");
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::SetNextItemWidth(100);
|
||||
ImGui::InputInt("ms##sdrplay_source_agc_attack", &_agcAttack);
|
||||
_agcAttack = std::clamp<int>(_agcAttack, 0, 65535);
|
||||
SmGui::TableNextRow();
|
||||
SmGui::TableSetColumnIndex(0);
|
||||
SmGui::LeftLabel("Decay Delay");
|
||||
SmGui::TableSetColumnIndex(1);
|
||||
SmGui::SetNextItemWidth(100);
|
||||
SmGui::InputInt("ms##sdrplay_source_agc_decay_delay", &_agcDecayDelay);
|
||||
_agcDecayDelay = std::clamp<int>(_agcDecayDelay, 0, 65535);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::LeftLabel("Decay");
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::SetNextItemWidth(100);
|
||||
ImGui::InputInt("ms##sdrplay_source_agc_decay", &_agcDecay);
|
||||
_agcDecay = std::clamp<int>(_agcDecay, 0, 65535);
|
||||
SmGui::TableNextRow();
|
||||
SmGui::TableSetColumnIndex(0);
|
||||
SmGui::LeftLabel("Decay Threshold");
|
||||
SmGui::TableSetColumnIndex(1);
|
||||
SmGui::SetNextItemWidth(100);
|
||||
SmGui::InputInt("dB##sdrplay_source_agc_decay_thresh", &_agcDecayThreshold);
|
||||
_agcDecayThreshold = std::clamp<int>(_agcDecayThreshold, 0, 100);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::LeftLabel("Decay Delay");
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::SetNextItemWidth(100);
|
||||
ImGui::InputInt("ms##sdrplay_source_agc_decay_delay", &_agcDecayDelay);
|
||||
_agcDecayDelay = std::clamp<int>(_agcDecayDelay, 0, 65535);
|
||||
SmGui::TableNextRow();
|
||||
SmGui::TableSetColumnIndex(0);
|
||||
SmGui::LeftLabel("Setpoint");
|
||||
SmGui::TableSetColumnIndex(1);
|
||||
SmGui::SetNextItemWidth(100);
|
||||
SmGui::InputInt("dBFS##sdrplay_source_agc_setpoint", &_agcSetPoint);
|
||||
_agcSetPoint = std::clamp<int>(_agcSetPoint, -60, -20);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::LeftLabel("Decay Threshold");
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::SetNextItemWidth(100);
|
||||
ImGui::InputInt("dB##sdrplay_source_agc_decay_thresh", &_agcDecayThreshold);
|
||||
_agcDecayThreshold = std::clamp<int>(_agcDecayThreshold, 0, 100);
|
||||
SmGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::LeftLabel("Setpoint");
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::SetNextItemWidth(100);
|
||||
ImGui::InputInt("dBFS##sdrplay_source_agc_setpoint", &_agcSetPoint);
|
||||
_agcSetPoint = std::clamp<int>(_agcSetPoint, -60, -20);
|
||||
|
||||
ImGui::EndTable();
|
||||
|
||||
if (ImGui::Button("Apply")) {
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button("Apply")) {
|
||||
open = false;
|
||||
valid = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
SmGui::SameLine();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button("Cancel")) {
|
||||
open = false;
|
||||
valid = false;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
SmGui::EndPopup();
|
||||
}
|
||||
return open;
|
||||
}
|
||||
|
||||
void RSP1Menu(float menuWidth) {
|
||||
void RSP1Menu() {
|
||||
// No options?
|
||||
}
|
||||
|
||||
void RSP1AMenu(float menuWidth) {
|
||||
if (ImGui::Checkbox(CONCAT("FM Notch##sdrplay_rsp1a_fmnotch", name), &rsp1a_fmNotch)) {
|
||||
void RSP1AMenu() {
|
||||
if (SmGui::Checkbox(CONCAT("FM Notch##sdrplay_rsp1a_fmnotch", name), &rsp1a_fmNotch)) {
|
||||
if (running) {
|
||||
openDevParams->devParams->rsp1aParams.rfNotchEnable = rsp1a_fmNotch;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_Rsp1a_RfNotchControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -966,7 +969,7 @@ private:
|
||||
config.conf["devices"][selectedName]["fmNotch"] = rsp1a_fmNotch;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("DAB Notch##sdrplay_rsp1a_dabnotch", name), &rsp1a_dabNotch)) {
|
||||
if (SmGui::Checkbox(CONCAT("DAB Notch##sdrplay_rsp1a_dabnotch", name), &rsp1a_dabNotch)) {
|
||||
if (running) {
|
||||
openDevParams->devParams->rsp1aParams.rfNotchEnable = rsp1a_dabNotch;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_Rsp1a_RfDabNotchControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -975,7 +978,7 @@ private:
|
||||
config.conf["devices"][selectedName]["dabNotch"] = rsp1a_dabNotch;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("Bias-T##sdrplay_rsp1a_biast", name), &rsp1a_biasT)) {
|
||||
if (SmGui::Checkbox(CONCAT("Bias-T##sdrplay_rsp1a_biast", name), &rsp1a_biasT)) {
|
||||
if (running) {
|
||||
channelParams->rsp1aTunerParams.biasTEnable = rsp1a_biasT;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_Rsp1a_BiasTControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -986,10 +989,10 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void RSP2Menu(float menuWidth) {
|
||||
ImGui::LeftLabel("Antenna");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##sdrplay_rsp2_ant", name), &rsp2_antennaPort, rsp2_antennaPortsTxt)) {
|
||||
void RSP2Menu() {
|
||||
SmGui::LeftLabel("Antenna");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##sdrplay_rsp2_ant", name), &rsp2_antennaPort, rsp2_antennaPortsTxt)) {
|
||||
if (running) {
|
||||
channelParams->rsp2TunerParams.antennaSel = rsp2_antennaPorts[rsp2_antennaPort];
|
||||
channelParams->rsp2TunerParams.amPortSel = (rsp2_antennaPort == 2) ? sdrplay_api_Rsp2_AMPORT_1 : sdrplay_api_Rsp2_AMPORT_2;
|
||||
@ -1000,7 +1003,7 @@ private:
|
||||
config.conf["devices"][selectedName]["antenna"] = rsp2_antennaPort;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("MW/FM Notch##sdrplay_rsp2_notch", name), &rsp2_notch)) {
|
||||
if (SmGui::Checkbox(CONCAT("MW/FM Notch##sdrplay_rsp2_notch", name), &rsp2_notch)) {
|
||||
if (running) {
|
||||
channelParams->rsp2TunerParams.rfNotchEnable = rsp2_notch;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_Rsp2_RfNotchControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -1009,7 +1012,7 @@ private:
|
||||
config.conf["devices"][selectedName]["notch"] = rsp2_notch;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("Bias-T##sdrplay_rsp2_biast", name), &rsp2_biasT)) {
|
||||
if (SmGui::Checkbox(CONCAT("Bias-T##sdrplay_rsp2_biast", name), &rsp2_biasT)) {
|
||||
if (running) {
|
||||
channelParams->rsp2TunerParams.biasTEnable = rsp2_biasT;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_Rsp2_BiasTControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -1020,11 +1023,10 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void RSPduoMenu(float menuWidth) {
|
||||
ImGui::LeftLabel("Antenna");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
|
||||
if (ImGui::Combo(CONCAT("##sdrplay_rspduo_ant", name), &rspduo_antennaPort, rspduo_antennaPortsTxt)) {
|
||||
void RSPduoMenu() {
|
||||
SmGui::LeftLabel("Antenna");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##sdrplay_rspduo_ant", name), &rspduo_antennaPort, rspduo_antennaPortsTxt)) {
|
||||
if (running) {
|
||||
rspDuoSelectAntennaPort(rspduo_antennaPort);
|
||||
}
|
||||
@ -1032,7 +1034,7 @@ private:
|
||||
config.conf["devices"][selectedName]["antenna"] = rspduo_antennaPort;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("FM Notch##sdrplay_rspduo_notch", name), &rspduo_fmNotch)) {
|
||||
if (SmGui::Checkbox(CONCAT("FM Notch##sdrplay_rspduo_notch", name), &rspduo_fmNotch)) {
|
||||
if (running) {
|
||||
channelParams->rspDuoTunerParams.rfNotchEnable = rspduo_fmNotch;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_RspDuo_RfNotchControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -1041,7 +1043,7 @@ private:
|
||||
config.conf["devices"][selectedName]["fmNotch"] = rspduo_fmNotch;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("DAB Notch##sdrplay_rspduo_dabnotch", name), &rspduo_dabNotch)) {
|
||||
if (SmGui::Checkbox(CONCAT("DAB Notch##sdrplay_rspduo_dabnotch", name), &rspduo_dabNotch)) {
|
||||
if (running) {
|
||||
channelParams->rspDuoTunerParams.rfDabNotchEnable = rspduo_dabNotch;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_RspDuo_RfDabNotchControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -1050,7 +1052,7 @@ private:
|
||||
config.conf["devices"][selectedName]["dabNotch"] = rspduo_dabNotch;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("AM Notch##sdrplay_rspduo_dabnotch", name), &rspduo_amNotch)) {
|
||||
if (SmGui::Checkbox(CONCAT("AM Notch##sdrplay_rspduo_dabnotch", name), &rspduo_amNotch)) {
|
||||
if (running) {
|
||||
channelParams->rspDuoTunerParams.tuner1AmNotchEnable = rspduo_amNotch;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_RspDuo_Tuner1AmNotchControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -1059,7 +1061,7 @@ private:
|
||||
config.conf["devices"][selectedName]["amNotch"] = rspduo_amNotch;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("Bias-T##sdrplay_rspduo_biast", name), &rspduo_biasT)) {
|
||||
if (SmGui::Checkbox(CONCAT("Bias-T##sdrplay_rspduo_biast", name), &rspduo_biasT)) {
|
||||
if (running) {
|
||||
channelParams->rspDuoTunerParams.biasTEnable = rspduo_biasT;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_RspDuo_BiasTControl, sdrplay_api_Update_Ext1_None);
|
||||
@ -1070,10 +1072,10 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void RSPdxMenu(float menuWidth) {
|
||||
ImGui::LeftLabel("Antenna");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##sdrplay_rspdx_ant", name), &rspdx_antennaPort, rspdx_antennaPortsTxt)) {
|
||||
void RSPdxMenu() {
|
||||
SmGui::LeftLabel("Antenna");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##sdrplay_rspdx_ant", name), &rspdx_antennaPort, rspdx_antennaPortsTxt)) {
|
||||
if (running) {
|
||||
openDevParams->devParams->rspDxParams.antennaSel = rspdx_antennaPorts[rspdx_antennaPort];
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_None, sdrplay_api_Update_RspDx_AntennaControl);
|
||||
@ -1083,7 +1085,7 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox(CONCAT("FM Notch##sdrplay_rspdx_fmnotch", name), &rspdx_fmNotch)) {
|
||||
if (SmGui::Checkbox(CONCAT("FM Notch##sdrplay_rspdx_fmnotch", name), &rspdx_fmNotch)) {
|
||||
if (running) {
|
||||
openDevParams->devParams->rspDxParams.rfNotchEnable = rspdx_fmNotch;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_None, sdrplay_api_Update_RspDx_RfNotchControl);
|
||||
@ -1092,7 +1094,7 @@ private:
|
||||
config.conf["devices"][selectedName]["fmNotch"] = rspdx_fmNotch;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("DAB Notch##sdrplay_rspdx_dabnotch", name), &rspdx_dabNotch)) {
|
||||
if (SmGui::Checkbox(CONCAT("DAB Notch##sdrplay_rspdx_dabnotch", name), &rspdx_dabNotch)) {
|
||||
if (running) {
|
||||
openDevParams->devParams->rspDxParams.rfDabNotchEnable = rspdx_dabNotch;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_None, sdrplay_api_Update_RspDx_RfDabNotchControl);
|
||||
@ -1101,7 +1103,7 @@ private:
|
||||
config.conf["devices"][selectedName]["dabNotch"] = rspdx_dabNotch;
|
||||
config.release(true);
|
||||
}
|
||||
if (ImGui::Checkbox(CONCAT("Bias-T##sdrplay_rspdx_biast", name), &rspdx_biasT)) {
|
||||
if (SmGui::Checkbox(CONCAT("Bias-T##sdrplay_rspdx_biast", name), &rspdx_biasT)) {
|
||||
if (running) {
|
||||
openDevParams->devParams->rspDxParams.biasTEnable = rspdx_biasT;
|
||||
sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_None, sdrplay_api_Update_RspDx_BiasTControl);
|
||||
@ -1112,8 +1114,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void RSPUnsupportedMenu(float menuWidth) {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Device currently unsupported");
|
||||
void RSPUnsupportedMenu() {
|
||||
SmGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Device currently unsupported");
|
||||
}
|
||||
|
||||
static void streamCB(short* xi, short* xq, sdrplay_api_StreamCbParamsT* params,
|
||||
|
25
source_modules/sdrpp_server_source/CMakeLists.txt
Normal file
25
source_modules/sdrpp_server_source/CMakeLists.txt
Normal file
@ -0,0 +1,25 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(sdrpp_server_source)
|
||||
|
||||
file(GLOB SRC "src/*.cpp")
|
||||
|
||||
add_library(sdrpp_server_source SHARED ${SRC})
|
||||
target_link_libraries(sdrpp_server_source PRIVATE sdrpp_core)
|
||||
set_target_properties(sdrpp_server_source PROPERTIES PREFIX "")
|
||||
|
||||
target_include_directories(sdrpp_server_source PRIVATE "src/")
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(sdrpp_server_source PRIVATE /O2 /Ob2 /std:c++17 /EHsc)
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
target_compile_options(sdrpp_server_source PRIVATE -O3 -std=c++17 -Wno-unused-command-line-argument -undefined dynamic_lookup)
|
||||
else ()
|
||||
target_compile_options(sdrpp_server_source PRIVATE -O3 -std=c++17)
|
||||
endif ()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(sdrpp_server_source PRIVATE wsock32 ws2_32)
|
||||
endif()
|
||||
|
||||
# Install directives
|
||||
install(TARGETS sdrpp_server_source DESTINATION lib/sdrpp/plugins)
|
279
source_modules/sdrpp_server_source/src/main.cpp
Normal file
279
source_modules/sdrpp_server_source/src/main.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
#include "sdrpp_server_client.h"
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <module.h>
|
||||
#include <gui/gui.h>
|
||||
#include <signal_path/signal_path.h>
|
||||
#include <core.h>
|
||||
#include <gui/style.h>
|
||||
#include <config.h>
|
||||
#include <options.h>
|
||||
#include <gui/widgets/stepped_slider.h>
|
||||
#include <utils/optionlist.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
SDRPP_MOD_INFO{
|
||||
/* Name: */ "sdrpp_server_source",
|
||||
/* Description: */ "SDR++ Server source module for SDR++",
|
||||
/* Author: */ "Ryzerth",
|
||||
/* Version: */ 0, 1, 0,
|
||||
/* Max instances */ 1
|
||||
};
|
||||
|
||||
ConfigManager config;
|
||||
|
||||
class SDRPPServerSourceModule : public ModuleManager::Instance {
|
||||
public:
|
||||
SDRPPServerSourceModule(std::string name) {
|
||||
this->name = name;
|
||||
|
||||
// Yeah no server-ception, sorry...
|
||||
if (options::opts.serverMode) { return; }
|
||||
|
||||
// Initialize lists
|
||||
sampleTypeList.define("Int8", dsp::PCM_TYPE_I8);
|
||||
sampleTypeList.define("Int16", dsp::PCM_TYPE_I16);
|
||||
sampleTypeList.define("Float32", dsp::PCM_TYPE_F32);
|
||||
sampleTypeId = sampleTypeList.valueId(dsp::PCM_TYPE_I16);
|
||||
|
||||
handler.ctx = this;
|
||||
handler.selectHandler = menuSelected;
|
||||
handler.deselectHandler = menuDeselected;
|
||||
handler.menuHandler = menuHandler;
|
||||
handler.startHandler = start;
|
||||
handler.stopHandler = stop;
|
||||
handler.tuneHandler = tune;
|
||||
handler.stream = &stream;
|
||||
|
||||
// Load config
|
||||
config.acquire();
|
||||
std::string hostStr = config.conf["hostname"];
|
||||
strcpy(hostname, hostStr.c_str());
|
||||
port = config.conf["port"];
|
||||
config.release();
|
||||
|
||||
sigpath::sourceManager.registerSource("SDR++ Server", &handler);
|
||||
}
|
||||
|
||||
~SDRPPServerSourceModule() {
|
||||
stop(this);
|
||||
sigpath::sourceManager.unregisterSource("SDR++ Server");
|
||||
}
|
||||
|
||||
void postInit() {}
|
||||
|
||||
void enable() {
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
void disable() {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
bool isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string getBandwdithScaled(double bw) {
|
||||
char buf[1024];
|
||||
if (bw >= 1000000.0) {
|
||||
sprintf(buf, "%.1lfMHz", bw / 1000000.0);
|
||||
}
|
||||
else if (bw >= 1000.0) {
|
||||
sprintf(buf, "%.1lfKHz", bw / 1000.0);
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "%.1lfHz", bw);
|
||||
}
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
static void menuSelected(void* ctx) {
|
||||
SDRPPServerSourceModule* _this = (SDRPPServerSourceModule*)ctx;
|
||||
if (_this->client) {
|
||||
core::setInputSampleRate(_this->client->getSampleRate());
|
||||
}
|
||||
gui::mainWindow.playButtonLocked = !(_this->client && _this->client->isOpen());
|
||||
spdlog::info("SDRPPServerSourceModule '{0}': Menu Select!", _this->name);
|
||||
}
|
||||
|
||||
static void menuDeselected(void* ctx) {
|
||||
SDRPPServerSourceModule* _this = (SDRPPServerSourceModule*)ctx;
|
||||
gui::mainWindow.playButtonLocked = false;
|
||||
spdlog::info("SDRPPServerSourceModule '{0}': Menu Deselect!", _this->name);
|
||||
}
|
||||
|
||||
static void start(void* ctx) {
|
||||
SDRPPServerSourceModule* _this = (SDRPPServerSourceModule*)ctx;
|
||||
if (_this->running) { return; }
|
||||
|
||||
// TODO: Set configuration here
|
||||
if (_this->client) { _this->client->start(); }
|
||||
|
||||
_this->running = true;
|
||||
spdlog::info("SDRPPServerSourceModule '{0}': Start!", _this->name);
|
||||
}
|
||||
|
||||
static void stop(void* ctx) {
|
||||
SDRPPServerSourceModule* _this = (SDRPPServerSourceModule*)ctx;
|
||||
if (!_this->running) { return; }
|
||||
|
||||
if (_this->client) { _this->client->stop(); }
|
||||
|
||||
_this->running = false;
|
||||
spdlog::info("SDRPPServerSourceModule '{0}': Stop!", _this->name);
|
||||
}
|
||||
|
||||
static void tune(double freq, void* ctx) {
|
||||
SDRPPServerSourceModule* _this = (SDRPPServerSourceModule*)ctx;
|
||||
if (_this->running && _this->client) {
|
||||
_this->client->setFrequency(freq);
|
||||
}
|
||||
_this->freq = freq;
|
||||
spdlog::info("SDRPPServerSourceModule '{0}': Tune: {1}!", _this->name, freq);
|
||||
}
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
SDRPPServerSourceModule* _this = (SDRPPServerSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
bool connected = (_this->client && _this->client->isOpen());
|
||||
gui::mainWindow.playButtonLocked = !connected;
|
||||
|
||||
if (connected) { style::beginDisabled(); }
|
||||
if (ImGui::InputText(CONCAT("##sdrpp_srv_srv_host_", _this->name), _this->hostname, 1023)) {
|
||||
config.acquire();
|
||||
config.conf["hostname"] = _this->hostname;
|
||||
config.release(true);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::InputInt(CONCAT("##sdrpp_srv_srv_port_", _this->name), &_this->port, 0, 0)) {
|
||||
config.acquire();
|
||||
config.conf["port"] = _this->port;
|
||||
config.release(true);
|
||||
}
|
||||
if (connected) { style::endDisabled(); }
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (!connected && ImGui::Button("Connect##sdrpp_srv_source", ImVec2(menuWidth, 0))) {
|
||||
try {
|
||||
if (_this->client) { _this->client.reset(); }
|
||||
_this->client = server::connect(_this->hostname, _this->port, &_this->stream);
|
||||
_this->deviceInit();
|
||||
}
|
||||
catch (std::exception e) {
|
||||
spdlog::error("Could not connect to SDR: {0}", e.what());
|
||||
}
|
||||
}
|
||||
else if (connected && ImGui::Button("Disconnect##sdrpp_srv_source", ImVec2(menuWidth, 0))) {
|
||||
_this->client->close();
|
||||
}
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
|
||||
|
||||
if (connected) {
|
||||
ImGui::LeftLabel("Sample type");
|
||||
ImGui::FillWidth();
|
||||
if (ImGui::Combo("##sdrpp_srv_source_samp_type", &_this->sampleTypeId, _this->sampleTypeList.txt)) {
|
||||
_this->client->setSampleType(_this->sampleTypeList[_this->sampleTypeId]);
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
config.conf["servers"][_this->devConfName]["sampleType"] = _this->sampleTypeList.key(_this->sampleTypeId);
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
bool dummy = false;
|
||||
style::beginDisabled();
|
||||
ImGui::Checkbox("Compression", &dummy);
|
||||
dummy = true;
|
||||
ImGui::Checkbox("Full IQ", &dummy);
|
||||
style::endDisabled();
|
||||
|
||||
// Calculate datarate
|
||||
_this->frametimeCounter += ImGui::GetIO().DeltaTime;
|
||||
if (_this->frametimeCounter >= 0.2f) {
|
||||
_this->datarate = ((float)_this->client->bytes / (_this->frametimeCounter * 1024.0f * 1024.0f)) * 8;
|
||||
_this->frametimeCounter = 0;
|
||||
_this->client->bytes = 0;
|
||||
}
|
||||
|
||||
ImGui::Text("Status:");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "Connected (%.3f Mbit/s)", _this->datarate);
|
||||
|
||||
ImGui::CollapsingHeader("Source [REMOTE]", ImGuiTreeNodeFlags_DefaultOpen);
|
||||
|
||||
_this->client->showMenu();
|
||||
}
|
||||
else {
|
||||
ImGui::Text("Status:");
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Not connected (--.--- Mbit/s)");
|
||||
}
|
||||
}
|
||||
|
||||
void deviceInit() {
|
||||
// Generate the config name
|
||||
char buf[4096];
|
||||
sprintf(buf, "%s:%05d", hostname, port);
|
||||
devConfName = buf;
|
||||
|
||||
// Load settings
|
||||
sampleTypeId = sampleTypeList.valueId(dsp::PCM_TYPE_I16);
|
||||
if (config.conf["servers"][devConfName].contains("sampleType")) {
|
||||
std::string key = config.conf["servers"][devConfName]["sampleType"];
|
||||
if (sampleTypeList.keyExists(key)) { sampleTypeId = sampleTypeList.keyId(key); }
|
||||
}
|
||||
|
||||
// Set settings
|
||||
client->setSampleType(sampleTypeList[sampleTypeId]);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
bool enabled = true;
|
||||
bool running = false;
|
||||
|
||||
double freq;
|
||||
|
||||
float datarate = 0;
|
||||
float frametimeCounter = 0;
|
||||
|
||||
char hostname[1024];
|
||||
int port = 50000;
|
||||
std::string devConfName = "";
|
||||
|
||||
dsp::stream<dsp::complex_t> stream;
|
||||
SourceManager::SourceHandler handler;
|
||||
|
||||
OptionList<std::string, dsp::PCMType> sampleTypeList;
|
||||
int sampleTypeId;
|
||||
|
||||
server::Client client;
|
||||
};
|
||||
|
||||
MOD_EXPORT void _INIT_() {
|
||||
json def = json({});
|
||||
def["hostname"] = "localhost";
|
||||
def["port"] = 5259;
|
||||
def["servers"] = json::object();
|
||||
config.setPath(options::opts.root + "/sdrpp_server_source_config.json");
|
||||
config.load(def);
|
||||
config.enableAutoSave();
|
||||
}
|
||||
|
||||
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
|
||||
return new SDRPPServerSourceModule(name);
|
||||
}
|
||||
|
||||
MOD_EXPORT void _DELETE_INSTANCE_(ModuleManager::Instance* instance) {
|
||||
delete (SDRPPServerSourceModule*)instance;
|
||||
}
|
||||
|
||||
MOD_EXPORT void _END_() {
|
||||
config.disableAutoSave();
|
||||
config.save();
|
||||
}
|
233
source_modules/sdrpp_server_source/src/sdrpp_server_client.cpp
Normal file
233
source_modules/sdrpp_server_source/src/sdrpp_server_client.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
#include "sdrpp_server_client.h"
|
||||
#include <volk/volk.h>
|
||||
#include <cstring>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <core.h>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace server {
|
||||
ClientClass::ClientClass(net::Conn conn, dsp::stream<dsp::complex_t>* out) {
|
||||
client = std::move(conn);
|
||||
output = out;
|
||||
|
||||
// Allocate buffers
|
||||
rbuffer = new uint8_t[SERVER_MAX_PACKET_SIZE];
|
||||
sbuffer = new uint8_t[SERVER_MAX_PACKET_SIZE];
|
||||
|
||||
// Initialize headers
|
||||
r_pkt_hdr = (PacketHeader*)rbuffer;
|
||||
r_pkt_data = &rbuffer[sizeof(PacketHeader)];
|
||||
r_cmd_hdr = (CommandHeader*)r_pkt_data;
|
||||
r_cmd_data = &rbuffer[sizeof(PacketHeader) + sizeof(CommandHeader)];
|
||||
|
||||
s_pkt_hdr = (PacketHeader*)sbuffer;
|
||||
s_pkt_data = &sbuffer[sizeof(PacketHeader)];
|
||||
s_cmd_hdr = (CommandHeader*)s_pkt_data;
|
||||
s_cmd_data = &sbuffer[sizeof(PacketHeader) + sizeof(CommandHeader)];
|
||||
|
||||
// Initialize DSP
|
||||
decomp.init(&decompIn);
|
||||
link.init(&decomp.out, output);
|
||||
decomp.start();
|
||||
link.start();
|
||||
|
||||
// Start readers
|
||||
client->readAsync(sizeof(PacketHeader), rbuffer, tcpHandler, this);
|
||||
|
||||
// Default configuration
|
||||
stop();
|
||||
|
||||
// Ask for a UI
|
||||
getUI();
|
||||
}
|
||||
|
||||
ClientClass::~ClientClass() {
|
||||
close();
|
||||
delete[] rbuffer;
|
||||
delete[] sbuffer;
|
||||
}
|
||||
|
||||
void ClientClass::showMenu() {
|
||||
std::string diffId = "";
|
||||
SmGui::DrawListElem diffValue;
|
||||
bool syncRequired = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dlMtx);
|
||||
dl.draw(diffId, diffValue, syncRequired);
|
||||
}
|
||||
|
||||
if (!diffId.empty()) {
|
||||
// Save ID
|
||||
SmGui::DrawListElem elemId;
|
||||
elemId.type = SmGui::DRAW_LIST_ELEM_TYPE_STRING;
|
||||
elemId.str = diffId;
|
||||
|
||||
// Encore packet
|
||||
int size = 0;
|
||||
s_cmd_data[size++] = syncRequired;
|
||||
size += SmGui::DrawList::storeItem(elemId, &s_cmd_data[size], SERVER_MAX_PACKET_SIZE - size);
|
||||
size += SmGui::DrawList::storeItem(diffValue, &s_cmd_data[size], SERVER_MAX_PACKET_SIZE - size);
|
||||
|
||||
// Send
|
||||
if (syncRequired) {
|
||||
spdlog::warn("Action requires resync");
|
||||
auto waiter = awaitCommandAck(COMMAND_UI_ACTION);
|
||||
sendCommand(COMMAND_UI_ACTION, size);
|
||||
if (waiter->await(PROTOCOL_TIMEOUT_MS)) {
|
||||
std::lock_guard lck(dlMtx);
|
||||
dl.load(r_cmd_data, r_pkt_hdr->size - sizeof(PacketHeader) - sizeof(CommandHeader));
|
||||
}
|
||||
else {
|
||||
spdlog::error("Timeout out after asking for UI");
|
||||
}
|
||||
waiter->handled();
|
||||
spdlog::warn("Resync done");
|
||||
}
|
||||
else {
|
||||
spdlog::warn("Action does not require resync");
|
||||
sendCommand(COMMAND_UI_ACTION, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientClass::setFrequency(double freq) {
|
||||
if (!client || !client->isOpen()) { return; }
|
||||
*(double*)s_cmd_data = freq;
|
||||
sendCommand(COMMAND_SET_FREQUENCY, sizeof(double));
|
||||
auto waiter = awaitCommandAck(COMMAND_SET_FREQUENCY);
|
||||
waiter->await(PROTOCOL_TIMEOUT_MS);
|
||||
waiter->handled();
|
||||
}
|
||||
|
||||
double ClientClass::getSampleRate() {
|
||||
return currentSampleRate;
|
||||
}
|
||||
|
||||
void ClientClass::setSampleType(dsp::PCMType type) {
|
||||
s_cmd_data[0] = type;
|
||||
sendCommand(COMMAND_SET_SAMPLE_TYPE, 1);
|
||||
}
|
||||
|
||||
void ClientClass::start() {
|
||||
if (!client || !client->isOpen()) { return; }
|
||||
sendCommand(COMMAND_START, 0);
|
||||
getUI();
|
||||
}
|
||||
|
||||
void ClientClass::stop() {
|
||||
if (!client || !client->isOpen()) { return; }
|
||||
sendCommand(COMMAND_STOP, 0);
|
||||
getUI();
|
||||
}
|
||||
|
||||
void ClientClass::close() {
|
||||
decomp.stop();
|
||||
link.stop();
|
||||
client->close();
|
||||
}
|
||||
|
||||
bool ClientClass::isOpen() {
|
||||
return client->isOpen();
|
||||
}
|
||||
|
||||
void ClientClass::tcpHandler(int count, uint8_t* buf, void* ctx) {
|
||||
ClientClass* _this = (ClientClass*)ctx;
|
||||
|
||||
// Read the rest of the data (TODO: CHECK SIZE OR SHIT WILL BE FUCKED)
|
||||
int len = 0;
|
||||
int read = 0;
|
||||
int goal = _this->r_pkt_hdr->size - sizeof(PacketHeader);
|
||||
while (len < goal) {
|
||||
read = _this->client->read(goal - len, &buf[sizeof(PacketHeader) + len]);
|
||||
if (read < 0) {
|
||||
return;
|
||||
};
|
||||
len += read;
|
||||
}
|
||||
_this->bytes += _this->r_pkt_hdr->size;
|
||||
|
||||
if (_this->r_pkt_hdr->type == PACKET_TYPE_COMMAND) {
|
||||
// TODO: Move to command handler
|
||||
if (_this->r_cmd_hdr->cmd == COMMAND_SET_SAMPLERATE && _this->r_pkt_hdr->size == sizeof(PacketHeader) + sizeof(CommandHeader) + sizeof(double)) {
|
||||
_this->currentSampleRate = *(double*)_this->r_cmd_data;
|
||||
core::setInputSampleRate(_this->currentSampleRate);
|
||||
}
|
||||
}
|
||||
else if (_this->r_pkt_hdr->type == PACKET_TYPE_COMMAND_ACK) {
|
||||
// Notify waiters
|
||||
std::vector<PacketWaiter*> toBeRemoved;
|
||||
for (auto& [waiter, cmd] : _this->commandAckWaiters) {
|
||||
if (cmd != _this->r_cmd_hdr->cmd) { continue; }
|
||||
waiter->notify();
|
||||
toBeRemoved.push_back(waiter);
|
||||
}
|
||||
|
||||
// Remove handled waiters
|
||||
for (auto& waiter : toBeRemoved) {
|
||||
_this->commandAckWaiters.erase(waiter);
|
||||
delete waiter;
|
||||
}
|
||||
}
|
||||
else if (_this->r_pkt_hdr->type == PACKET_TYPE_BASEBAND) {
|
||||
memcpy(_this->decompIn.writeBuf, &buf[sizeof(PacketHeader)], _this->r_pkt_hdr->size - sizeof(PacketHeader));
|
||||
_this->decompIn.swap(_this->r_pkt_hdr->size - sizeof(PacketHeader));
|
||||
}
|
||||
else if (_this->r_pkt_hdr->type == PACKET_TYPE_ERROR) {
|
||||
spdlog::error("SDR++ Server Error: {0}", buf[sizeof(PacketHeader)]);
|
||||
}
|
||||
else {
|
||||
spdlog::error("Invalid packet type: {0}", _this->r_pkt_hdr->type);
|
||||
}
|
||||
|
||||
// Restart an async read
|
||||
_this->client->readAsync(sizeof(PacketHeader), _this->rbuffer, tcpHandler, _this);
|
||||
}
|
||||
|
||||
void ClientClass::getUI() {
|
||||
auto waiter = awaitCommandAck(COMMAND_GET_UI);
|
||||
sendCommand(COMMAND_GET_UI, 0);
|
||||
if (waiter->await(PROTOCOL_TIMEOUT_MS)) {
|
||||
std::lock_guard lck(dlMtx);
|
||||
dl.load(r_cmd_data, r_pkt_hdr->size - sizeof(PacketHeader) - sizeof(CommandHeader));
|
||||
}
|
||||
else {
|
||||
spdlog::error("Timeout out after asking for UI");
|
||||
}
|
||||
waiter->handled();
|
||||
}
|
||||
|
||||
void ClientClass::sendPacket(PacketType type, int len) {
|
||||
s_pkt_hdr->type = type;
|
||||
s_pkt_hdr->size = sizeof(PacketHeader) + len;
|
||||
client->write(s_pkt_hdr->size, sbuffer);
|
||||
}
|
||||
|
||||
void ClientClass::sendCommand(Command cmd, int len) {
|
||||
s_cmd_hdr->cmd = cmd;
|
||||
sendPacket(PACKET_TYPE_COMMAND, sizeof(CommandHeader) + len);
|
||||
}
|
||||
|
||||
void ClientClass::sendCommandAck(Command cmd, int len) {
|
||||
s_cmd_hdr->cmd = cmd;
|
||||
sendPacket(PACKET_TYPE_COMMAND_ACK, sizeof(CommandHeader) + len);
|
||||
}
|
||||
|
||||
PacketWaiter* ClientClass::awaitCommandAck(Command cmd) {
|
||||
PacketWaiter* waiter = new PacketWaiter;
|
||||
commandAckWaiters[waiter] = cmd;
|
||||
return waiter;
|
||||
}
|
||||
|
||||
void ClientClass::dHandler(dsp::complex_t *data, int count, void *ctx) {
|
||||
ClientClass* _this = (ClientClass*)ctx;
|
||||
memcpy(_this->output->writeBuf, data, count * sizeof(dsp::complex_t));
|
||||
_this->output->swap(count);
|
||||
}
|
||||
|
||||
Client connect(std::string host, uint16_t port, dsp::stream<dsp::complex_t>* out) {
|
||||
net::Conn conn = net::connect(host, port);
|
||||
if (!conn) { return NULL; }
|
||||
return Client(new ClientClass(std::move(conn), out));
|
||||
}
|
||||
}
|
134
source_modules/sdrpp_server_source/src/sdrpp_server_client.h
Normal file
134
source_modules/sdrpp_server_source/src/sdrpp_server_client.h
Normal file
@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
#include <utils/networking.h>
|
||||
#include <dsp/stream.h>
|
||||
#include <dsp/types.h>
|
||||
#include <atomic>
|
||||
#include <queue>
|
||||
#include <server_protocol.h>
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <dsp/compression.h>
|
||||
#include <dsp/sink.h>
|
||||
#include <dsp/link.h>
|
||||
|
||||
#define RFSPACE_MAX_SIZE 8192
|
||||
#define RFSPACE_HEARTBEAT_INTERVAL_MS 1000
|
||||
#define RFSPACE_TIMEOUT_MS 3000
|
||||
|
||||
#define PROTOCOL_TIMEOUT_MS 10000
|
||||
|
||||
namespace server {
|
||||
class PacketWaiter {
|
||||
public:
|
||||
bool await(int timeout) {
|
||||
std::unique_lock lck(readyMtx);
|
||||
return readyCnd.wait_for(lck, std::chrono::milliseconds(timeout), [=](){ return dataReady; });
|
||||
}
|
||||
|
||||
void handled() {
|
||||
{
|
||||
std::lock_guard lck(handledMtx);
|
||||
dataHandled = true;
|
||||
}
|
||||
handledCnd.notify_all();
|
||||
}
|
||||
|
||||
void notify() {
|
||||
// Tell waiter that data is ready
|
||||
{
|
||||
std::lock_guard lck(readyMtx);
|
||||
dataReady = true;
|
||||
}
|
||||
readyCnd.notify_all();
|
||||
|
||||
// Wait for waiter to handle the request
|
||||
{
|
||||
std::unique_lock lck(readyMtx);
|
||||
handledCnd.wait(lck, [=](){ return dataHandled; });
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
std::lock_guard lck1(readyMtx);
|
||||
std::lock_guard lck2(handledMtx);
|
||||
dataReady = false;
|
||||
dataHandled = false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool dataReady = false;
|
||||
bool dataHandled = false;
|
||||
|
||||
std::condition_variable readyCnd;
|
||||
std::condition_variable handledCnd;
|
||||
|
||||
std::mutex readyMtx;
|
||||
std::mutex handledMtx;
|
||||
};
|
||||
|
||||
class ClientClass {
|
||||
public:
|
||||
ClientClass(net::Conn conn, dsp::stream<dsp::complex_t>* out);
|
||||
~ClientClass();
|
||||
|
||||
void showMenu();
|
||||
|
||||
void setFrequency(double freq);
|
||||
double getSampleRate();
|
||||
|
||||
void setSampleType(dsp::PCMType type);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void close();
|
||||
bool isOpen();
|
||||
|
||||
int bytes = 0;
|
||||
|
||||
private:
|
||||
static void tcpHandler(int count, uint8_t* buf, void* ctx);
|
||||
|
||||
void getUI();
|
||||
|
||||
void sendPacket(PacketType type, int len);
|
||||
void sendCommand(Command cmd, int len);
|
||||
void sendCommandAck(Command cmd, int len);
|
||||
|
||||
PacketWaiter* awaitCommandAck(Command cmd);
|
||||
void commandAckHandled(PacketWaiter* waiter);
|
||||
std::map<PacketWaiter*, Command> commandAckWaiters;
|
||||
|
||||
static void dHandler(dsp::complex_t *data, int count, void *ctx);
|
||||
|
||||
net::Conn client;
|
||||
|
||||
dsp::stream<uint8_t> decompIn;
|
||||
dsp::DynamicRangeDecompressor decomp;
|
||||
dsp::Link<dsp::complex_t> link;
|
||||
dsp::stream<dsp::complex_t>* output;
|
||||
|
||||
uint8_t* rbuffer = NULL;
|
||||
uint8_t* sbuffer = NULL;
|
||||
|
||||
PacketHeader* r_pkt_hdr = NULL;
|
||||
uint8_t* r_pkt_data = NULL;
|
||||
CommandHeader* r_cmd_hdr = NULL;
|
||||
uint8_t* r_cmd_data = NULL;
|
||||
|
||||
PacketHeader* s_pkt_hdr = NULL;
|
||||
uint8_t* s_pkt_data = NULL;
|
||||
CommandHeader* s_cmd_hdr = NULL;
|
||||
uint8_t* s_cmd_data = NULL;
|
||||
|
||||
SmGui::DrawList dl;
|
||||
std::mutex dlMtx;
|
||||
|
||||
double currentSampleRate = 1000000.0;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<ClientClass> Client;
|
||||
|
||||
Client connect(std::string host, uint16_t port, dsp::stream<dsp::complex_t>* out);
|
||||
}
|
@ -11,6 +11,7 @@
|
||||
#include <core.h>
|
||||
#include <gui/style.h>
|
||||
#include <options.h>
|
||||
#include <gui/smgui.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
@ -365,65 +366,66 @@ private:
|
||||
static void menuHandler(void* ctx) {
|
||||
SoapyModule* _this = (SoapyModule*)ctx;
|
||||
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
// If no device is selected, draw only the refresh button
|
||||
if (_this->devId < 0) {
|
||||
if (ImGui::Button(CONCAT("Refresh##_dev_select_", _this->name), ImVec2(menuWidth, 0))) {
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Button(CONCAT("Refresh##_dev_select_", _this->name))) {
|
||||
_this->refresh();
|
||||
_this->selectDevice(config.conf["device"]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::Combo(CONCAT("##_dev_select_", _this->name), &_this->devId, _this->txtDevList.c_str())) {
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_dev_select_", _this->name), &_this->devId, _this->txtDevList.c_str())) {
|
||||
_this->selectDevice(_this->devList[_this->devId]["label"]);
|
||||
config.acquire();
|
||||
config.conf["device"] = _this->devList[_this->devId]["label"];
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
if (ImGui::Combo(CONCAT("##_sr_select_", _this->name), &_this->srId, _this->txtSrList.c_str())) {
|
||||
if (SmGui::Combo(CONCAT("##_sr_select_", _this->name), &_this->srId, _this->txtSrList.c_str())) {
|
||||
_this->selectSampleRate(_this->sampleRates[_this->srId]);
|
||||
if (_this->bandwidthList.size() > 2 && _this->running && _this->bandwidthList[_this->uiBandwidthId] == -1)
|
||||
_this->dev->setBandwidth(SOAPY_SDR_RX, _this->channelId, _this->selectBwBySr(_this->sampleRates[_this->srId]));
|
||||
_this->saveCurrent();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX();
|
||||
if (ImGui::Button(CONCAT("Refresh##_dev_select_", _this->name), ImVec2(refreshBtnWdith, 0))) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Button(CONCAT("Refresh##_dev_select_", _this->name))) {
|
||||
_this->refresh();
|
||||
_this->selectDevice(config.conf["device"]);
|
||||
}
|
||||
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
if (_this->antennaList.size() > 1) {
|
||||
ImGui::LeftLabel("Antenna");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_antenna_select_", _this->name), &_this->uiAntennaId, _this->txtAntennaList.c_str())) {
|
||||
SmGui::LeftLabel("Antenna");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_antenna_select_", _this->name), &_this->uiAntennaId, _this->txtAntennaList.c_str())) {
|
||||
if (_this->running)
|
||||
_this->dev->setAntenna(SOAPY_SDR_RX, _this->channelId, _this->antennaList[_this->uiAntennaId]);
|
||||
_this->saveCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
float gainNameLen = 0;
|
||||
float len;
|
||||
for (auto gain : _this->gainList) {
|
||||
len = ImGui::CalcTextSize((gain + " gain").c_str()).x;
|
||||
if (len > gainNameLen) {
|
||||
gainNameLen = len;
|
||||
}
|
||||
}
|
||||
gainNameLen += 5.0f;
|
||||
// float gainNameLen = 0;
|
||||
// float len;
|
||||
// for (auto gain : _this->gainList) {
|
||||
// len = ImGui::CalcTextSize((gain + " gain").c_str()).x;
|
||||
// if (len > gainNameLen) {
|
||||
// gainNameLen = len;
|
||||
// }
|
||||
// }
|
||||
// gainNameLen += 5.0f;
|
||||
|
||||
if (_this->hasAgc) {
|
||||
if (ImGui::Checkbox((std::string("AGC##_agc_sel_") + _this->name).c_str(), &_this->agc)) {
|
||||
if (SmGui::Checkbox((std::string("AGC##_agc_sel_") + _this->name).c_str(), &_this->agc)) {
|
||||
if (_this->running) { _this->dev->setGainMode(SOAPY_SDR_RX, _this->channelId, _this->agc); }
|
||||
// When disabled, reset the gains
|
||||
if (!_this->agc) {
|
||||
@ -441,16 +443,17 @@ private:
|
||||
char buf[128];
|
||||
for (auto gain : _this->gainList) {
|
||||
sprintf(buf, "%s gain", gain.c_str());
|
||||
ImGui::LeftLabel(buf);
|
||||
ImGui::SetCursorPosX(gainNameLen);
|
||||
ImGui::SetNextItemWidth(menuWidth - gainNameLen);
|
||||
SmGui::LeftLabel(buf);
|
||||
// ImGui::SetCursorPosX(gainNameLen);
|
||||
// ImGui::SetNextItemWidth(menuWidth - gainNameLen);
|
||||
float step = _this->gainRanges[i].step();
|
||||
bool res;
|
||||
SmGui::FillWidth();
|
||||
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());
|
||||
res = SmGui::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);
|
||||
res = SmGui::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) {
|
||||
@ -461,9 +464,9 @@ private:
|
||||
i++;
|
||||
}
|
||||
if (_this->bandwidthList.size() > 2) {
|
||||
ImGui::LeftLabel("Bandwidth");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo(CONCAT("##_bw_select_", _this->name), &_this->uiBandwidthId, _this->txtBwList.c_str())) {
|
||||
SmGui::LeftLabel("Bandwidth");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::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]));
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <config.h>
|
||||
#include <options.h>
|
||||
#include <gui/widgets/stepped_slider.h>
|
||||
#include <gui/smgui.h>
|
||||
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
@ -155,28 +156,29 @@ private:
|
||||
|
||||
static void menuHandler(void* ctx) {
|
||||
SpyServerSourceModule* _this = (SpyServerSourceModule*)ctx;
|
||||
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||
|
||||
bool connected = (_this->client && _this->client->isOpen());
|
||||
gui::mainWindow.playButtonLocked = !connected;
|
||||
|
||||
if (connected) { style::beginDisabled(); }
|
||||
if (ImGui::InputText(CONCAT("##_spyserver_srv_host_", _this->name), _this->hostname, 1023)) {
|
||||
if (connected) { SmGui::BeginDisabled(); }
|
||||
if (SmGui::InputText(CONCAT("##_spyserver_srv_host_", _this->name), _this->hostname, 1023)) {
|
||||
config.acquire();
|
||||
config.conf["hostname"] = _this->hostname;
|
||||
config.release(true);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::InputInt(CONCAT("##_spyserver_srv_port_", _this->name), &_this->port, 0, 0)) {
|
||||
SmGui::SameLine();
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::InputInt(CONCAT("##_spyserver_srv_port_", _this->name), &_this->port, 0, 0)) {
|
||||
config.acquire();
|
||||
config.conf["port"] = _this->port;
|
||||
config.release(true);
|
||||
}
|
||||
if (connected) { style::endDisabled(); }
|
||||
if (connected) { SmGui::EndDisabled(); }
|
||||
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
if (!connected && ImGui::Button("Connect##spyserver_source", ImVec2(menuWidth, 0))) {
|
||||
if (_this->running) { SmGui::BeginDisabled(); }
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (!connected && SmGui::Button("Connect##spyserver_source")) {
|
||||
try {
|
||||
if (_this->client) { _this->client.reset(); }
|
||||
_this->client = spyserver::connect(_this->hostname, _this->port, &_this->stream);
|
||||
@ -223,17 +225,17 @@ private:
|
||||
spdlog::error("Could not connect to spyserver {0}", e.what());
|
||||
}
|
||||
}
|
||||
else if (connected && ImGui::Button("Disconnect##spyserver_source", ImVec2(menuWidth, 0))) {
|
||||
else if (connected && SmGui::Button("Disconnect##spyserver_source")) {
|
||||
_this->client->close();
|
||||
}
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
|
||||
if (connected) {
|
||||
if (_this->running) { style::beginDisabled(); }
|
||||
ImGui::LeftLabel("Samplerate");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##spyserver_source_sr", &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
SmGui::LeftLabel("Samplerate");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo("##spyserver_source_sr", &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
_this->sampleRate = _this->sampleRates[_this->srId];
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
config.acquire();
|
||||
@ -242,9 +244,9 @@ private:
|
||||
}
|
||||
if (_this->running) { style::endDisabled(); }
|
||||
|
||||
ImGui::LeftLabel("Sample bit depth");
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##spyserver_source_type", &_this->iqType, streamFormatStr)) {
|
||||
SmGui::LeftLabel("Sample bit depth");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo("##spyserver_source_type", &_this->iqType, streamFormatStr)) {
|
||||
int srvBits = streamFormatsBitCount[_this->iqType];
|
||||
_this->client->setSetting(SPYSERVER_SETTING_IQ_FORMAT, streamFormats[_this->iqType]);
|
||||
_this->client->setSetting(SPYSERVER_SETTING_IQ_DIGITAL_GAIN, _this->client->computeDigitalGain(srvBits, _this->gain, _this->srId + _this->client->devInfo.MinimumIQDecimation));
|
||||
@ -255,8 +257,8 @@ private:
|
||||
}
|
||||
|
||||
if (_this->client->devInfo.MaximumGainIndex) {
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
if (ImGui::SliderInt("##spyserver_source_gain", (int*)&_this->gain, 0, _this->client->devInfo.MaximumGainIndex)) {
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::SliderInt("##spyserver_source_gain", (int*)&_this->gain, 0, _this->client->devInfo.MaximumGainIndex)) {
|
||||
int srvBits = streamFormatsBitCount[_this->iqType];
|
||||
_this->client->setSetting(SPYSERVER_SETTING_GAIN, _this->gain);
|
||||
_this->client->setSetting(SPYSERVER_SETTING_IQ_DIGITAL_GAIN, _this->client->computeDigitalGain(srvBits, _this->gain, _this->srId + _this->client->devInfo.MinimumIQDecimation));
|
||||
@ -266,14 +268,14 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Text("Status:");
|
||||
ImGui::SameLine();
|
||||
SmGui::Text("Status:");
|
||||
SmGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "Connected (%s)", deviceTypesStr[_this->client->devInfo.DeviceType]);
|
||||
}
|
||||
else {
|
||||
ImGui::Text("Status:");
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Not connected");
|
||||
SmGui::Text("Status:");
|
||||
SmGui::SameLine();
|
||||
SmGui::Text("Not connected");
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user