2022-05-02 11:58:05 +02:00
|
|
|
#include "recorder.h"
|
|
|
|
|
#include "core/config.h"
|
|
|
|
|
#include "common/utils.h"
|
2022-05-02 18:59:03 +02:00
|
|
|
#include "core/style.h"
|
|
|
|
|
#include "logger.h"
|
2022-05-03 17:00:43 +02:00
|
|
|
#include "imgui/imgui_stdlib.h"
|
|
|
|
|
#include "core/pipeline.h"
|
|
|
|
|
|
|
|
|
|
#include "main_ui.h"
|
2022-05-02 11:58:05 +02:00
|
|
|
|
2022-05-06 17:02:51 +02:00
|
|
|
#include "imgui/imgui_internal.h"
|
|
|
|
|
|
2022-05-07 20:18:47 +02:00
|
|
|
#include "processing.h"
|
|
|
|
|
|
2022-11-29 20:15:06 +01:00
|
|
|
#include "resources.h"
|
|
|
|
|
|
2022-05-02 11:58:05 +02:00
|
|
|
namespace satdump
|
|
|
|
|
{
|
|
|
|
|
RecorderApplication::RecorderApplication()
|
2022-05-03 17:00:43 +02:00
|
|
|
: Application("recorder"), pipeline_selector(true)
|
2022-05-02 11:58:05 +02:00
|
|
|
{
|
2022-05-02 18:59:03 +02:00
|
|
|
dsp::registerAllSources();
|
|
|
|
|
|
2023-05-20 19:19:44 +02:00
|
|
|
automated_live_output_dir = config::main_cfg["satdump_directories"]["live_processing_autogen"]["value"].get<bool>();
|
2022-07-30 20:29:37 +02:00
|
|
|
processing_modules_floating_windows = config::main_cfg["user_interface"]["recorder_floating_windows"]["value"].get<bool>();
|
2022-05-06 18:06:57 +02:00
|
|
|
|
2022-05-02 18:59:03 +02:00
|
|
|
sources = dsp::getAllAvailableSources();
|
|
|
|
|
|
|
|
|
|
for (dsp::SourceDescriptor src : sources)
|
|
|
|
|
{
|
|
|
|
|
logger->debug("Device " + src.name);
|
|
|
|
|
sdr_select_string += src.name + '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-28 01:05:30 +02:00
|
|
|
for (int i = 0; i < (int)sources.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
source_ptr = dsp::getSourceFromDescriptor(sources[i]);
|
|
|
|
|
source_ptr->open();
|
|
|
|
|
sdr_select_id = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
catch (std::runtime_error &e)
|
|
|
|
|
{
|
|
|
|
|
logger->error(e.what());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-29 20:15:06 +01:00
|
|
|
// Load waterfall palettes
|
|
|
|
|
{
|
|
|
|
|
waterfall_palettes_str = "";
|
|
|
|
|
std::filesystem::recursive_directory_iterator paletteIterator(resources::getResourcePath("waterfall"));
|
|
|
|
|
std::error_code iteratorError;
|
|
|
|
|
while (paletteIterator != std::filesystem::recursive_directory_iterator())
|
|
|
|
|
{
|
|
|
|
|
if (!std::filesystem::is_directory(paletteIterator->path()))
|
|
|
|
|
{
|
|
|
|
|
auto map = colormaps::loadMap(paletteIterator->path().string());
|
|
|
|
|
waterfall_palettes.push_back(map);
|
|
|
|
|
waterfall_palettes_str += map.name + " [" + map.author + "]" + '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
paletteIterator.increment(iteratorError);
|
|
|
|
|
if (iteratorError)
|
|
|
|
|
logger->critical(iteratorError.message());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-29 18:00:19 +02:00
|
|
|
set_frequency(frequency_mhz);
|
2022-10-11 21:14:56 +02:00
|
|
|
try_load_sdr_settings();
|
2022-05-02 18:59:03 +02:00
|
|
|
|
2022-05-02 20:04:54 +02:00
|
|
|
splitter = std::make_shared<dsp::SplitterBlock>(source_ptr->output_stream);
|
2023-02-19 18:19:01 +01:00
|
|
|
splitter->add_output("record");
|
|
|
|
|
splitter->add_output("live");
|
2022-05-02 20:04:54 +02:00
|
|
|
|
2022-08-15 12:38:39 +02:00
|
|
|
fft = std::make_shared<dsp::FFTPanBlock>(splitter->output_stream);
|
2023-01-23 17:58:03 +01:00
|
|
|
fft->set_fft_settings(fft_size, get_samplerate(), fft_rate);
|
2022-12-12 15:14:24 +01:00
|
|
|
fft->avg_rate = 0.1;
|
2022-05-02 20:04:54 +02:00
|
|
|
fft->start();
|
2022-05-02 18:59:03 +02:00
|
|
|
|
2023-02-19 18:19:01 +01:00
|
|
|
file_sink = std::make_shared<dsp::FileSinkBlock>(splitter->get_output("record"));
|
2022-05-03 23:53:23 +02:00
|
|
|
file_sink->set_output_sample_type(dsp::CF_32);
|
2022-05-02 22:05:54 +02:00
|
|
|
file_sink->start();
|
|
|
|
|
|
2022-05-02 18:59:03 +02:00
|
|
|
fft_plot = std::make_shared<widgets::FFTPlot>(fft->output_stream->writeBuf, fft_size, -10, 20, 10);
|
2023-07-28 13:55:21 +02:00
|
|
|
fft_plot->frequency = frequency_mhz * 1e6;
|
2023-02-11 01:35:26 +01:00
|
|
|
waterfall_plot = std::make_shared<widgets::WaterfallPlot>(fft_sizes_lut[0], 500);
|
2023-02-11 01:07:39 +01:00
|
|
|
|
|
|
|
|
fft->on_fft = [this](float *v)
|
|
|
|
|
{ waterfall_plot->push_fft(v); };
|
2022-10-11 21:39:41 +02:00
|
|
|
|
2023-07-08 11:51:08 +02:00
|
|
|
// Load config
|
2022-10-11 21:39:41 +02:00
|
|
|
if (config::main_cfg["user"].contains("recorder_state"))
|
|
|
|
|
deserialize_config(config::main_cfg["user"]["recorder_state"]);
|
2023-07-08 11:51:08 +02:00
|
|
|
|
|
|
|
|
fft_plot->set_size(fft_size);
|
|
|
|
|
waterfall_plot->set_size(fft_size);
|
|
|
|
|
waterfall_plot->set_rate(fft_rate, waterfall_rate);
|
2022-05-02 11:58:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RecorderApplication::~RecorderApplication()
|
|
|
|
|
{
|
2022-12-17 16:55:11 +01:00
|
|
|
stop_processing();
|
2022-12-17 15:55:06 +01:00
|
|
|
if (is_started)
|
2023-01-23 18:02:26 +01:00
|
|
|
stop();
|
2022-05-07 00:24:30 +02:00
|
|
|
source_ptr->close();
|
2022-07-30 20:19:55 +02:00
|
|
|
splitter->input_stream = std::make_shared<dsp::stream<complex_t>>();
|
2022-05-07 00:24:30 +02:00
|
|
|
splitter->stop();
|
|
|
|
|
fft->stop();
|
|
|
|
|
file_sink->stop();
|
2023-07-22 21:23:38 +02:00
|
|
|
|
|
|
|
|
if (tracking_widget != nullptr)
|
|
|
|
|
delete tracking_widget;
|
2023-08-14 12:05:21 +00:00
|
|
|
if (constellation_debug != nullptr)
|
|
|
|
|
delete constellation_debug;
|
2022-05-02 11:58:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RecorderApplication::drawUI()
|
|
|
|
|
{
|
|
|
|
|
ImVec2 recorder_size = ImGui::GetContentRegionAvail();
|
2022-05-07 18:16:24 +02:00
|
|
|
// recorder_size.y -= ImGui::GetCursorPosY();
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::BeginTable("##recorder_table", 2, ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_Resizable))
|
2022-05-02 18:59:03 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::TableSetupColumn("##panel_v", ImGuiTableColumnFlags_WidthFixed, recorder_size.x * panel_ratio);
|
|
|
|
|
ImGui::TableSetupColumn("##view", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
|
|
2023-02-09 17:51:07 +01:00
|
|
|
float wf_size = recorder_size.y - ((is_processing && !processing_modules_floating_windows) ? 250 * ui_scale : 0); // + 13 * ui_scale;
|
2023-08-09 22:41:09 +02:00
|
|
|
ImGui::BeginChild("RecorderChildPanel", {float(recorder_size.x * panel_ratio), wf_size}, false, ImGuiWindowFlags_NoBringToFrontOnFocus);
|
2022-05-02 18:59:03 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::CollapsingHeader("Device", ImGuiTreeNodeFlags_DefaultOpen))
|
2022-05-02 18:59:03 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::Spacing();
|
|
|
|
|
if (is_started)
|
|
|
|
|
style::beginDisabled();
|
|
|
|
|
if (ImGui::Combo("##Source", &sdr_select_id, sdr_select_string.c_str()))
|
2022-07-28 01:05:30 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
// Try to open a device, if it doesn't work, we re-open a device we can
|
|
|
|
|
try
|
2022-07-28 01:05:30 +02:00
|
|
|
{
|
2023-09-11 16:48:28 +02:00
|
|
|
source_ptr = getSourceFromDescriptor(sources[sdr_select_id]);
|
2023-01-22 22:23:43 +01:00
|
|
|
source_ptr->open();
|
|
|
|
|
}
|
|
|
|
|
catch (std::runtime_error &e)
|
|
|
|
|
{
|
2023-09-11 16:48:28 +02:00
|
|
|
logger->error("Could not open device! %s", e.what());
|
2023-01-22 22:23:43 +01:00
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)sources.size(); i++)
|
2022-07-28 01:05:30 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
source_ptr = dsp::getSourceFromDescriptor(sources[i]);
|
|
|
|
|
source_ptr->open();
|
|
|
|
|
sdr_select_id = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
catch (std::runtime_error &e)
|
|
|
|
|
{
|
|
|
|
|
logger->error(e.what());
|
|
|
|
|
}
|
2022-07-28 01:05:30 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-29 18:00:19 +02:00
|
|
|
set_frequency(frequency_mhz);
|
2023-01-22 22:23:43 +01:00
|
|
|
try_load_sdr_settings();
|
2022-05-04 12:41:27 +02:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button(u8" \uead2 "))
|
|
|
|
|
{
|
|
|
|
|
sources = dsp::getAllAvailableSources();
|
2022-05-12 23:30:42 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
sdr_select_string.clear();
|
|
|
|
|
for (dsp::SourceDescriptor src : sources)
|
|
|
|
|
{
|
|
|
|
|
logger->debug("Device " + src.name);
|
|
|
|
|
sdr_select_string += src.name + '\0';
|
|
|
|
|
}
|
2022-05-12 23:30:42 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
while (sdr_select_id >= (int)sources.size())
|
|
|
|
|
sdr_select_id--;
|
|
|
|
|
|
|
|
|
|
source_ptr = getSourceFromDescriptor(sources[sdr_select_id]);
|
|
|
|
|
source_ptr->open();
|
2023-07-29 18:00:19 +02:00
|
|
|
set_frequency(frequency_mhz);
|
2023-01-22 22:23:43 +01:00
|
|
|
try_load_sdr_settings();
|
2022-09-07 19:52:02 +02:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
/*
|
|
|
|
|
if (ImGui::IsItemHovered())
|
|
|
|
|
{
|
|
|
|
|
ImGui::BeginTooltip();
|
|
|
|
|
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
|
|
|
|
ImGui::TextUnformatted("Refresh source list");
|
|
|
|
|
ImGui::PopTextWrapPos();
|
|
|
|
|
ImGui::EndTooltip();
|
|
|
|
|
}
|
|
|
|
|
*/
|
2022-05-02 18:59:03 +02:00
|
|
|
|
2023-01-23 17:58:03 +01:00
|
|
|
ImGui::InputInt("Decimation##recorderdecimation", ¤t_decimation);
|
|
|
|
|
if (current_decimation < 1)
|
|
|
|
|
current_decimation = 1;
|
2022-09-07 19:52:02 +02:00
|
|
|
|
2023-07-29 19:50:28 +02:00
|
|
|
bool pushed_color_xconv = xconverter_frequency != 0;
|
|
|
|
|
if (pushed_color_xconv)
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 255, 0, 255));
|
|
|
|
|
if (ImGui::InputDouble("MHz (LO)##downupconverter", &xconverter_frequency))
|
|
|
|
|
set_frequency(frequency_mhz);
|
|
|
|
|
if (pushed_color_xconv)
|
|
|
|
|
ImGui::PopStyleColor();
|
|
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (is_started)
|
|
|
|
|
style::endDisabled();
|
2022-05-02 18:59:03 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::Spacing();
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
ImGui::Spacing();
|
2022-05-02 18:59:03 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::InputDouble("MHz", &frequency_mhz))
|
2023-07-29 18:00:19 +02:00
|
|
|
set_frequency(frequency_mhz);
|
2022-12-05 12:22:45 +01:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
source_ptr->drawControlUI();
|
2022-12-05 12:22:45 +01:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (!is_started)
|
2022-05-02 18:59:03 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::Button("Start"))
|
2023-01-23 17:58:03 +01:00
|
|
|
start();
|
2022-05-02 18:59:03 +02:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
else
|
2022-05-02 18:59:03 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::Button("Stop"))
|
2023-01-23 17:58:03 +01:00
|
|
|
stop();
|
2022-05-02 18:59:03 +02:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::TextColored(ImColor(255, 0, 0), "%s", sdr_error.c_str());
|
2022-05-02 18:59:03 +02:00
|
|
|
}
|
|
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::CollapsingHeader("FFT", ImGuiTreeNodeFlags_DefaultOpen))
|
2022-11-29 00:01:26 +01:00
|
|
|
{
|
2023-07-08 11:51:08 +02:00
|
|
|
if (ImGui::Combo("FFT Size", &selected_fft_size, "131072\0"
|
|
|
|
|
"65536\0"
|
|
|
|
|
"16384\0"
|
|
|
|
|
"8192\0"
|
|
|
|
|
"4096\0"
|
|
|
|
|
"2048\0"
|
|
|
|
|
"1024\0"))
|
2022-05-02 18:59:03 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
fft_size = fft_sizes_lut[selected_fft_size];
|
2022-11-29 00:01:26 +01:00
|
|
|
|
2023-01-23 17:58:03 +01:00
|
|
|
fft->set_fft_settings(fft_size, get_samplerate(), fft_rate);
|
2023-01-22 22:23:43 +01:00
|
|
|
fft_plot->set_size(fft_size);
|
|
|
|
|
waterfall_plot->set_size(fft_size);
|
2022-11-29 00:01:26 +01:00
|
|
|
|
2023-05-08 23:08:34 +02:00
|
|
|
logger->info("Set FFT size to %d", fft_size);
|
2022-05-02 18:59:03 +02:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::InputInt("FFT Rate", &fft_rate))
|
|
|
|
|
{
|
|
|
|
|
fft_size = fft_sizes_lut[selected_fft_size];
|
2022-12-05 13:10:29 +01:00
|
|
|
|
2023-01-23 17:58:03 +01:00
|
|
|
fft->set_fft_settings(fft_size, get_samplerate(), fft_rate);
|
2023-02-11 01:07:39 +01:00
|
|
|
waterfall_plot->set_rate(fft_rate, waterfall_rate);
|
2022-12-05 13:10:29 +01:00
|
|
|
|
2023-05-08 23:08:34 +02:00
|
|
|
logger->info("Set FFT rate to %d", fft_rate);
|
2023-01-22 22:23:43 +01:00
|
|
|
}
|
2023-02-11 01:07:39 +01:00
|
|
|
if (ImGui::InputInt("Waterfall Rate", &waterfall_rate))
|
|
|
|
|
{
|
|
|
|
|
waterfall_plot->set_rate(fft_rate, waterfall_rate);
|
2023-05-08 23:08:34 +02:00
|
|
|
logger->info("Set Waterfall rate to %d", fft_rate);
|
2023-02-11 01:07:39 +01:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::SliderFloat("FFT Max", &fft_plot->scale_max, -150, 150);
|
|
|
|
|
ImGui::SliderFloat("FFT Min", &fft_plot->scale_min, -150, 150);
|
|
|
|
|
ImGui::SliderFloat("Avg Rate", &fft->avg_rate, 0.01, 0.99);
|
|
|
|
|
if (ImGui::Combo("Palette", &selected_waterfall_palette, waterfall_palettes_str.c_str()))
|
|
|
|
|
waterfall_plot->set_palette(waterfall_palettes[selected_waterfall_palette]);
|
|
|
|
|
ImGui::Checkbox("Show Waterfall", &show_waterfall);
|
2023-07-28 20:38:23 +02:00
|
|
|
ImGui::Checkbox("Frequency Scale", &fft_plot->enable_freq_scale);
|
2022-12-05 13:10:29 +01:00
|
|
|
}
|
2022-05-02 18:59:03 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (fft_plot->scale_max < fft_plot->scale_min)
|
|
|
|
|
{
|
|
|
|
|
fft_plot->scale_min = waterfall_plot->scale_min;
|
|
|
|
|
fft_plot->scale_max = waterfall_plot->scale_max;
|
2022-11-29 00:01:26 +01:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
else if (fft_plot->scale_min > fft_plot->scale_max)
|
2022-12-05 13:10:29 +01:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
fft_plot->scale_min = waterfall_plot->scale_min;
|
|
|
|
|
fft_plot->scale_max = waterfall_plot->scale_max;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
waterfall_plot->scale_min = fft_plot->scale_min;
|
|
|
|
|
waterfall_plot->scale_max = fft_plot->scale_max;
|
2022-12-05 13:10:29 +01:00
|
|
|
}
|
2022-05-02 19:49:40 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::CollapsingHeader("Processing"))
|
2022-06-10 22:21:22 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
// Settings & Selection menu
|
|
|
|
|
if (is_processing)
|
|
|
|
|
style::beginDisabled();
|
|
|
|
|
pipeline_selector.renderSelectionBox(ImGui::GetContentRegionAvail().x);
|
|
|
|
|
if (!automated_live_output_dir)
|
|
|
|
|
pipeline_selector.drawMainparamsLive();
|
|
|
|
|
pipeline_selector.renderParamTable();
|
|
|
|
|
if (is_processing)
|
|
|
|
|
style::endDisabled();
|
|
|
|
|
|
|
|
|
|
// Preset Menu
|
|
|
|
|
Pipeline selected_pipeline = pipelines[pipeline_selector.pipeline_id];
|
|
|
|
|
if (selected_pipeline.preset.frequencies.size() > 0)
|
2022-06-10 22:21:22 +02:00
|
|
|
{
|
2023-09-14 22:10:39 -04:00
|
|
|
if (ImGui::BeginCombo("Freq###presetscombo", selected_pipeline.preset.frequencies[pipeline_preset_id].second == frequency_mhz * 1e6 ?
|
|
|
|
|
selected_pipeline.preset.frequencies[pipeline_preset_id].first.c_str() : ""))
|
2022-06-10 22:21:22 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
for (int n = 0; n < (int)selected_pipeline.preset.frequencies.size(); n++)
|
2022-06-12 16:17:30 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
const bool is_selected = (pipeline_preset_id == n);
|
|
|
|
|
if (ImGui::Selectable(selected_pipeline.preset.frequencies[n].first.c_str(), is_selected))
|
2022-06-12 16:17:30 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
pipeline_preset_id = n;
|
|
|
|
|
|
|
|
|
|
if (selected_pipeline.preset.frequencies[pipeline_preset_id].second != 0)
|
|
|
|
|
{
|
|
|
|
|
frequency_mhz = double(selected_pipeline.preset.frequencies[pipeline_preset_id].second) / 1e6;
|
2023-07-29 18:00:19 +02:00
|
|
|
set_frequency(frequency_mhz);
|
2023-01-22 22:23:43 +01:00
|
|
|
}
|
2022-06-12 16:17:30 +02:00
|
|
|
}
|
2022-06-10 22:21:22 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (is_selected)
|
|
|
|
|
ImGui::SetItemDefaultFocus();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndCombo();
|
2022-06-10 22:21:22 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (!is_started)
|
|
|
|
|
style::beginDisabled();
|
2022-06-10 22:21:22 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (!is_processing)
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::Button("Start###startprocessing"))
|
|
|
|
|
start_processing();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::Button("Stop##stopprocessing"))
|
|
|
|
|
stop_processing();
|
|
|
|
|
}
|
2022-05-03 17:00:43 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::SameLine();
|
|
|
|
|
ImGui::TextColored(ImColor(255, 0, 0), "%s", error.c_str());
|
2022-05-06 00:26:21 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (!is_started)
|
|
|
|
|
style::endDisabled();
|
|
|
|
|
}
|
2022-05-02 22:05:54 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::CollapsingHeader("Recording"))
|
2022-05-02 22:05:54 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
if (is_recording)
|
|
|
|
|
style::beginDisabled();
|
|
|
|
|
if (ImGui::Combo("Format", &select_sample_format, "f32\0"
|
|
|
|
|
"s16\0"
|
|
|
|
|
"s8\0"
|
|
|
|
|
"wav16\0"
|
2022-05-04 00:37:34 +02:00
|
|
|
#ifdef BUILD_ZIQ
|
2023-01-22 22:23:43 +01:00
|
|
|
"ziq s8\0"
|
|
|
|
|
"ziq s16\0"
|
|
|
|
|
"ziq f32\0"
|
2023-02-15 19:25:26 +01:00
|
|
|
#endif
|
|
|
|
|
#ifdef BUILD_ZIQ2
|
2023-02-16 16:44:44 +01:00
|
|
|
"ziq2 s8 (WIP)\0"
|
|
|
|
|
"ziq2 s16 (WIP)\0"
|
2022-05-04 00:37:34 +02:00
|
|
|
#endif
|
2023-01-22 22:23:43 +01:00
|
|
|
))
|
2023-01-17 11:43:13 +01:00
|
|
|
{
|
2023-02-16 15:18:54 +01:00
|
|
|
int type_lut[] = {
|
|
|
|
|
0,
|
|
|
|
|
1,
|
|
|
|
|
2,
|
|
|
|
|
3,
|
|
|
|
|
#ifdef BUILD_ZIQ
|
|
|
|
|
4,
|
|
|
|
|
5,
|
|
|
|
|
6,
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef BUILD_ZIQ2
|
|
|
|
|
7,
|
|
|
|
|
8,
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int f = type_lut[select_sample_format];
|
|
|
|
|
|
|
|
|
|
if (f == 0)
|
2023-01-22 22:23:43 +01:00
|
|
|
file_sink->set_output_sample_type(dsp::CF_32);
|
2023-02-16 15:18:54 +01:00
|
|
|
else if (f == 1)
|
2023-01-22 22:23:43 +01:00
|
|
|
file_sink->set_output_sample_type(dsp::IS_16);
|
2023-02-16 15:18:54 +01:00
|
|
|
else if (f == 2)
|
2023-01-22 22:23:43 +01:00
|
|
|
file_sink->set_output_sample_type(dsp::IS_8);
|
2023-02-16 15:18:54 +01:00
|
|
|
else if (f == 3)
|
2023-01-22 22:23:43 +01:00
|
|
|
file_sink->set_output_sample_type(dsp::WAV_16);
|
|
|
|
|
#ifdef BUILD_ZIQ
|
2023-02-16 15:18:54 +01:00
|
|
|
else if (f == 4)
|
2023-01-22 22:23:43 +01:00
|
|
|
{
|
|
|
|
|
file_sink->set_output_sample_type(dsp::ZIQ);
|
|
|
|
|
ziq_bit_depth = 8;
|
|
|
|
|
}
|
2023-02-16 15:18:54 +01:00
|
|
|
else if (f == 5)
|
2023-01-22 22:23:43 +01:00
|
|
|
{
|
|
|
|
|
file_sink->set_output_sample_type(dsp::ZIQ);
|
|
|
|
|
ziq_bit_depth = 16;
|
|
|
|
|
}
|
2023-02-16 15:18:54 +01:00
|
|
|
else if (f == 6)
|
2023-01-22 22:23:43 +01:00
|
|
|
{
|
|
|
|
|
file_sink->set_output_sample_type(dsp::ZIQ);
|
|
|
|
|
ziq_bit_depth = 32;
|
|
|
|
|
}
|
2023-02-15 18:47:53 +01:00
|
|
|
#endif
|
|
|
|
|
#ifdef BUILD_ZIQ2
|
2023-02-16 15:18:54 +01:00
|
|
|
else if (f == 7)
|
2023-02-15 18:47:53 +01:00
|
|
|
{
|
|
|
|
|
file_sink->set_output_sample_type(dsp::ZIQ2);
|
|
|
|
|
ziq_bit_depth = 8;
|
|
|
|
|
}
|
2023-02-16 15:18:54 +01:00
|
|
|
else if (f == 8)
|
|
|
|
|
{
|
|
|
|
|
file_sink->set_output_sample_type(dsp::ZIQ2);
|
|
|
|
|
ziq_bit_depth = 16;
|
|
|
|
|
}
|
2022-05-04 00:37:34 +02:00
|
|
|
#endif
|
2023-01-17 11:43:13 +01:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
if (is_recording)
|
|
|
|
|
style::endDisabled();
|
2022-05-02 22:05:54 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (file_sink->get_written() < 1e9)
|
|
|
|
|
ImGui::Text("Size : %.2f MB", file_sink->get_written() / 1e6);
|
|
|
|
|
else
|
|
|
|
|
ImGui::Text("Size : %.2f GB", file_sink->get_written() / 1e9);
|
2022-05-04 00:37:34 +02:00
|
|
|
|
|
|
|
|
#ifdef BUILD_ZIQ
|
2023-01-22 22:23:43 +01:00
|
|
|
if (select_sample_format == 4 || select_sample_format == 5 || select_sample_format == 6)
|
|
|
|
|
{
|
|
|
|
|
if (file_sink->get_written_raw() < 1e9)
|
|
|
|
|
ImGui::Text("Size (raw) : %.2f MB", file_sink->get_written_raw() / 1e6);
|
|
|
|
|
else
|
|
|
|
|
ImGui::Text("Size (raw) : %.2f GB", file_sink->get_written_raw() / 1e9);
|
|
|
|
|
}
|
2022-05-04 00:37:34 +02:00
|
|
|
#endif
|
|
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::Text("File : %s", recorder_filename.c_str());
|
2022-05-02 22:05:54 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::Spacing();
|
2022-05-02 22:05:54 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (!is_recording)
|
|
|
|
|
ImGui::TextColored(ImColor(255, 0, 0), "IDLE");
|
|
|
|
|
else
|
|
|
|
|
ImGui::TextColored(ImColor(0, 255, 0), "RECORDING");
|
2022-05-02 22:05:54 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::Spacing();
|
2022-05-02 22:05:54 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
if (!is_recording)
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::Button("Start###startrecording"))
|
|
|
|
|
start_recording();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::Button("Stop##stoprecording"))
|
|
|
|
|
stop_recording();
|
|
|
|
|
}
|
2022-05-02 22:05:54 +02:00
|
|
|
}
|
2023-07-17 23:11:13 +02:00
|
|
|
|
|
|
|
|
if (ImGui::CollapsingHeader("Tracking"))
|
|
|
|
|
{
|
2023-07-22 21:23:38 +02:00
|
|
|
if (tracking_widget == nullptr)
|
2023-07-26 20:08:25 +02:00
|
|
|
{
|
2023-07-22 21:23:38 +02:00
|
|
|
tracking_widget = new TrackingWidget();
|
2023-07-26 20:08:25 +02:00
|
|
|
|
2023-07-28 20:38:23 +02:00
|
|
|
tracking_widget->aos_callback = [this](tracking::SatellitePass, tracking::TrackedObject obj)
|
2023-07-26 20:08:25 +02:00
|
|
|
{
|
|
|
|
|
stop_recording();
|
|
|
|
|
stop_processing();
|
|
|
|
|
|
2023-07-26 21:49:23 +02:00
|
|
|
frequency_mhz = obj.frequency;
|
2023-07-29 18:00:19 +02:00
|
|
|
set_frequency(frequency_mhz);
|
2023-07-26 20:08:25 +02:00
|
|
|
|
|
|
|
|
if (obj.live)
|
|
|
|
|
{
|
2023-07-29 22:13:49 +02:00
|
|
|
pipeline_selector.select_pipeline(pipelines[obj.pipeline_selector->pipeline_id].name);
|
2023-07-29 22:20:03 +02:00
|
|
|
pipeline_selector.setParameters(obj.pipeline_selector->getParameters());
|
2023-07-26 20:08:25 +02:00
|
|
|
start_processing();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (obj.record)
|
|
|
|
|
{
|
|
|
|
|
start_recording();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-07-29 22:13:49 +02:00
|
|
|
tracking_widget->los_callback = [this](tracking::SatellitePass, tracking::TrackedObject)
|
2023-07-26 20:08:25 +02:00
|
|
|
{
|
|
|
|
|
stop_recording();
|
|
|
|
|
stop_processing();
|
|
|
|
|
};
|
|
|
|
|
}
|
2023-07-22 21:23:38 +02:00
|
|
|
tracking_widget->render();
|
2023-07-17 23:11:13 +02:00
|
|
|
}
|
2023-08-14 12:05:21 +00:00
|
|
|
|
|
|
|
|
if (ImGui::CollapsingHeader("Debug"))
|
|
|
|
|
{
|
|
|
|
|
if (constellation_debug == nullptr)
|
|
|
|
|
constellation_debug = new widgets::ConstellationViewer();
|
2023-09-11 16:48:28 +02:00
|
|
|
if (is_started)
|
2023-08-18 13:52:00 -04:00
|
|
|
constellation_debug->pushComplex(source_ptr->output_stream->readBuf, 256);
|
2023-08-14 12:05:21 +00:00
|
|
|
constellation_debug->draw();
|
|
|
|
|
}
|
2022-05-02 22:05:54 +02:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::EndChild();
|
|
|
|
|
ImGui::EndGroup();
|
2022-05-02 18:59:03 +02:00
|
|
|
|
2023-01-22 23:40:56 +01:00
|
|
|
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left) || last_width != recorder_size.x)
|
|
|
|
|
panel_ratio = ImGui::GetColumnWidth() / recorder_size[0];
|
|
|
|
|
last_width = recorder_size.x;
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::TableNextColumn();
|
2022-05-02 18:59:03 +02:00
|
|
|
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
|
ImGui::BeginChild("RecorderFFT", {float(recorder_size.x * (1.0 - panel_ratio)), wf_size}, false, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
2022-05-08 13:42:52 +02:00
|
|
|
{
|
2023-01-22 22:23:43 +01:00
|
|
|
float fft_height = wf_size * (show_waterfall ? waterfall_ratio : 1.0);
|
2023-01-23 19:44:44 +01:00
|
|
|
float wf_height = wf_size * (1 - waterfall_ratio) + 15 * ui_scale;
|
2023-01-22 22:23:43 +01:00
|
|
|
bool t = true;
|
2023-01-23 13:45:04 +01:00
|
|
|
#ifdef __ANDROID__
|
|
|
|
|
int offset = 8;
|
|
|
|
|
#else
|
|
|
|
|
int offset = 30;
|
|
|
|
|
#endif
|
2023-01-23 19:34:41 +01:00
|
|
|
ImGui::SetNextWindowSizeConstraints(ImVec2((recorder_size.x * (1.0 - panel_ratio) + offset * ui_scale), 50), ImVec2((recorder_size.x * (1.0 - panel_ratio) + offset * ui_scale), wf_size));
|
|
|
|
|
ImGui::SetNextWindowSize(ImVec2((recorder_size.x * (1.0 - panel_ratio) + offset * ui_scale), show_waterfall ? waterfall_ratio * wf_size : wf_size));
|
2023-01-23 01:23:05 +01:00
|
|
|
ImGui::SetNextWindowPos(ImVec2(recorder_size.x * panel_ratio, 25 * ui_scale));
|
2023-01-22 22:23:43 +01:00
|
|
|
if (ImGui::Begin("#fft", &t, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse))
|
2022-05-08 13:42:52 +02:00
|
|
|
{
|
2023-01-23 01:23:05 +01:00
|
|
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 8 * ui_scale);
|
2023-01-23 13:45:04 +01:00
|
|
|
fft_plot->draw({float(recorder_size.x * (1.0 - panel_ratio) - 8 * ui_scale), fft_height});
|
2023-01-22 23:40:56 +01:00
|
|
|
if (show_waterfall && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
2023-01-23 19:34:41 +01:00
|
|
|
waterfall_ratio = ImGui::GetWindowHeight() / wf_size;
|
2023-02-09 17:51:07 +01:00
|
|
|
if (ImGui::IsWindowHovered())
|
|
|
|
|
{
|
2023-01-23 17:39:04 +01:00
|
|
|
ImVec2 mouse_pos = ImGui::GetMousePos();
|
2023-01-23 18:02:26 +01:00
|
|
|
float ratio = (mouse_pos.x - recorder_size.x * panel_ratio - 16 * ui_scale) / (recorder_size.x * (1.0 - panel_ratio) - 8 * ui_scale) - 0.5;
|
2023-09-07 21:49:55 -04:00
|
|
|
ImGui::SetTooltip("%s", ((ratio >= 0 ? "" : "- ") + format_notated(abs(ratio) * get_samplerate(), "Hz\n") +
|
2023-09-11 16:48:28 +02:00
|
|
|
format_notated(source_ptr->get_frequency() + ratio * get_samplerate(), "Hz"))
|
|
|
|
|
.c_str());
|
2023-01-23 17:39:04 +01:00
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::EndChild();
|
2022-05-08 13:42:52 +02:00
|
|
|
}
|
2023-01-23 13:45:04 +01:00
|
|
|
if (show_waterfall)
|
2022-05-08 13:42:52 +02:00
|
|
|
{
|
2023-01-22 23:40:56 +01:00
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 15 * ui_scale);
|
2023-01-23 13:45:04 +01:00
|
|
|
waterfall_plot->draw({float(recorder_size.x * (1.0 - panel_ratio) - 8 * ui_scale), wf_height}, is_started);
|
2022-05-08 13:42:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-01-22 22:23:43 +01:00
|
|
|
ImGui::EndChild();
|
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
ImGui::EndTable();
|
2022-05-08 14:47:56 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-03 17:00:43 +02:00
|
|
|
if (is_processing)
|
2022-05-05 23:55:05 +02:00
|
|
|
{
|
2022-07-30 20:29:37 +02:00
|
|
|
if (processing_modules_floating_windows)
|
2022-05-05 23:55:05 +02:00
|
|
|
{
|
2022-07-30 20:29:37 +02:00
|
|
|
for (std::shared_ptr<ProcessingModule> &module : live_pipeline->modules)
|
|
|
|
|
module->drawUI(true);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
float y_pos = ImGui::GetCursorPosY() + 35 * ui_scale;
|
|
|
|
|
float live_width = recorder_size.x + 16 * ui_scale;
|
|
|
|
|
float live_height = 250 * ui_scale;
|
|
|
|
|
float winwidth = live_pipeline->modules.size() > 0 ? live_width / live_pipeline->modules.size() : live_width;
|
|
|
|
|
float currentPos = 0;
|
2023-07-31 23:01:52 -04:00
|
|
|
ImGui::PushStyleColor(11, ImGui::GetStyleColorVec4(10));
|
2022-07-30 20:29:37 +02:00
|
|
|
for (std::shared_ptr<ProcessingModule> &module : live_pipeline->modules)
|
|
|
|
|
{
|
|
|
|
|
ImGui::SetNextWindowPos({currentPos, y_pos});
|
|
|
|
|
ImGui::SetNextWindowSize({(float)winwidth, (float)live_height});
|
|
|
|
|
module->drawUI(false);
|
|
|
|
|
currentPos += winwidth;
|
|
|
|
|
|
|
|
|
|
// if (ImGui::GetCurrentContext()->last_window != NULL)
|
|
|
|
|
// currentPos += ImGui::GetCurrentContext()->last_window->Size.x;
|
|
|
|
|
// logger->info(ImGui::GetCurrentContext()->last_window->Name);
|
|
|
|
|
}
|
2023-07-31 23:01:52 -04:00
|
|
|
ImGui::PopStyleColor();
|
2022-05-05 23:55:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-06-06 11:20:21 +02:00
|
|
|
|
|
|
|
|
// Keyboard shortcuts
|
|
|
|
|
{
|
|
|
|
|
// FFT
|
|
|
|
|
if (ImGui::IsKeyDown(ImGuiKey_ModShift) && ImGui::IsKeyDown(ImGuiKey_X))
|
|
|
|
|
{
|
|
|
|
|
if (ImGui::IsKeyDown(ImGuiKey_DownArrow))
|
|
|
|
|
fft_plot->scale_max -= 0.5;
|
|
|
|
|
else if (ImGui::IsKeyDown(ImGuiKey_UpArrow))
|
|
|
|
|
fft_plot->scale_max += 0.5;
|
|
|
|
|
else if (ImGui::IsKeyDown(ImGuiKey_LeftArrow))
|
|
|
|
|
fft_plot->scale_min -= 0.5;
|
|
|
|
|
else if (ImGui::IsKeyDown(ImGuiKey_RightArrow))
|
|
|
|
|
fft_plot->scale_min += 0.5;
|
|
|
|
|
else if (ImGui::IsKeyDown(ImGuiKey_PageUp))
|
|
|
|
|
fft->avg_rate += 0.001;
|
|
|
|
|
else if (ImGui::IsKeyDown(ImGuiKey_PageDown))
|
|
|
|
|
fft->avg_rate -= 0.001;
|
|
|
|
|
|
|
|
|
|
if (fft->avg_rate > 0.99)
|
|
|
|
|
fft->avg_rate = 0.99;
|
|
|
|
|
else if (fft->avg_rate < 0.01)
|
|
|
|
|
fft->avg_rate = 0.01;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-02 11:58:05 +02:00
|
|
|
}
|
2022-05-03 21:08:46 +02:00
|
|
|
};
|