mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-01-11 18:57:11 +01:00
Fixed support in the module manager
This commit is contained in:
parent
b327bfbe5d
commit
85de72a859
@ -50,15 +50,18 @@ public:
|
|||||||
std::string devSerial = config.conf["device"];
|
std::string devSerial = config.conf["device"];
|
||||||
config.release();
|
config.release();
|
||||||
selectByString(devSerial);
|
selectByString(devSerial);
|
||||||
core::setInputSampleRate(sampleRate);
|
|
||||||
|
|
||||||
sigpath::sourceManager.registerSource("Airspy", &handler);
|
sigpath::sourceManager.registerSource("Airspy", &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
~AirspySourceModule() {
|
~AirspySourceModule() {
|
||||||
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("Airspy");
|
||||||
airspy_exit();
|
airspy_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -46,15 +46,17 @@ public:
|
|||||||
std::string devSerial = config.conf["device"];
|
std::string devSerial = config.conf["device"];
|
||||||
config.release();
|
config.release();
|
||||||
selectByString(devSerial);
|
selectByString(devSerial);
|
||||||
core::setInputSampleRate(sampleRate);
|
|
||||||
|
|
||||||
sigpath::sourceManager.registerSource("Airspy HF+", &handler);
|
sigpath::sourceManager.registerSource("Airspy HF+", &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
~AirspyHFSourceModule() {
|
~AirspyHFSourceModule() {
|
||||||
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("Airspy HF+");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
enum AGCMode {
|
enum AGCMode {
|
||||||
AGC_MODE_OFF,
|
AGC_MODE_OFF,
|
||||||
AGC_MODE_LOW,
|
AGC_MODE_LOW,
|
||||||
|
@ -251,6 +251,8 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -50,15 +50,17 @@ public:
|
|||||||
std::string serial = config.conf["device"];
|
std::string serial = config.conf["device"];
|
||||||
config.release();
|
config.release();
|
||||||
selectBySerial(serial);
|
selectBySerial(serial);
|
||||||
core::setInputSampleRate(sampleRate);
|
|
||||||
|
|
||||||
sigpath::sourceManager.registerSource("BladeRF", &handler);
|
sigpath::sourceManager.registerSource("BladeRF", &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
~BladeRFSourceModule() {
|
~BladeRFSourceModule() {
|
||||||
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("BladeRF");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@ namespace dsp {
|
|||||||
// NOTE: For some reason, the base class destrcutor doesn't get called.... this is a temporary fix I guess
|
// NOTE: For some reason, the base class destrcutor doesn't get called.... this is a temporary fix I guess
|
||||||
// I also don't check for _block_init for the exact sample reason, something's weird
|
// I also don't check for _block_init for the exact sample reason, something's weird
|
||||||
~Reshaper() {
|
~Reshaper() {
|
||||||
|
if (!generic_block<Reshaper<T>>::_block_init) { return; }
|
||||||
generic_block<Reshaper<T>>::stop();
|
generic_block<Reshaper<T>>::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ namespace dsp {
|
|||||||
void updateWindow(dsp::filter_window::generic_complex_window* window) {
|
void updateWindow(dsp::filter_window::generic_complex_window* window) {
|
||||||
assert(generic_block<FMStereoDemuxPilotFilter>::_block_init);
|
assert(generic_block<FMStereoDemuxPilotFilter>::_block_init);
|
||||||
std::lock_guard<std::mutex> lck(generic_block<FMStereoDemuxPilotFilter>::ctrlMtx);
|
std::lock_guard<std::mutex> lck(generic_block<FMStereoDemuxPilotFilter>::ctrlMtx);
|
||||||
|
std::lock_guard<std::mutex> lck2(bufMtx);
|
||||||
_window = window;
|
_window = window;
|
||||||
volk_free(taps);
|
volk_free(taps);
|
||||||
tapCount = window->getTapCount();
|
tapCount = window->getTapCount();
|
||||||
@ -59,7 +60,7 @@ namespace dsp {
|
|||||||
int count = _in->read();
|
int count = _in->read();
|
||||||
if (count < 0) { return -1; }
|
if (count < 0) { return -1; }
|
||||||
|
|
||||||
generic_block<FMStereoDemuxPilotFilter>::ctrlMtx.lock();
|
bufMtx.lock();
|
||||||
|
|
||||||
memcpy(bufStart, _in->readBuf, count * sizeof(complex_t));
|
memcpy(bufStart, _in->readBuf, count * sizeof(complex_t));
|
||||||
_in->flush();
|
_in->flush();
|
||||||
@ -70,12 +71,14 @@ namespace dsp {
|
|||||||
|
|
||||||
memcpy(dataOut.writeBuf, &buffer[tapCount - ((tapCount-1)/2)], count * sizeof(complex_t));
|
memcpy(dataOut.writeBuf, &buffer[tapCount - ((tapCount-1)/2)], count * sizeof(complex_t));
|
||||||
|
|
||||||
if (!dataOut.swap(count)) { return -1; }
|
if (!pilotOut.swap(count) || !dataOut.swap(count)) {
|
||||||
if (!pilotOut.swap(count)) { return -1; }
|
bufMtx.unlock();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
memmove(buffer, &buffer[count], tapCount * sizeof(complex_t));
|
memmove(buffer, &buffer[count], tapCount * sizeof(complex_t));
|
||||||
|
|
||||||
generic_block<FMStereoDemuxPilotFilter>::ctrlMtx.unlock();
|
bufMtx.unlock();
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -89,6 +92,8 @@ namespace dsp {
|
|||||||
|
|
||||||
dsp::filter_window::generic_complex_window* _window;
|
dsp::filter_window::generic_complex_window* _window;
|
||||||
|
|
||||||
|
std::mutex bufMtx;
|
||||||
|
|
||||||
complex_t* bufStart;
|
complex_t* bufStart;
|
||||||
complex_t* buffer;
|
complex_t* buffer;
|
||||||
int tapCount;
|
int tapCount;
|
||||||
|
@ -212,7 +212,7 @@ void MainWindow::init() {
|
|||||||
|
|
||||||
initComplete = true;
|
initComplete = true;
|
||||||
|
|
||||||
onInitComplete.emit(true);
|
core::moduleManager.doPostInitAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::fftHandler(dsp::complex_t* samples, int count, void* ctx) {
|
void MainWindow::fftHandler(dsp::complex_t* samples, int count, void* ctx) {
|
||||||
|
@ -35,7 +35,6 @@ public:
|
|||||||
bool playButtonLocked = false;
|
bool playButtonLocked = false;
|
||||||
|
|
||||||
Event<bool> onPlayStateChange;
|
Event<bool> onPlayStateChange;
|
||||||
Event<bool> onInitComplete;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void generateFFTWindow(int win, int size);
|
void generateFFTWindow(int win, int size);
|
||||||
|
@ -16,11 +16,6 @@ namespace module_manager_menu {
|
|||||||
modTypes.clear();
|
modTypes.clear();
|
||||||
modTypesTxt = "";
|
modTypesTxt = "";
|
||||||
for (auto& [name, mod] : core::moduleManager.modules) {
|
for (auto& [name, mod] : core::moduleManager.modules) {
|
||||||
// TEMPORARY EXCLUSION FOR SOURCES AND SINKS
|
|
||||||
if (name.find("source") != std::string::npos) { continue; }
|
|
||||||
if (name.find("sink") != std::string::npos) { continue; }
|
|
||||||
if (name.find("recorder") != std::string::npos) { continue; }
|
|
||||||
if (name.find("discord") != std::string::npos) { continue; }
|
|
||||||
modTypes.push_back(name);
|
modTypes.push_back(name);
|
||||||
modTypesTxt += name;
|
modTypesTxt += name;
|
||||||
modTypesTxt += '\0';
|
modTypesTxt += '\0';
|
||||||
@ -38,13 +33,6 @@ namespace module_manager_menu {
|
|||||||
float height = ImGui::CalcTextSize("-").y;
|
float height = ImGui::CalcTextSize("-").y;
|
||||||
|
|
||||||
for (auto& [name, inst] : core::moduleManager.instances) {
|
for (auto& [name, inst] : core::moduleManager.instances) {
|
||||||
// TEMPORARY EXCLUSION FOR SOURCES AND SINKS
|
|
||||||
std::string type = inst.module.info->name;
|
|
||||||
if (type.find("source") != std::string::npos) { continue; }
|
|
||||||
if (type.find("sink") != std::string::npos) { continue; }
|
|
||||||
if (type.find("recorder") != std::string::npos) { continue; }
|
|
||||||
if (type.find("discord") != std::string::npos) { continue; }
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
@ -83,6 +71,7 @@ namespace module_manager_menu {
|
|||||||
if (strlen(modName) == 0) { style::beginDisabled(); }
|
if (strlen(modName) == 0) { style::beginDisabled(); }
|
||||||
if (ImGui::Button("+##module_mgr_add_btn", ImVec2(16,0))) {
|
if (ImGui::Button("+##module_mgr_add_btn", ImVec2(16,0))) {
|
||||||
core::moduleManager.createInstance(modName, modTypes[modTypeId]);
|
core::moduleManager.createInstance(modName, modTypes[modTypeId]);
|
||||||
|
core::moduleManager.postInit(modName);
|
||||||
}
|
}
|
||||||
if (strlen(modName) == 0) { style::endDisabled(); }
|
if (strlen(modName) == 0) { style::endDisabled(); }
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
|
@ -12,6 +12,14 @@ namespace sourecmenu {
|
|||||||
double customOffset = 0.0;
|
double customOffset = 0.0;
|
||||||
double effectiveOffset = 0.0;
|
double effectiveOffset = 0.0;
|
||||||
|
|
||||||
|
EventHandler<std::string> sourceRegisteredHandler;
|
||||||
|
EventHandler<std::string> sourceUnregisterHandler;
|
||||||
|
EventHandler<std::string> sourceUnregisteredHandler;
|
||||||
|
|
||||||
|
std::vector<std::string> sourceNames;
|
||||||
|
std::string sourceNamesTxt;
|
||||||
|
std::string selectedSource;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OFFSET_MODE_NONE,
|
OFFSET_MODE_NONE,
|
||||||
OFFSET_MODE_CUSTOM,
|
OFFSET_MODE_CUSTOM,
|
||||||
@ -42,41 +50,94 @@ namespace sourecmenu {
|
|||||||
sigpath::sourceManager.setTuningOffset(effectiveOffset);
|
sigpath::sourceManager.setTuningOffset(effectiveOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void refreshSources() {
|
||||||
|
sourceNames = sigpath::sourceManager.getSourceNames();
|
||||||
|
sourceNamesTxt.clear();
|
||||||
|
for (auto name : sourceNames) {
|
||||||
|
sourceNamesTxt += name;
|
||||||
|
sourceNamesTxt += '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectSource(std::string name) {
|
||||||
|
if (sourceNames.empty()) {
|
||||||
|
selectedSource.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto it = std::find(sourceNames.begin(), sourceNames.end(), name);
|
||||||
|
if (it == sourceNames.end()) {
|
||||||
|
selectSource(sourceNames[0]);
|
||||||
|
}
|
||||||
|
sourceId = std::distance(sourceNames.begin(), it);
|
||||||
|
selectedSource = sourceNames[sourceId];
|
||||||
|
sigpath::sourceManager.selectSource(sourceNames[sourceId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSourceRegistered(std::string name, void* ctx) {
|
||||||
|
refreshSources();
|
||||||
|
|
||||||
|
if (selectedSource.empty()) {
|
||||||
|
sourceId = 0;
|
||||||
|
selectSource(sourceNames[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceId = std::distance(sourceNames.begin(), std::find(sourceNames.begin(), sourceNames.end(), selectedSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSourceUnregister(std::string name, void* ctx) {
|
||||||
|
if (name != selectedSource) { return; }
|
||||||
|
|
||||||
|
// TODO: Stop everything
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSourceUnregistered(std::string name, void* ctx) {
|
||||||
|
refreshSources();
|
||||||
|
|
||||||
|
if (sourceNames.empty()) {
|
||||||
|
selectedSource = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == selectedSource) {
|
||||||
|
sourceId = std::clamp<int>(sourceId, 0, sourceNames.size() - 1);
|
||||||
|
selectSource(sourceNames[sourceId]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceId = std::distance(sourceNames.begin(), std::find(sourceNames.begin(), sourceNames.end(), selectedSource));
|
||||||
|
}
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
core::configManager.acquire();
|
core::configManager.acquire();
|
||||||
std::string name = core::configManager.conf["source"];
|
std::string selected = core::configManager.conf["source"];
|
||||||
auto it = std::find(sigpath::sourceManager.sourceNames.begin(), sigpath::sourceManager.sourceNames.end(), name);
|
|
||||||
if (it != sigpath::sourceManager.sourceNames.end()) {
|
|
||||||
sigpath::sourceManager.selectSource(name);
|
|
||||||
sourceId = std::distance(sigpath::sourceManager.sourceNames.begin(), it);
|
|
||||||
}
|
|
||||||
else if (sigpath::sourceManager.sourceNames.size() > 0) {
|
|
||||||
sigpath::sourceManager.selectSource(sigpath::sourceManager.sourceNames[0]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
spdlog::warn("No source available...");
|
|
||||||
}
|
|
||||||
customOffset = core::configManager.conf["offset"];
|
customOffset = core::configManager.conf["offset"];
|
||||||
offsetMode = core::configManager.conf["offsetMode"];
|
offsetMode = core::configManager.conf["offsetMode"];
|
||||||
updateOffset();
|
updateOffset();
|
||||||
|
|
||||||
|
refreshSources();
|
||||||
|
selectSource(selected);
|
||||||
|
|
||||||
|
sourceRegisteredHandler.handler = onSourceRegistered;
|
||||||
|
sourceUnregisterHandler.handler = onSourceUnregister;
|
||||||
|
sourceUnregisteredHandler.handler = onSourceUnregistered;
|
||||||
|
sigpath::sourceManager.onSourceRegistered.bindHandler(&sourceRegisteredHandler);
|
||||||
|
sigpath::sourceManager.onSourceUnregister.bindHandler(&sourceUnregisterHandler);
|
||||||
|
sigpath::sourceManager.onSourceUnregistered.bindHandler(&sourceUnregisteredHandler);
|
||||||
|
|
||||||
core::configManager.release();
|
core::configManager.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(void* ctx) {
|
void draw(void* ctx) {
|
||||||
std::string items = "";
|
|
||||||
for (std::string name : sigpath::sourceManager.sourceNames) {
|
|
||||||
items += name;
|
|
||||||
items += '\0';
|
|
||||||
}
|
|
||||||
float itemWidth = ImGui::GetContentRegionAvailWidth();
|
float itemWidth = ImGui::GetContentRegionAvailWidth();
|
||||||
|
|
||||||
if (gui::mainWindow.sdrIsRunning()) { style::beginDisabled(); }
|
if (gui::mainWindow.sdrIsRunning()) { style::beginDisabled(); }
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(itemWidth);
|
ImGui::SetNextItemWidth(itemWidth);
|
||||||
if (ImGui::Combo("##source", &sourceId, items.c_str())) {
|
if (ImGui::Combo("##source", &sourceId, sourceNamesTxt.c_str())) {
|
||||||
sigpath::sourceManager.selectSource(sigpath::sourceManager.sourceNames[sourceId]);
|
selectSource(sourceNames[sourceId]);
|
||||||
core::configManager.acquire();
|
core::configManager.acquire();
|
||||||
core::configManager.conf["source"] = sigpath::sourceManager.sourceNames[sourceId];
|
core::configManager.conf["source"] = sourceNames[sourceId];
|
||||||
core::configManager.release(true);
|
core::configManager.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +171,5 @@ namespace sourecmenu {
|
|||||||
ImGui::InputDouble("##freq_offset", &effectiveOffset, 1.0, 100.0);
|
ImGui::InputDouble("##freq_offset", &effectiveOffset, 1.0, 100.0);
|
||||||
style::endDisabled();
|
style::endDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,14 @@ bool ModuleManager::instanceEnabled(std::string name) {
|
|||||||
return instances[name].instance->isEnabled();
|
return instances[name].instance->isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModuleManager::postInit(std::string name) {
|
||||||
|
if (instances.find(name) == instances.end()) {
|
||||||
|
spdlog::error("Cannot post-init '{0}', instance doesn't exist", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
instances[name].instance->postInit();
|
||||||
|
}
|
||||||
|
|
||||||
std::string ModuleManager::getInstanceModuleName(std::string name) {
|
std::string ModuleManager::getInstanceModuleName(std::string name) {
|
||||||
if (instances.find(name) == instances.end()) {
|
if (instances.find(name) == instances.end()) {
|
||||||
spdlog::error("Cannot get module name of'{0}', instance doesn't exist", name);
|
spdlog::error("Cannot get module name of'{0}', instance doesn't exist", name);
|
||||||
@ -159,4 +167,11 @@ int ModuleManager::countModuleInstances(std::string module) {
|
|||||||
if (instance.module == mod) { count++; }
|
if (instance.module == mod) { count++; }
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleManager::doPostInitAll() {
|
||||||
|
for (auto& [name, inst] : instances) {
|
||||||
|
spdlog::info("Running post-init for {0}", name);
|
||||||
|
inst.instance->postInit();
|
||||||
|
}
|
||||||
}
|
}
|
@ -42,6 +42,7 @@ public:
|
|||||||
|
|
||||||
class Instance {
|
class Instance {
|
||||||
public:
|
public:
|
||||||
|
virtual void postInit() = 0;
|
||||||
virtual void enable() = 0;
|
virtual void enable() = 0;
|
||||||
virtual void disable() = 0;
|
virtual void disable() = 0;
|
||||||
virtual bool isEnabled() = 0;
|
virtual bool isEnabled() = 0;
|
||||||
@ -84,10 +85,13 @@ public:
|
|||||||
void enableInstance(std::string name);
|
void enableInstance(std::string name);
|
||||||
void disableInstance(std::string name);
|
void disableInstance(std::string name);
|
||||||
bool instanceEnabled(std::string name);
|
bool instanceEnabled(std::string name);
|
||||||
|
void postInit(std::string name);
|
||||||
std::string getInstanceModuleName(std::string name);
|
std::string getInstanceModuleName(std::string name);
|
||||||
|
|
||||||
int countModuleInstances(std::string module);
|
int countModuleInstances(std::string module);
|
||||||
|
|
||||||
|
void doPostInitAll();
|
||||||
|
|
||||||
Event<std::string> onInstanceCreated;
|
Event<std::string> onInstanceCreated;
|
||||||
Event<std::string> onInstanceDelete;
|
Event<std::string> onInstanceDelete;
|
||||||
Event<std::string> onInstanceDeleted;
|
Event<std::string> onInstanceDeleted;
|
||||||
|
@ -115,7 +115,7 @@ void SinkManager::registerStream(std::string name, SinkManager::Stream* stream)
|
|||||||
core::configManager.release();
|
core::configManager.release();
|
||||||
if (available) { loadStreamConfig(name); }
|
if (available) { loadStreamConfig(name); }
|
||||||
|
|
||||||
streamRegisteredEvnt.emit(name);
|
onStreamRegistered.emit(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SinkManager::unregisterStream(std::string name) {
|
void SinkManager::unregisterStream(std::string name) {
|
||||||
@ -123,12 +123,13 @@ void SinkManager::unregisterStream(std::string name) {
|
|||||||
spdlog::error("Cannot unregister stream '{0}', this stream doesn't exist", name);
|
spdlog::error("Cannot unregister stream '{0}', this stream doesn't exist", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
streamUnregisteredEvnt.emit(name);
|
onStreamUnregister.emit(name);
|
||||||
SinkManager::Stream* stream = streams[name];
|
SinkManager::Stream* stream = streams[name];
|
||||||
stream->stop();
|
stream->stop();
|
||||||
delete stream->sink;
|
delete stream->sink;
|
||||||
streams.erase(name);
|
streams.erase(name);
|
||||||
streamNames.erase(std::remove(streamNames.begin(), streamNames.end(), name), streamNames.end());
|
streamNames.erase(std::remove(streamNames.begin(), streamNames.end(), name), streamNames.end());
|
||||||
|
onStreamUnregistered.emit(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SinkManager::startStream(std::string name) {
|
void SinkManager::startStream(std::string name) {
|
||||||
|
@ -110,8 +110,9 @@ public:
|
|||||||
|
|
||||||
std::vector<std::string> getStreamNames();
|
std::vector<std::string> getStreamNames();
|
||||||
|
|
||||||
Event<std::string> streamRegisteredEvnt;
|
Event<std::string> onStreamRegistered;
|
||||||
Event<std::string> streamUnregisteredEvnt;
|
Event<std::string> onStreamUnregister;
|
||||||
|
Event<std::string> onStreamUnregistered;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadStreamConfig(std::string name);
|
void loadStreamConfig(std::string name);
|
||||||
|
@ -12,7 +12,27 @@ void SourceManager::registerSource(std::string name, SourceHandler* handler) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sources[name] = handler;
|
sources[name] = handler;
|
||||||
sourceNames.push_back(name);
|
onSourceRegistered.emit(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceManager::unregisterSource(std::string name) {
|
||||||
|
if (sources.find(name) == sources.end()) {
|
||||||
|
spdlog::error("Tried to unregister non existant source: {0}", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onSourceUnregister.emit(name);
|
||||||
|
if (name == selectedName) {
|
||||||
|
sigpath::signalPath.setInput(&nullSource);
|
||||||
|
selectedHandler = NULL;
|
||||||
|
}
|
||||||
|
sources.erase(name);
|
||||||
|
onSourceUnregistered.emit(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> SourceManager::getSourceNames() {
|
||||||
|
std::vector<std::string> names;
|
||||||
|
for (auto const& [name, src] : sources) { names.push_back(name); }
|
||||||
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceManager::selectSource(std::string name) {
|
void SourceManager::selectSource(std::string name) {
|
||||||
@ -20,7 +40,7 @@ void SourceManager::selectSource(std::string name) {
|
|||||||
spdlog::error("Tried to select non existant source: {0}", name);
|
spdlog::error("Tried to select non existant source: {0}", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (selectedName != "") {
|
if (selectedHandler != NULL) {
|
||||||
sources[selectedName]->deselectHandler(sources[selectedName]->ctx);
|
sources[selectedName]->deselectHandler(sources[selectedName]->ctx);
|
||||||
}
|
}
|
||||||
selectedHandler = sources[name];
|
selectedHandler = sources[name];
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <dsp/stream.h>
|
#include <dsp/stream.h>
|
||||||
#include <dsp/types.h>
|
#include <dsp/types.h>
|
||||||
|
#include <utils/event.h>
|
||||||
|
|
||||||
class SourceManager {
|
class SourceManager {
|
||||||
public:
|
public:
|
||||||
@ -21,6 +22,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void registerSource(std::string name, SourceHandler* handler);
|
void registerSource(std::string name, SourceHandler* handler);
|
||||||
|
void unregisterSource(std::string name);
|
||||||
void selectSource(std::string name);
|
void selectSource(std::string name);
|
||||||
void showSelectedMenu();
|
void showSelectedMenu();
|
||||||
void start();
|
void start();
|
||||||
@ -28,7 +30,11 @@ public:
|
|||||||
void tune(double freq);
|
void tune(double freq);
|
||||||
void setTuningOffset(double offset);
|
void setTuningOffset(double offset);
|
||||||
|
|
||||||
std::vector<std::string> sourceNames;
|
std::vector<std::string> getSourceNames();
|
||||||
|
|
||||||
|
Event<std::string> onSourceRegistered;
|
||||||
|
Event<std::string> onSourceUnregister;
|
||||||
|
Event<std::string> onSourceUnregistered;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, SourceHandler*> sources;
|
std::map<std::string, SourceHandler*> sources;
|
||||||
@ -36,5 +42,6 @@ private:
|
|||||||
SourceHandler* selectedHandler = NULL;
|
SourceHandler* selectedHandler = NULL;
|
||||||
double tuneOffset;
|
double tuneOffset;
|
||||||
double currentFreq;
|
double currentFreq;
|
||||||
|
dsp::stream<dsp::complex_t> nullSource;
|
||||||
|
|
||||||
};
|
};
|
@ -21,6 +21,8 @@ public:
|
|||||||
gui::menu.removeEntry(name);
|
gui::menu.removeEntry(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,12 @@ public:
|
|||||||
// Change to timer stop later on
|
// Change to timer stop later on
|
||||||
workerRunning = false;
|
workerRunning = false;
|
||||||
if (workerThread.joinable()) { workerThread.join(); }
|
if (workerThread.joinable()) { workerThread.join(); }
|
||||||
|
Discord_ClearPresence();
|
||||||
|
Discord_Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
// Change to timer start later on
|
// Change to timer start later on
|
||||||
workerRunning = true;
|
workerRunning = true;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <signal_path/signal_path.h>
|
#include <signal_path/signal_path.h>
|
||||||
#include <module.h>
|
#include <module.h>
|
||||||
#include <options.h>
|
#include <options.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
#include <dsp/pll.h>
|
#include <dsp/pll.h>
|
||||||
#include <dsp/stream.h>
|
#include <dsp/stream.h>
|
||||||
#include <dsp/demodulator.h>
|
#include <dsp/demodulator.h>
|
||||||
@ -87,6 +87,8 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 4000000, INPUT_SAMPLE_RATE, 4000000, 4000000, true);
|
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 4000000, INPUT_SAMPLE_RATE, 4000000, 4000000, true);
|
||||||
|
|
||||||
@ -155,7 +157,7 @@ private:
|
|||||||
if (ImGui::Button("Clear logs##GPSClear")) { _this->gpsLogs.clear(); }
|
if (ImGui::Button("Clear logs##GPSClear")) { _this->gpsLogs.clear(); }
|
||||||
ImGui::BeginChild(ImGuiID("GPSChild"));
|
ImGui::BeginChild(ImGuiID("GPSChild"));
|
||||||
ImGui::TextUnformatted(_this->gpsLogs.c_str());
|
ImGui::TextUnformatted(_this->gpsLogs.c_str());
|
||||||
ImGui::SetScrollHere(1.0f);
|
ImGui::SetScrollHereY(1.0f);
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
|
|
||||||
|
@ -41,15 +41,15 @@ public:
|
|||||||
handler.tuneHandler = tune;
|
handler.tuneHandler = tune;
|
||||||
handler.stream = &stream;
|
handler.stream = &stream;
|
||||||
sigpath::sourceManager.registerSource("File", &handler);
|
sigpath::sourceManager.registerSource("File", &handler);
|
||||||
|
|
||||||
spdlog::info("FileSourceModule '{0}': Instance created!", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~FileSourceModule() {
|
~FileSourceModule() {
|
||||||
|
stop(this);
|
||||||
spdlog::info("FileSourceModule '{0}': Instance deleted!", name);
|
sigpath::sourceManager.unregisterSource("File");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,8 @@ public:
|
|||||||
gui::waterfall.onInputProcess.unbindHandler(&inputHandler);
|
gui::waterfall.onInputProcess.unbindHandler(&inputHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -104,9 +104,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
~HackRFSourceModule() {
|
~HackRFSourceModule() {
|
||||||
|
stop(this);
|
||||||
hackrf_exit();
|
hackrf_exit();
|
||||||
|
sigpath::sourceManager.unregisterSource("HackRF");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
|
@ -44,15 +44,17 @@ public:
|
|||||||
|
|
||||||
// Select device from config
|
// Select device from config
|
||||||
selectFirst();
|
selectFirst();
|
||||||
core::setInputSampleRate(sampleRate);
|
|
||||||
|
|
||||||
sigpath::sourceManager.registerSource("LimeSDR", &handler);
|
sigpath::sourceManager.registerSource("LimeSDR", &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
~LimeSDRSourceModule() {
|
~LimeSDRSourceModule() {
|
||||||
// Exit limesuite if needed
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("LimeSDR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,8 @@ public:
|
|||||||
gui::menu.removeEntry(name);
|
gui::menu.removeEntry(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
double bw = gui::waterfall.getBandwidth();
|
double bw = gui::waterfall.getBandwidth();
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw/2.0, bw/2.0), 150000, INPUT_SAMPLE_RATE, 150000, 150000, true);
|
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw/2.0, bw/2.0), 150000, INPUT_SAMPLE_RATE, 150000, 150000, true);
|
||||||
|
@ -398,6 +398,8 @@ public:
|
|||||||
Pa_Terminate();
|
Pa_Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -50,14 +50,15 @@ public:
|
|||||||
handler.tuneHandler = tune;
|
handler.tuneHandler = tune;
|
||||||
handler.stream = &stream;
|
handler.stream = &stream;
|
||||||
sigpath::sourceManager.registerSource("PlutoSDR", &handler);
|
sigpath::sourceManager.registerSource("PlutoSDR", &handler);
|
||||||
|
|
||||||
spdlog::info("PlutoSDRSourceModule '{0}': Instance created!", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~PlutoSDRSourceModule() {
|
~PlutoSDRSourceModule() {
|
||||||
spdlog::info("PlutoSDRSourceModule '{0}': Instance deleted!", name);
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("PlutoSDR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -296,6 +296,8 @@ public:
|
|||||||
Pa_Terminate();
|
Pa_Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,8 @@ public:
|
|||||||
sigpath::sinkManager.unregisterStream(name);
|
sigpath::sinkManager.unregisterStream(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
double bw = gui::waterfall.getBandwidth();
|
double bw = gui::waterfall.getBandwidth();
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw/2.0, bw/2.0), 200000, 200000, 50000, 200000, false);
|
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw/2.0, bw/2.0), 200000, 200000, 50000, 200000, false);
|
||||||
|
@ -84,40 +84,51 @@ public:
|
|||||||
|
|
||||||
wavSampleBuf = new int16_t[2 * STREAM_BUFFER_SIZE];
|
wavSampleBuf = new int16_t[2 * STREAM_BUFFER_SIZE];
|
||||||
|
|
||||||
refreshStreams();
|
|
||||||
|
|
||||||
gui::menu.registerEntry(name, menuHandler, this);
|
gui::menu.registerEntry(name, menuHandler, this);
|
||||||
core::modComManager.registerInterface("recorder", name, moduleInterfaceHandler, this);
|
core::modComManager.registerInterface("recorder", name, moduleInterfaceHandler, this);
|
||||||
|
|
||||||
|
streamRegisteredHandler.handler = onStreamRegistered;
|
||||||
|
streamRegisteredHandler.ctx = this;
|
||||||
|
streamUnregisterHandler.handler = onStreamUnregister;
|
||||||
|
streamUnregisterHandler.ctx = this;
|
||||||
|
streamUnregisteredHandler.handler = onStreamUnregistered;
|
||||||
|
streamUnregisteredHandler.ctx = this;
|
||||||
|
sigpath::sinkManager.onStreamRegistered.bindHandler(&streamRegisteredHandler);
|
||||||
|
sigpath::sinkManager.onStreamUnregister.bindHandler(&streamUnregisterHandler);
|
||||||
|
sigpath::sinkManager.onStreamUnregistered.bindHandler(&streamUnregisteredHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
~RecorderModule() {
|
~RecorderModule() {
|
||||||
|
std::lock_guard lck(recMtx);
|
||||||
|
gui::menu.removeEntry(name);
|
||||||
core::modComManager.unregisterInterface(name);
|
core::modComManager.unregisterInterface(name);
|
||||||
|
|
||||||
// Stop recording
|
// Stop recording
|
||||||
if (recording) {
|
if (recording) { stopRecording(); }
|
||||||
if (recMode == RECORDER_MODE_AUDIO) {
|
|
||||||
audioSplit.unbindStream(&audioHandlerStream);
|
if (audioInput != NULL) { sigpath::sinkManager.unbindStream(selectedStreamName, audioInput); }
|
||||||
audioHandler.stop();
|
|
||||||
audioWriter->close();
|
sigpath::sinkManager.onStreamRegistered.unbindHandler(&streamRegisteredHandler);
|
||||||
delete audioWriter;
|
sigpath::sinkManager.onStreamUnregister.unbindHandler(&streamUnregisterHandler);
|
||||||
}
|
sigpath::sinkManager.onStreamUnregistered.unbindHandler(&streamUnregisteredHandler);
|
||||||
else {
|
|
||||||
sigpath::signalPath.unbindIQStream(&basebandStream);
|
|
||||||
basebandHandler.stop();
|
|
||||||
basebandWriter->close();
|
|
||||||
delete basebandWriter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vol.stop();
|
vol.stop();
|
||||||
audioSplit.stop();
|
audioSplit.stop();
|
||||||
meter.stop();
|
meter.stop();
|
||||||
|
|
||||||
gui::menu.removeEntry(name);
|
|
||||||
|
|
||||||
delete[] wavSampleBuf;
|
delete[] wavSampleBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {
|
||||||
|
refreshStreams();
|
||||||
|
if (selectedStreamName == "") {
|
||||||
|
selectStream(streamNames[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
selectStream(selectedStreamName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
@ -134,35 +145,39 @@ private:
|
|||||||
void refreshStreams() {
|
void refreshStreams() {
|
||||||
std::vector<std::string> names = sigpath::sinkManager.getStreamNames();
|
std::vector<std::string> names = sigpath::sinkManager.getStreamNames();
|
||||||
|
|
||||||
// If there are no stream, cancel
|
|
||||||
if (names.size() == 0) { return; }
|
|
||||||
|
|
||||||
// List streams
|
|
||||||
streamNames.clear();
|
streamNames.clear();
|
||||||
streamNamesTxt = "";
|
streamNamesTxt = "";
|
||||||
|
|
||||||
|
// If there are no stream, cancel
|
||||||
|
if (names.size() == 0) {return; }
|
||||||
|
|
||||||
|
// List streams
|
||||||
for (auto const& name : names) {
|
for (auto const& name : names) {
|
||||||
streamNames.push_back(name);
|
streamNames.push_back(name);
|
||||||
streamNamesTxt += name;
|
streamNamesTxt += name;
|
||||||
streamNamesTxt += '\0';
|
streamNamesTxt += '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedStreamName == "") {
|
|
||||||
selectStream(streamNames[0]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
selectStream(selectedStreamName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectStream(std::string name) {
|
void selectStream(std::string name) {
|
||||||
|
if (streamNames.empty()) {
|
||||||
|
selectedStreamName = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto it = std::find(streamNames.begin(), streamNames.end(), name);
|
auto it = std::find(streamNames.begin(), streamNames.end(), name);
|
||||||
if (it == streamNames.end()) { return; }
|
if (it == streamNames.end()) {
|
||||||
|
selectStream(streamNames[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
streamId = std::distance(streamNames.begin(), it);
|
streamId = std::distance(streamNames.begin(), it);
|
||||||
|
|
||||||
vol.stop();
|
vol.stop();
|
||||||
if (audioInput != NULL) { sigpath::sinkManager.unbindStream(selectedStreamName, audioInput); }
|
if (audioInput != NULL) { sigpath::sinkManager.unbindStream(selectedStreamName, audioInput); }
|
||||||
audioInput = sigpath::sinkManager.bindStream(name);
|
audioInput = sigpath::sinkManager.bindStream(name);
|
||||||
if (audioInput == NULL) { return; }
|
if (audioInput == NULL) {
|
||||||
|
selectedStreamName = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
selectedStreamName = name;
|
selectedStreamName = name;
|
||||||
vol.setInput(audioInput);
|
vol.setInput(audioInput);
|
||||||
vol.start();
|
vol.start();
|
||||||
@ -237,8 +252,6 @@ private:
|
|||||||
ImGui::PushItemWidth(menuColumnWidth);
|
ImGui::PushItemWidth(menuColumnWidth);
|
||||||
|
|
||||||
if (streamNames.size() == 0) {
|
if (streamNames.size() == 0) {
|
||||||
refreshStreams();
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,6 +352,9 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (recMode == RECORDER_MODE_AUDIO) {
|
else if (recMode == RECORDER_MODE_AUDIO) {
|
||||||
|
if (selectedStreamName.empty()) {
|
||||||
|
spdlog::error("Cannot record with no selected stream");
|
||||||
|
}
|
||||||
samplesWritten = 0;
|
samplesWritten = 0;
|
||||||
std::string expandedPath = expandString(folderSelect.path + genFileName("/audio_", true, selectedStreamName));
|
std::string expandedPath = expandString(folderSelect.path + genFileName("/audio_", true, selectedStreamName));
|
||||||
sampleRate = sigpath::sinkManager.getStreamSampleRate(selectedStreamName);
|
sampleRate = sigpath::sinkManager.getStreamSampleRate(selectedStreamName);
|
||||||
@ -372,6 +388,69 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void onStreamRegistered(std::string name, void* ctx){
|
||||||
|
RecorderModule* _this = (RecorderModule*)ctx;
|
||||||
|
_this->refreshStreams();
|
||||||
|
|
||||||
|
if (_this->streamNames.empty()) {
|
||||||
|
_this->selectedStreamName = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_this->selectedStreamName.empty()) {
|
||||||
|
_this->streamId = 0;
|
||||||
|
_this->selectedStreamName = _this->streamNames[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reselect stream in UI to make sure the ID is correct
|
||||||
|
int id = 0;
|
||||||
|
for (auto& str : _this->streamNames) {
|
||||||
|
if (str == _this->selectedStreamName) {
|
||||||
|
_this->streamId = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onStreamUnregister(std::string name, void* ctx){
|
||||||
|
RecorderModule* _this = (RecorderModule*)ctx;
|
||||||
|
if (name != _this->selectedStreamName) { return; }
|
||||||
|
if (_this->recording) { _this->stopRecording(); }
|
||||||
|
if (_this->audioInput != NULL) {
|
||||||
|
sigpath::sinkManager.unbindStream(_this->selectedStreamName, _this->audioInput);
|
||||||
|
_this->audioInput = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onStreamUnregistered(std::string name, void* ctx){
|
||||||
|
RecorderModule* _this = (RecorderModule*)ctx;
|
||||||
|
_this->refreshStreams();
|
||||||
|
|
||||||
|
if (_this->streamNames.empty()) {
|
||||||
|
_this->selectedStreamName = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If current stream was deleted, reselect steam completely
|
||||||
|
if (name == _this->selectedStreamName) {
|
||||||
|
_this->streamId = std::clamp<int>(_this->streamId, 0, _this->streamNames.size() - 1);
|
||||||
|
_this->selectStream(_this->streamNames[_this->streamId]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reselect stream in UI to make sure the ID is correct
|
||||||
|
int id = 0;
|
||||||
|
for (auto& str : _this->streamNames) {
|
||||||
|
if (str == _this->selectedStreamName) {
|
||||||
|
_this->streamId = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
@ -415,6 +494,10 @@ private:
|
|||||||
uint64_t samplesWritten;
|
uint64_t samplesWritten;
|
||||||
int16_t* wavSampleBuf;
|
int16_t* wavSampleBuf;
|
||||||
|
|
||||||
|
EventHandler<std::string> streamRegisteredHandler;
|
||||||
|
EventHandler<std::string> streamUnregisterHandler;
|
||||||
|
EventHandler<std::string> streamUnregisteredHandler;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RecorderContext_t {
|
struct RecorderContext_t {
|
||||||
|
@ -53,16 +53,41 @@ public:
|
|||||||
selectedRecorder = config.conf[name]["recorder"];
|
selectedRecorder = config.conf[name]["recorder"];
|
||||||
config.release(true);
|
config.release(true);
|
||||||
|
|
||||||
initHandler.handler = _initHandler;
|
|
||||||
initHandler.ctx = this;
|
|
||||||
gui::mainWindow.onInitComplete.bindHandler(&initHandler);
|
|
||||||
|
|
||||||
gui::menu.registerEntry(name, menuHandler, this, NULL);
|
gui::menu.registerEntry(name, menuHandler, this, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SigctlServerModule() {
|
~SigctlServerModule() {
|
||||||
gui::menu.removeEntry(name);
|
gui::menu.removeEntry(name);
|
||||||
// TODO: Use several handler instead of one for the recorders and remove event bindings
|
sigpath::vfoManager.onVfoCreated.unbindHandler(&vfoCreatedHandler);
|
||||||
|
sigpath::vfoManager.onVfoDeleted.unbindHandler(&vfoDeletedHandler);
|
||||||
|
core::moduleManager.onInstanceCreated.unbindHandler(&modChangedHandler);
|
||||||
|
core::moduleManager.onInstanceDeleted.unbindHandler(&modChangedHandler);
|
||||||
|
if (client) { client->close(); }
|
||||||
|
if (listener) { listener->close(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void postInit() {
|
||||||
|
// Refresh modules
|
||||||
|
refreshModules();
|
||||||
|
|
||||||
|
// Select VFO and recorder from config
|
||||||
|
selectVfoByName(selectedVfo);
|
||||||
|
selectRecorderByName(selectedRecorder);
|
||||||
|
|
||||||
|
// Bind handlers
|
||||||
|
vfoCreatedHandler.handler = _vfoCreatedHandler;
|
||||||
|
vfoCreatedHandler.ctx = this;
|
||||||
|
vfoDeletedHandler.handler = _vfoDeletedHandler;
|
||||||
|
vfoDeletedHandler.ctx = this;
|
||||||
|
modChangedHandler.handler = _modChangeHandler;
|
||||||
|
modChangedHandler.ctx = this;
|
||||||
|
sigpath::vfoManager.onVfoCreated.bindHandler(&vfoCreatedHandler);
|
||||||
|
sigpath::vfoManager.onVfoDeleted.bindHandler(&vfoDeletedHandler);
|
||||||
|
core::moduleManager.onInstanceCreated.bindHandler(&modChangedHandler);
|
||||||
|
core::moduleManager.onInstanceDeleted.bindHandler(&modChangedHandler);
|
||||||
|
|
||||||
|
// If autostart is enabled, start the server
|
||||||
|
if (autoStart) { startServer(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
@ -262,32 +287,6 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _initHandler(bool dummy, void* ctx) {
|
|
||||||
SigctlServerModule* _this = (SigctlServerModule*)ctx;
|
|
||||||
|
|
||||||
// Refresh modules
|
|
||||||
_this->refreshModules();
|
|
||||||
|
|
||||||
// Select VFO and recorder from config
|
|
||||||
_this->selectVfoByName(_this->selectedVfo);
|
|
||||||
_this->selectRecorderByName(_this->selectedRecorder);
|
|
||||||
|
|
||||||
// Bind handlers
|
|
||||||
_this->vfoCreatedHandler.handler = _vfoCreatedHandler;
|
|
||||||
_this->vfoCreatedHandler.ctx = _this;
|
|
||||||
_this->vfoDeletedHandler.handler = _vfoDeletedHandler;
|
|
||||||
_this->vfoDeletedHandler.ctx = _this;
|
|
||||||
_this->modChangedHandler.handler = _modChangeHandler;
|
|
||||||
_this->modChangedHandler.ctx = _this;
|
|
||||||
sigpath::vfoManager.onVfoCreated.bindHandler(&_this->vfoCreatedHandler);
|
|
||||||
sigpath::vfoManager.onVfoDeleted.bindHandler(&_this->vfoDeletedHandler);
|
|
||||||
core::moduleManager.onInstanceCreated.bindHandler(&_this->modChangedHandler);
|
|
||||||
core::moduleManager.onInstanceDeleted.bindHandler(&_this->modChangedHandler);
|
|
||||||
|
|
||||||
// If autostart is enabled, start the server
|
|
||||||
if (_this->autoStart) { _this->startServer(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _vfoCreatedHandler(VFOManager::VFO* vfo, void* ctx) {
|
static void _vfoCreatedHandler(VFOManager::VFO* vfo, void* ctx) {
|
||||||
SigctlServerModule* _this = (SigctlServerModule*)ctx;
|
SigctlServerModule* _this = (SigctlServerModule*)ctx;
|
||||||
_this->refreshModules();
|
_this->refreshModules();
|
||||||
@ -465,7 +464,6 @@ private:
|
|||||||
|
|
||||||
std::string command = "";
|
std::string command = "";
|
||||||
|
|
||||||
EventHandler<bool> initHandler;
|
|
||||||
EventHandler<std::string> modChangedHandler;
|
EventHandler<std::string> modChangedHandler;
|
||||||
EventHandler<VFOManager::VFO*> vfoCreatedHandler;
|
EventHandler<VFOManager::VFO*> vfoCreatedHandler;
|
||||||
EventHandler<std::string> vfoDeletedHandler;
|
EventHandler<std::string> vfoDeletedHandler;
|
||||||
|
@ -88,15 +88,16 @@ public:
|
|||||||
config.release(true);
|
config.release(true);
|
||||||
selectByName(selectedDevName);
|
selectByName(selectedDevName);
|
||||||
|
|
||||||
core::setInputSampleRate(sampleRate);
|
|
||||||
|
|
||||||
sigpath::sourceManager.registerSource("RTL-SDR", &handler);
|
sigpath::sourceManager.registerSource("RTL-SDR", &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
~RTLSDRSourceModule() {
|
~RTLSDRSourceModule() {
|
||||||
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("RTL-SDR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -87,9 +87,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
~RTLTCPSourceModule() {
|
~RTLTCPSourceModule() {
|
||||||
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("RTL-TCP");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -44,15 +44,16 @@ public:
|
|||||||
|
|
||||||
selectFirst();
|
selectFirst();
|
||||||
|
|
||||||
core::setInputSampleRate(sampleRate);
|
|
||||||
|
|
||||||
sigpath::sourceManager.registerSource("SDDC", &handler);
|
sigpath::sourceManager.registerSource("SDDC", &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
~AirspyHFSourceModule() {
|
~AirspyHFSourceModule() {
|
||||||
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("SDDC");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -155,9 +155,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
~SDRPlaySourceModule() {
|
~SDRPlaySourceModule() {
|
||||||
|
stop(this);
|
||||||
sdrplay_api_Close();
|
sdrplay_api_Close();
|
||||||
|
sigpath::sourceManager.unregisterSource("SDRplay");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -50,14 +50,15 @@ public:
|
|||||||
handler.tuneHandler = tune;
|
handler.tuneHandler = tune;
|
||||||
handler.stream = &stream;
|
handler.stream = &stream;
|
||||||
sigpath::sourceManager.registerSource("SoapySDR", &handler);
|
sigpath::sourceManager.registerSource("SoapySDR", &handler);
|
||||||
|
|
||||||
spdlog::info("SoapyModule '{0}': Instance created!", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~SoapyModule() {
|
~SoapyModule() {
|
||||||
spdlog::info("SoapyModule '{0}': Instance deleted!", name);
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("SoapySDR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
~AirspyHFSourceModule() {
|
~AirspyHFSourceModule() {
|
||||||
|
stop(this);
|
||||||
|
sigpath::sourceManager.unregisterSource("SpyServer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,8 @@ public:
|
|||||||
decoder->stop();
|
decoder->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void postInit() {}
|
||||||
|
|
||||||
void enable() {
|
void enable() {
|
||||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 1000000, 1000000, 1000000, 1000000, true);
|
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 1000000, 1000000, 1000000, 1000000, true);
|
||||||
for (auto const& [name, dec] : decoders) { dec->setVFO(vfo); }
|
for (auto const& [name, dec] : decoders) { dec->setVFO(vfo); }
|
||||||
|
Loading…
Reference in New Issue
Block a user