removed scrolling due to bug + Fixed file source

This commit is contained in:
Ryzerth 2021-02-07 23:47:17 +01:00
parent 49ec3d68d2
commit 9df90e5e75
37 changed files with 11910 additions and 3792 deletions

View File

@ -16,6 +16,7 @@ add_subdirectory("core")
# Base modules
add_subdirectory("radio")
add_subdirectory("recorder")
add_subdirectory("file_source")
# Source modules
if (OPT_BUILD_RTL_TCP_SOURCE)

View File

@ -8,7 +8,7 @@
#include <config.h>
#include <options.h>
#include <libairspy/airspy.h>
#include <gui/widgets/scroll_behavior.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -406,7 +406,7 @@ private:
ImGui::Text("Gain");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderInt(CONCAT("##_airspy_sens_gain_", _this->name), &_this->sensitiveGain, 0, 21) || ImGui::AllowScrollwheelStSz<int>(_this->sensitiveGain, 1, 0, 21)) {
if (ImGui::SliderInt(CONCAT("##_airspy_sens_gain_", _this->name), &_this->sensitiveGain, 0, 21)) {
if (_this->running) {
airspy_set_sensitivity_gain(_this->openDev, _this->sensitiveGain);
}
@ -421,7 +421,7 @@ private:
ImGui::Text("Gain");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderInt(CONCAT("##_airspy_lin_gain_", _this->name), &_this->linearGain, 0, 21) || ImGui::AllowScrollwheelStSz<int>(_this->linearGain, 1, 0, 21)) {
if (ImGui::SliderInt(CONCAT("##_airspy_lin_gain_", _this->name), &_this->linearGain, 0, 21)) {
if (_this->running) {
airspy_set_linearity_gain(_this->openDev, _this->linearGain);
}
@ -441,7 +441,7 @@ private:
ImGui::SameLine();
ImGui::SetCursorPosX(pos);
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderInt(CONCAT("##_airspy_lna_gain_", _this->name), &_this->lnaGain, 0, 15) || ImGui::AllowScrollwheelStSz<int>(_this->lnaGain, 1, 0, 15)) {
if (ImGui::SliderInt(CONCAT("##_airspy_lna_gain_", _this->name), &_this->lnaGain, 0, 15)) {
if (_this->running) {
airspy_set_lna_gain(_this->openDev, _this->lnaGain);
}
@ -458,7 +458,7 @@ private:
ImGui::SameLine();
ImGui::SetCursorPosX(pos);
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderInt(CONCAT("##_airspy_mix_gain_", _this->name), &_this->mixerGain, 0, 15) || ImGui::AllowScrollwheelStSz<int>(_this->mixerGain, 1, 0, 15)) {
if (ImGui::SliderInt(CONCAT("##_airspy_mix_gain_", _this->name), &_this->mixerGain, 0, 15)) {
if (_this->running) {
airspy_set_mixer_gain(_this->openDev, _this->mixerGain);
}
@ -474,7 +474,7 @@ private:
ImGui::SameLine();
ImGui::SetCursorPosX(pos);
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderInt(CONCAT("##_airspy_vga_gain_", _this->name), &_this->vgaGain, 0, 15) || ImGui::AllowScrollwheelStSz<int>(_this->vgaGain, 1, 0, 15)) {
if (ImGui::SliderInt(CONCAT("##_airspy_vga_gain_", _this->name), &_this->vgaGain, 0, 15)) {
if (_this->running) {
airspy_set_vga_gain(_this->openDev, _this->vgaGain);
}

View File

@ -26,7 +26,7 @@ namespace LoadingScreen {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20.0f, 20.0f));
ImGui::OpenPopup("Credits");
ImGui::PushStyleColor(ImGuiCol_ModalWindowDarkening, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ModalWindowDimBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
ImGui::BeginPopupModal("Credits", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground);
ImGui::PushFont(style::hugeFont);

View File

@ -32,10 +32,12 @@
#include <gui/dialogs/loading_screen.h>
#include <options.h>
#include <gui/colormaps.h>
#include <gui/widgets/scroll_behavior.h>
#include <gui/widgets/file_select.h>
FileSelect fileSelect("%ROOT/recordings", "Alllll\0*.*\0Text\0*.TXT\0");
#include <gui/widgets/folder_select.h>
FileSelect fileSelect("D:/Downloads/unicast.wav");
FolderSelect foldSelect("%ROOT/recordings");
// const int FFTSizes[] = {
// 65536,
@ -114,11 +116,21 @@ bool centerTuning = false;
dsp::stream<dsp::complex_t> dummyStream;
bool demoWindow = false;
COMDLG_FILTERSPEC rgSpec[] ={
{ L"Wav File", L"*.wav" },
{ L"All", L"*.*" },
};
void windowInit() {
LoadingScreen::show("Initializing UI");
gui::waterfall.init();
gui::waterfall.setRawFFTSize(fftSize);
// TEMP TEST
fileSelect.setWindowsFilter(rgSpec, 2);
// ==========
tempFFT = new float[fftSize];
FFTdata = new float[fftSize];
@ -558,6 +570,9 @@ void drawWindow() {
ImGui::Checkbox("Show demo window", &demoWindow);
ImGui::Checkbox("Experimental zoom", &experimentalZoom);
fileSelect.render("##_testfile");
foldSelect.render("##_testfold");
ImGui::Text("ImGui version: %s", ImGui::GetVersion());
ImGui::Spacing();
}
@ -589,8 +604,7 @@ void drawWindow() {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Zoom").x / 2.0));
ImGui::Text("Zoom");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
if (ImGui::VSliderFloat("##_7_", ImVec2(20.0, 150.0), &bw, gui::waterfall.getBandwidth(), 1000.0, "", (experimentalZoom ? 2.0 : 1.0)) ||
ImGui::AllowScrollwheel<float>(bw, 20, gui::waterfall.getBandwidth(), 1000.0)) {
if (ImGui::VSliderFloat("##_7_", ImVec2(20.0, 150.0), &bw, gui::waterfall.getBandwidth(), 1000.0, "", (experimentalZoom ? 2.0 : 1.0))) {
gui::waterfall.setViewBandwidth(bw);
if (vfo != NULL) {
gui::waterfall.setViewOffset(vfo->centerOffset); // center vfo on screen
@ -602,7 +616,7 @@ void drawWindow() {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Max").x / 2.0));
ImGui::Text("Max");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
if (ImGui::VSliderFloat("##_8_", ImVec2(20.0, 150.0), &fftMax, 0.0, -100.0, "") || ImGui::AllowScrollwheel<float>(fftMax, 20, -100, 0)) {
if (ImGui::VSliderFloat("##_8_", ImVec2(20.0, 150.0), &fftMax, 0.0, -100.0, "")) {
fftMax = std::max<float>(fftMax, fftMin + 10);
core::configManager.aquire();
core::configManager.conf["max"] = fftMax;
@ -614,7 +628,7 @@ void drawWindow() {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Min").x / 2.0));
ImGui::Text("Min");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
if (ImGui::VSliderFloat("##_9_", ImVec2(20.0, 150.0), &fftMin, 0.0, -100.0, "") || ImGui::AllowScrollwheel<float>(fftMin, 20, -100, 0)) {
if (ImGui::VSliderFloat("##_9_", ImVec2(20.0, 150.0), &fftMin, 0.0, -100.0, "")) {
fftMin = std::min<float>(fftMax - 10, fftMin);
core::configManager.aquire();
core::configManager.conf["min"] = fftMin;

View File

@ -99,7 +99,7 @@ namespace style {
colors[ImGuiCol_PlotHistogram] = ImVec4(0.73f, 0.60f, 0.15f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.87f, 0.87f, 0.87f, 0.35f);
colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);

View File

@ -3,14 +3,14 @@
#include <options.h>
#include <filesystem>
FileSelect::FileSelect(std::string defaultPath, char* filter) {
FileSelect::FileSelect(std::string defaultPath) {
path = defaultPath;
strcpy(_filter, filter);
pathValid = std::filesystem::is_regular_file(path);
strcpy(strPath, path.c_str());
}
void FileSelect::render(std::string id) {
bool FileSelect::render(std::string id) {
bool _pathChanged = false;
#ifdef _WIN32
float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
float buttonWidth = ImGui::CalcTextSize("...").x + 20.0f;
@ -59,6 +59,15 @@ void FileSelect::render(std::string id) {
ImGui::PopStyleColor();
}
#endif
_pathChanged |= pathChanged;
pathChanged = false;
return _pathChanged;
}
void FileSelect::setPath(std::string path) {
this->path = path;
pathValid = std::filesystem::is_regular_file(path);
strcpy(strPath, path.c_str());
}
std::string FileSelect::expandString(std::string input) {
@ -70,45 +79,35 @@ bool FileSelect::pathIsValid() {
return pathValid;
}
bool FileSelect::pathChanged() {
if (_pathChanged) {
_pathChanged = false;
return true;
}
return false;
#ifdef _WIN32
void FileSelect::setWindowsFilter(COMDLG_FILTERSPEC* filt, int n) {
filter = filt;
filterCount = n;
}
#ifdef _WIN32
void FileSelect::windowsWorker() {
OPENFILENAMEA ofn; // common dialog box structure
char szFile[2048]; // buffer for file name
HWND hwnd; // owner window
HANDLE hf; // file handle
IFileOpenDialog *pFileOpen;
HRESULT hr;
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = GetFocus();
ofn.lpstrFile = (LPSTR)szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = (LPCSTR)_filter;
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXTENSIONDIFFERENT;
// Create the FileOpenDialog object.
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
if (filter != NULL) { pFileOpen->SetFileTypes(filterCount, filter); }
// Display the Open dialog box.
if (GetOpenFileNameA(&ofn)==TRUE) {
strcpy(strPath, szFile);
_pathChanged = true;
hr = pFileOpen->Show(NULL);
if (SUCCEEDED(hr)) {
PWSTR pszFilePath;
IShellItem *pItem;
hr = pFileOpen->GetResult(&pItem);
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
wcstombs(strPath, pszFilePath, 2048);
CoTaskMemFree(pszFilePath);
path = std::string(strPath);
pathChanged = true;
}
pathValid = std::filesystem::is_regular_file(strPath);
pathValid = std::filesystem::is_regular_file(path);
dialogOpen = false;
}
#endif

View File

@ -7,28 +7,35 @@
#ifdef _WIN32
#include <Windows.h>
#include <thread>
#include <ShObjIdl.h>
#endif
class FileSelect {
public:
FileSelect(std::string defaultPath, char* filter = "All\0*.*");
void render(std::string id);
FileSelect(std::string defaultPath);
bool render(std::string id);
void setPath(std::string path);
bool pathIsValid();
bool pathChanged();
std::string expandString(std::string input);
std::string path = "";
#ifdef _WIN32
void setWindowsFilter(COMDLG_FILTERSPEC* filt, int n);
#endif
private:
#ifdef _WIN32
void windowsWorker();
std::thread workerThread;
COMDLG_FILTERSPEC* filter = NULL;
int filterCount = 0;
#endif
char _filter[2048];
bool pathValid = false;
bool dialogOpen = false;
char strPath[2048];
bool _pathChanged = false;
bool pathChanged = false;
};

View File

@ -0,0 +1,108 @@
#include <gui/widgets/folder_select.h>
#include <regex>
#include <options.h>
#include <filesystem>
FolderSelect::FolderSelect(std::string defaultPath) {
setPath(defaultPath);
}
bool FolderSelect::render(std::string id) {
bool _pathChanged = false;
#ifdef _WIN32
float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
float buttonWidth = ImGui::CalcTextSize("...").x + 20.0f;
bool lastPathValid = pathValid;
if (!lastPathValid) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
}
ImGui::SetNextItemWidth(menuColumnWidth - buttonWidth);
if (ImGui::InputText(id.c_str(), strPath, 2047)) {
path = std::string(strPath);
std::string expandedPath = expandString(strPath);
if (!std::filesystem::is_directory(expandedPath)) {
pathValid = false;
}
else {
pathValid = true;
_pathChanged = true;
}
}
if (!lastPathValid) {
ImGui::PopStyleColor();
}
ImGui::SameLine();
if (ImGui::Button(("..." + id + "_winselect").c_str(), ImVec2(buttonWidth - 8.0f, 0)) && !dialogOpen) {
dialogOpen = true;
if (workerThread.joinable()) { workerThread.join(); }
workerThread = std::thread(&FolderSelect::windowsWorker, this);
}
#else
bool lastPathValid = pathValid;
if (!lastPathValid) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
}
if (ImGui::InputText(id.c_str(), strPath, 2047)) {
path = std::string(strPath);
std::string expandedPath = expandString(strPath);
if (!std::filesystem::is_directory(expandedPath)) {
pathValid = false;
}
else {
pathValid = true;
_pathChanged = true;
}
}
if (!lastPathValid) {
ImGui::PopStyleColor();
}
#endif
_pathChanged |= pathChanged;
pathChanged = false;
return _pathChanged;
}
void FolderSelect::setPath(std::string path) {
this->path = path;
std::string expandedPath = expandString(path);
pathValid = std::filesystem::is_directory(expandedPath);
strcpy(strPath, path.c_str());
}
std::string FolderSelect::expandString(std::string input) {
input = std::regex_replace(input, std::regex("%ROOT%"), options::opts.root);
return std::regex_replace(input, std::regex("//"), "/");
}
bool FolderSelect::pathIsValid() {
return pathValid;
}
#ifdef _WIN32
void FolderSelect::windowsWorker() {
IFileOpenDialog *pFileOpen;
HRESULT hr;
// Create the FileOpenDialog object.
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
DWORD options;
pFileOpen->GetOptions(&options);
pFileOpen->SetOptions(options | FOS_PICKFOLDERS);
hr = pFileOpen->Show(NULL);
if (SUCCEEDED(hr)) {
PWSTR pszFilePath;
IShellItem *pItem;
hr = pFileOpen->GetResult(&pItem);
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
wcstombs(strPath, pszFilePath, 2048);
CoTaskMemFree(pszFilePath);
path = std::string(strPath);
pathChanged = true;
}
pathValid = std::filesystem::is_directory(path);
dialogOpen = false;
}
#endif

View File

@ -0,0 +1,35 @@
#pragma once
#include <imgui.h>
#include <imgui_internal.h>
#include <stdint.h>
#include <string>
#ifdef _WIN32
#include <Windows.h>
#include <ShlObj_core.h>
#include <thread>
#endif
class FolderSelect {
public:
FolderSelect(std::string defaultPath);
bool render(std::string id);
void setPath(std::string path);
bool pathIsValid();
std::string expandString(std::string input);
std::string path = "";
private:
#ifdef _WIN32
void windowsWorker();
std::thread workerThread;
#endif
bool pathValid = false;
bool dialogOpen = false;
char strPath[2048];
bool pathChanged = false;
};

View File

@ -1,21 +0,0 @@
#pragma once
#include <algorithm>
namespace ImGui {
template<class T>
inline bool AllowScrollwheel(T& value, int stepCount, T min, T max) {
if(!ImGui::IsItemHovered()) { return false; }
T lastVal = value;
T step = (max - min) / (T)stepCount;
value = std::clamp<T>(value + ((T)ImGui::GetIO().MouseWheel * step), (min < max) ? min : max, (max > min) ? max : min);
return (value != lastVal);
}
template<class T>
inline bool AllowScrollwheelStSz(T& value, T step, T min, T max) {
if(!ImGui::IsItemHovered()) { return false; }
T lastVal = value;
value = std::clamp<T>(value + ((T)ImGui::GetIO().MouseWheel * step), (min < max) ? min : max, (max > min) ? max : min);
return (value != lastVal);
}
}

View File

@ -1,7 +1,7 @@
#include <gui/widgets/stepped_slider.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <gui/widgets/scroll_behavior.h>
namespace ImGui {
bool SliderFloatWithSteps(const char* label, float* v, float v_min, float v_max, float v_step, const char* display_format) {
@ -16,7 +16,6 @@ namespace ImGui {
const int countValues = int((v_max-v_min)/v_step);
int v_i = int((*v - v_min)/v_step);
bool value_changed = ImGui::SliderInt(label, &v_i, 0, countValues, text_buf);
value_changed |= ImGui::AllowScrollwheelStSz<int>(v_i, 1, 0, countValues);
// Remap from [0,N] to [v_min,v_max]
*v = v_min + float(v_i) * v_step;

View File

@ -3,10 +3,11 @@
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
//-----------------------------------------------------------------------------
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/branch with your modifications to imconfig.h)
// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include
// the imgui*.cpp files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
//-----------------------------------------------------------------------------
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
//-----------------------------------------------------------------------------
@ -30,7 +31,7 @@
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable debug/metrics window: ShowMetricsWindow() will be empty.
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty.
//---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
@ -48,7 +49,7 @@
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use 32-bit for ImWchar (default is 16-bit) to support full unicode code points.
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
@ -58,8 +59,8 @@
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//---- Unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined, use the much faster STB sprintf library implementation of vsnprintf instead of the one from the default C library.
// Note that stb_sprintf.h is meant to be provided by the user and available in the include path at compile time. Also, the compatibility checks of the arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
// #define IMGUI_USE_STB_SPRINTF
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
@ -75,12 +76,12 @@
*/
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bit indices).
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
//#define ImDrawIdx unsigned int
//---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly)
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
//struct ImDrawList;
//struct ImDrawCmd;
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// dear imgui: Platform Binding for GLFW
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
// (Requires: GLFW 3.1+)
@ -9,9 +9,9 @@
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
@ -143,7 +143,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
g_Window = window;
g_Time = 0.0;
// Setup back-end capabilities flags
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
@ -345,7 +345,7 @@ static void ImGui_ImplGlfw_UpdateGamepads()
void ImGui_ImplGlfw_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
// Setup display size (every frame to accommodate for window resizing)
int w, h;
@ -358,7 +358,7 @@ void ImGui_ImplGlfw_NewFrame()
// Setup time step
double current_time = glfwGetTime();
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
g_Time = current_time;
ImGui_ImplGlfw_UpdateMousePosAndButtons();
@ -366,4 +366,4 @@ void ImGui_ImplGlfw_NewFrame()
// Update game controllers (if enabled and available)
ImGui_ImplGlfw_UpdateGamepads();
}
}

View File

@ -1,4 +1,4 @@
// dear imgui: Platform Binding for GLFW
// dear imgui: Platform Backend for GLFW
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
@ -8,9 +8,9 @@
// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW.
// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// About GLSL version:
// The 'glsl_version' initialization parameter defaults to "#version 150" if NULL.
@ -32,4 +32,4 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);

View File

@ -1,18 +1,23 @@
// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
// - Desktop GL: 2.x 3.x 4.x
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
// 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix.
// 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset.
@ -24,7 +29,7 @@
// 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop.
// 2019-03-15: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
// 2019-03-15: OpenGL: Added a GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
// 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0).
// 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
@ -80,7 +85,6 @@
#include <stdint.h> // intptr_t
#endif
// GL includes
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <GLES2/gl2.h>
@ -101,6 +105,8 @@
#include <GL/glew.h> // Needs to be initialized with glewInit() in user's code.
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
#include <glad/glad.h> // Needs to be initialized with gladLoadGL() in user's code.
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2)
#include <glad/gl.h> // Needs to be initialized with gladLoadGL(...) or gladLoaderLoadGL() in user's code.
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)
#ifndef GLFW_INCLUDE_NONE
#define GLFW_INCLUDE_NONE // GLFW including OpenGL headers causes ambiguity or multiple definition errors.
@ -121,10 +127,18 @@ using namespace gl;
#endif
// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
#if defined(IMGUI_IMPL_OPENGL_ES2) || defined(IMGUI_IMPL_OPENGL_ES3) || !defined(GL_VERSION_3_2)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 0
#else
#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 1
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
#endif
// Desktop GL 3.3+ has glBindSampler()
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_3)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
#endif
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif
// OpenGL Data
@ -141,18 +155,25 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{
// Query for GL version (e.g. 320 for GL 3.2)
#if !defined(IMGUI_IMPL_OPENGL_ES2)
GLint major, minor;
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major == 0 && minor == 0)
{
// Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
const char* gl_version = (const char*)glGetString(GL_VERSION);
sscanf(gl_version, "%d.%d", &major, &minor);
}
g_GlVersion = (GLuint)(major * 100 + minor * 10);
#else
g_GlVersion = 200; // GLES 2
#endif
// Setup back-end capabilities flags
// Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_opengl3";
#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
if (g_GlVersion >= 320)
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
#endif
@ -176,7 +197,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
strcpy(g_GlslVersionString, glsl_version);
strcat(g_GlslVersionString, "\n");
// Dummy construct to make it easily visible in the IDE and debugger which GL loader has been selected.
// Debugging construct to make it easily visible in the IDE and debugger which GL loader has been selected.
// The code actually never uses the 'gl_loader' variable! It is only here so you can read it!
// If auto-detection fails or doesn't select the same GL loader file as used by your application,
// you are likely to get a crash below.
@ -189,6 +210,8 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
gl_loader = "GLEW";
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
gl_loader = "GLAD";
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2)
gl_loader = "GLAD2";
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2)
gl_loader = "glbinding2";
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3)
@ -199,7 +222,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
gl_loader = "none";
#endif
// Make a dummy GL call (we don't actually need the result)
// Make an arbitrary GL call (we don't actually need the result)
// IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code.
// Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above.
GLint current_texture;
@ -227,14 +250,19 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glEnable(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
if (g_GlVersion >= 310)
glDisable(GL_PRIMITIVE_RESTART);
#endif
#ifdef GL_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
bool clip_origin_lower_left = true;
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
bool clip_origin_lower_left = true;
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin);
if (current_clip_origin == GL_UPPER_LEFT)
clip_origin_lower_left = false;
@ -247,7 +275,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
#endif
const float ortho_projection[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
@ -258,8 +288,10 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
glUseProgram(g_ShaderHandle);
glUniform1i(g_AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
#ifdef GL_SAMPLER_BINDING
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (g_GlVersion >= 330)
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
#endif
(void)vertex_array_object;
@ -279,8 +311,8 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
}
// OpenGL3 Render function.
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
// This is in order to be able to run within an OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
@ -294,8 +326,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
glActiveTexture(GL_TEXTURE0);
GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program);
GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture);
#ifdef GL_SAMPLER_BINDING
GLuint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
GLuint last_sampler; if (g_GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
#endif
GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
#ifndef IMGUI_IMPL_OPENGL_ES2
@ -315,7 +347,11 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
#endif
// Setup desired GL state
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
@ -367,7 +403,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
// Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
if (g_GlVersion >= 320)
glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
else
@ -386,8 +422,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
// Restore modified GL state
glUseProgram(last_program);
glBindTexture(GL_TEXTURE_2D, last_texture);
#ifdef GL_SAMPLER_BINDING
glBindSampler(0, last_sampler);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (g_GlVersion >= 330)
glBindSampler(0, last_sampler);
#endif
glActiveTexture(last_active_texture);
#ifndef IMGUI_IMPL_OPENGL_ES2
@ -399,7 +436,12 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
#endif
#ifdef GL_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
#endif

View File

@ -1,15 +1,15 @@
// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
// - Desktop GL: 2.x 3.x 4.x
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// About Desktop OpenGL function loaders:
// Modern Desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
@ -49,6 +49,7 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD2) \
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING2) \
&& !defined(IMGUI_IMPL_OPENGL_LOADER_GLBINDING3) \
&& !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
@ -68,6 +69,8 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
#define IMGUI_IMPL_OPENGL_LOADER_GLEW
#elif __has_include(<glad/glad.h>)
#define IMGUI_IMPL_OPENGL_LOADER_GLAD
#elif __has_include(<glad/gl.h>)
#define IMGUI_IMPL_OPENGL_LOADER_GLAD2
#elif __has_include(<GL/gl3w.h>)
#define IMGUI_IMPL_OPENGL_LOADER_GL3W
#elif __has_include(<glbinding/glbinding.h>)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -148,6 +148,8 @@
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
// STB_TEXTEDIT_K_UP keyboard input to move cursor up
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
@ -170,14 +172,10 @@
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
//
// Todo:
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
//
// Keyboard input must be encoded as a single integer value; e.g. a character code
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
// i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
// i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
//
// You can encode other things, such as CONTROL or ALT, in additional bits, and
// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
@ -337,6 +335,10 @@ typedef struct
// each textfield keeps its own insert mode state. to keep an app-wide
// insert mode, copy this value in/out of the app state
int row_count_per_page;
// page size in number of row.
// this value MUST be set to >0 for pageup or pagedown in multilines documents.
/////////////////////
//
// private data
@ -855,12 +857,16 @@ retry:
break;
case STB_TEXTEDIT_K_DOWN:
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: {
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGDOWN:
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: {
StbFindState find;
StbTexteditRow row;
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN;
int row_count = is_page ? state->row_count_per_page : 1;
if (state->single_line) {
if (!is_page && state->single_line) {
// on windows, up&down in single-line behave like left&right
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
goto retry;
@ -869,17 +875,25 @@ retry:
if (sel)
stb_textedit_prep_selection_at_cursor(state);
else if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_last(str,state);
stb_textedit_move_to_last(str, state);
// compute current position of cursor point
stb_textedit_clamp(str, state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
// now find character position down a row
if (find.length) {
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
float x;
for (j = 0; j < row_count; ++j) {
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
int start = find.first_char + find.length;
if (find.length == 0)
break;
// [DEAR IMGUI]
// going down while being on the last line shouldn't bring us to that line end
if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE)
break;
// now find character position down a row
state->cursor = start;
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
x = row.x0;
@ -901,17 +915,25 @@ retry:
if (sel)
state->select_end = state->cursor;
// go to next line
find.first_char = find.first_char + find.length;
find.length = row.num_chars;
}
break;
}
case STB_TEXTEDIT_K_UP:
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGUP:
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: {
StbFindState find;
StbTexteditRow row;
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP;
int row_count = is_page ? state->row_count_per_page : 1;
if (state->single_line) {
if (!is_page && state->single_line) {
// on windows, up&down become left&right
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
goto retry;
@ -926,11 +948,14 @@ retry:
stb_textedit_clamp(str, state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
// can only go up if there's a previous row
if (find.prev_first != find.first_char) {
for (j = 0; j < row_count; ++j) {
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
// can only go up if there's a previous row
if (find.prev_first == find.first_char)
break;
// now find character position up a row
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
float x;
state->cursor = find.prev_first;
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
x = row.x0;
@ -952,6 +977,14 @@ retry:
if (sel)
state->select_end = state->cursor;
// go to previous line
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
--prev_scan;
find.first_char = find.prev_first;
find.prev_first = prev_scan;
}
break;
}
@ -1075,10 +1108,6 @@ retry:
state->has_preferred_x = 0;
break;
}
// @TODO:
// STB_TEXTEDIT_K_PGUP - move cursor up a page
// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
}
}
@ -1134,7 +1163,7 @@ static void stb_textedit_discard_redo(StbUndoState *state)
state->undo_rec[i].char_storage += n;
}
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
// {DEAR IMGUI]
// [DEAR IMGUI]
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
@ -1350,6 +1379,7 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
state->initialized = 1;
state->single_line = (unsigned char) is_single_line;
state->insert_mode = 0;
state->row_count_per_page = 0;
}
// API initialize

View File

@ -3,7 +3,7 @@
#include <imgui/imgui.h>
#include <gui/style.h>
#include <gui/icons.h>
#include <gui/widgets/scroll_behavior.h>
#include <core.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -217,7 +217,7 @@ void SinkManager::showVolumeSlider(std::string name, std::string prefix, float w
ImGui::SetNextItemWidth(width - height - 8);
ImGui::SetCursorPosY(ypos + ((height - sliderHeight) / 2.0f) + btwBorder);
if (ImGui::SliderFloat((prefix + name).c_str(), &stream->guiVolume, 0.0f, 1.0f, "") || ImGui::AllowScrollwheel<float>(stream->guiVolume, 20, 0, 1)) {
if (ImGui::SliderFloat((prefix + name).c_str(), &stream->guiVolume, 0.0f, 1.0f, "")) {
stream->setVolume(stream->guiVolume);
core::configManager.aquire();
saveStreamConfig(name);

View File

@ -5,19 +5,22 @@
#include <signal_path/signal_path.h>
#include <wavreader.h>
#include <core.h>
#include <gui/widgets/file_select.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
MOD_INFO {
/* Name: */ "fike_source",
/* Description: */ "File input module for SDR++",
/* Author: */ "Ryzerth",
/* Version: */ "0.1.0"
SDRPP_MOD_INFO {
/* Name: */ "file_source",
/* Description: */ "Wav file source module for SDR++",
/* Author: */ "Ryzerth",
/* Version: */ 0, 1, 1,
/* Max instances */ 1
};
class FileSourceModule {
class FileSourceModule : public ModuleManager::Instance {
public:
FileSourceModule(std::string name) {
FileSourceModule(std::string name) : fileSelect("") {
this->name = name;
handler.ctx = this;
@ -30,10 +33,6 @@ public:
handler.stream = &stream;
sigpath::sourceManager.registerSource("File", &handler);
reader = new WavReader("D:/satpic/raw_recordings/NOAA-18_09-08-2018_21-39-00_baseband_NR.wav");
spdlog::info("Samplerate: {0}, Bit depth: {1}, Channel count: {2}", reader->getSampleRate(), reader->getBitDepth(), reader->getChannelCount());
spdlog::info("FileSourceModule '{0}': Instance created!", name);
}
@ -41,10 +40,22 @@ public:
spdlog::info("FileSourceModule '{0}': Instance deleted!", name);
}
void enable() {
enabled = true;
}
void disable() {
enabled = false;
}
bool isEnabled() {
return enabled;
}
private:
static void menuSelected(void* ctx) {
FileSourceModule* _this = (FileSourceModule*)ctx;
core::setInputSampleRate(_this->reader->getSampleRate());
core::setInputSampleRate(_this->sampleRate);
spdlog::info("FileSourceModule '{0}': Menu Select!", _this->name);
}
@ -55,15 +66,22 @@ private:
static void start(void* ctx) {
FileSourceModule* _this = (FileSourceModule*)ctx;
if (_this->running) { return; }
if (_this->reader == NULL) { return; }
_this->running = true;
_this->workerThread = std::thread(worker, _this);
spdlog::info("FileSourceModule '{0}': Start!", _this->name);
}
static void stop(void* ctx) {
FileSourceModule* _this = (FileSourceModule*)ctx;
if (!_this->running) { return; }
if (_this->reader == NULL) { return; }
_this->stream.stopWriter();
_this->workerThread.join();
_this->stream.clearWriteStop();
_this->running = false;
_this->reader->rewind();
spdlog::info("FileSourceModule '{0}': Stop!", _this->name);
}
@ -74,7 +92,27 @@ private:
static void menuHandler(void* ctx) {
FileSourceModule* _this = (FileSourceModule*)ctx;
ImGui::Text("Hi from %s!", _this->name.c_str());
if (_this->fileSelect.render("##file_source_" + _this->name)) {
if (_this->fileSelect.pathIsValid()) {
if (_this->reader != NULL) {
_this->reader->close();
delete _this->reader;
}
try {
_this->reader = new WavReader(_this->fileSelect.path);
if (_this->reader->isValid() && _this->reader->getBitDepth() == 16 && _this->reader->getChannelCount() == 2) {
_this->sampleRate = _this->reader->getSampleRate();
core::setInputSampleRate(_this->sampleRate);
}
else {
_this->reader->close();
delete _this->reader;
}
}
catch (std::exception e) {}
}
}
}
static void worker(void* ctx) {
@ -85,22 +123,24 @@ private:
while (true) {
_this->reader->readSamples(inBuf, blockSize * 2 * sizeof(int16_t));
if (_this->stream.aquire() < 0) { break; };
for (int i = 0; i < blockSize; i++) {
_this->stream.data[i].q = (float)inBuf[i * 2] / (float)0x7FFF;
_this->stream.data[i].i = (float)inBuf[(i * 2) + 1] / (float)0x7FFF;
_this->stream.writeBuf[i].q = (float)inBuf[i * 2] / (float)0x7FFF;
_this->stream.writeBuf[i].i = (float)inBuf[(i * 2) + 1] / (float)0x7FFF;
}
_this->stream.write(blockSize);
//std::this_thread::sleep_for(std::chrono::milliseconds(5));
if (!_this->stream.swap(blockSize)) { break; };
}
delete[] inBuf;
}
FileSelect fileSelect;
std::string name;
dsp::stream<dsp::complex_t> stream;
SourceManager::SourceHandler handler;
WavReader* reader;
WavReader* reader = NULL;
bool running = false;
bool enabled = true;
float sampleRate = 48000;
std::thread workerThread;
};
@ -116,6 +156,6 @@ MOD_EXPORT void _DELETE_INSTANCE_(void* instance) {
delete (FileSourceModule*)instance;
}
MOD_EXPORT void _STOP_() {
MOD_EXPORT void _END_() {
// Do your one shutdown here
}

View File

@ -2,6 +2,7 @@
#pragma once
#include <stdint.h>
#include <string.h>
#include <fstream>
#define WAV_SIGNATURE "RIFF"
@ -15,6 +16,10 @@ public:
WavReader(std::string path) {
file = std::ifstream(path.c_str(), std::ios::binary);
file.read((char*)&hdr, sizeof(WavHeader_t));
valid = false;
if (memcmp(hdr.signature, "RIFF", 4) != 0) { return; }
if (memcmp(hdr.fileType, "WAVE", 4) != 0) { return; }
valid = true;
}
uint16_t getBitDepth() {
@ -29,13 +34,26 @@ public:
return hdr.sampleRate;
}
bool isValid() {
return valid;
}
void readSamples(void* data, size_t size) {
file.read((char*)data, size);
char* _data = (char*)data;
file.read(_data, size);
int read = file.gcount();
if (read < size) {
file.seekg(sizeof(WavHeader_t));
file.read(&_data[read], size - read);
}
bytesRead += size;
}
void rewind() {
file.seekg(sizeof(WavHeader_t));
}
void close() {
file.close();
}
@ -56,6 +74,7 @@ private:
uint32_t dataSize;
};
bool valid = false;
std::ifstream file;
size_t bytesRead = 0;
WavHeader_t hdr;

View File

@ -8,7 +8,7 @@
#include <iio.h>
#include <ad9361.h>
#include <options.h>
#include <gui/widgets/scroll_behavior.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -193,7 +193,7 @@ private:
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (_this->gainMode) { style::beginDisabled(); }
if (ImGui::SliderFloat(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 76) || ImGui::AllowScrollwheel<float>(_this->gain, 19, 0, 76)) {
if (ImGui::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));
}

View File

@ -7,7 +7,7 @@
#include <string>
#include <config.h>
#include <imgui.h>
#include <gui/widgets/scroll_behavior.h>
class AMDemodulator : public Demodulator {
public:
@ -119,7 +119,7 @@ public:
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::SetNextItemWidth(menuWidth);
if (ImGui::InputFloat(("##_radio_am_bw_" + uiPrefix).c_str(), &bw, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_am_bw_" + uiPrefix).c_str(), &bw, 1, 100, "%.0f", 0)) {
bw = std::clamp<float>(bw, bwMin, bwMax);
setBandwidth(bw);
_config->aquire();
@ -130,7 +130,7 @@ public:
ImGui::Text("Snap Interval");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputFloat(("##_radio_am_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_am_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, "%.0f", 0)) {
setSnapInterval(snapInterval);
_config->aquire();
_config->conf[uiPrefix]["AM"]["snapInterval"] = snapInterval;
@ -140,7 +140,7 @@ public:
ImGui::Text("Squelch");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderFloat(("##_radio_am_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB") || ImGui::AllowScrollwheel<float>(squelchLevel, 20, -100, 0)) {
if (ImGui::SliderFloat(("##_radio_am_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
squelch.setLevel(squelchLevel);
_config->aquire();
_config->conf[uiPrefix]["AM"]["squelchLevel"] = squelchLevel;

View File

@ -10,7 +10,7 @@
#include <string>
#include <config.h>
#include <imgui.h>
#include <gui/widgets/scroll_behavior.h>
class CWDemodulator : public Demodulator {
public:
@ -127,7 +127,7 @@ public:
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::SetNextItemWidth(menuWidth);
if (ImGui::InputFloat(("##_radio_cw_bw_" + uiPrefix).c_str(), &bw, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_cw_bw_" + uiPrefix).c_str(), &bw, 1, 100, "%.0f", 0)) {
bw = std::clamp<float>(bw, bwMin, bwMax);
setBandwidth(bw);
_config->aquire();
@ -138,7 +138,7 @@ public:
ImGui::Text("Snap Interval");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputFloat(("##_radio_cw_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_cw_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, "%.0f", 0)) {
setSnapInterval(snapInterval);
_config->aquire();
_config->conf[uiPrefix]["CW"]["snapInterval"] = snapInterval;
@ -148,7 +148,7 @@ public:
ImGui::Text("Squelch");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderFloat(("##_radio_cw_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB") || ImGui::AllowScrollwheel<float>(squelchLevel, 20, -100, 0)) {
if (ImGui::SliderFloat(("##_radio_cw_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
squelch.setLevel(squelchLevel);
_config->aquire();
_config->conf[uiPrefix]["CW"]["squelchLevel"] = squelchLevel;

View File

@ -7,7 +7,7 @@
#include <string>
#include <config.h>
#include <imgui.h>
#include <gui/widgets/scroll_behavior.h>
class DSBDemodulator : public Demodulator {
public:
@ -119,7 +119,7 @@ public:
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::SetNextItemWidth(menuWidth);
if (ImGui::InputFloat(("##_radio_dsb_bw_" + uiPrefix).c_str(), &bw, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_dsb_bw_" + uiPrefix).c_str(), &bw, 1, 100, "%.0f", 0)) {
bw = std::clamp<float>(bw, bwMin, bwMax);
setBandwidth(bw);
_config->aquire();
@ -130,7 +130,7 @@ public:
ImGui::Text("Snap Interval");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputFloat(("##_radio_dsb_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_dsb_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, "%.0f", 0)) {
setSnapInterval(snapInterval);
_config->aquire();
_config->conf[uiPrefix]["DSB"]["snapInterval"] = snapInterval;
@ -140,7 +140,7 @@ public:
ImGui::Text("Squelch");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderFloat(("##_radio_dsb_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB") || ImGui::AllowScrollwheel<float>(squelchLevel, 20, -100, 0)) {
if (ImGui::SliderFloat(("##_radio_dsb_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
squelch.setLevel(squelchLevel);
_config->aquire();
_config->conf[uiPrefix]["DSB"]["squelchLevel"] = squelchLevel;

View File

@ -7,7 +7,7 @@
#include <string>
#include <config.h>
#include <imgui.h>
#include <gui/widgets/scroll_behavior.h>
class FMDemodulator : public Demodulator {
public:
@ -115,7 +115,7 @@ public:
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::SetNextItemWidth(menuWidth);
if (ImGui::InputFloat(("##_radio_fm_bw_" + uiPrefix).c_str(), &bw, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_fm_bw_" + uiPrefix).c_str(), &bw, 1, 100, "%.0f", 0)) {
bw = std::clamp<float>(bw, bwMin, bwMax);
setBandwidth(bw);
_config->aquire();
@ -126,7 +126,7 @@ public:
ImGui::Text("Snap Interval");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputFloat(("##_radio_fm_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_fm_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, "%.0f", 0)) {
setSnapInterval(snapInterval);
_config->aquire();
_config->conf[uiPrefix]["FM"]["snapInterval"] = snapInterval;
@ -136,7 +136,7 @@ public:
ImGui::Text("Squelch");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderFloat(("##_radio_fm_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB") || ImGui::AllowScrollwheel<float>(squelchLevel, 20, -100, 0)) {
if (ImGui::SliderFloat(("##_radio_fm_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
squelch.setLevel(squelchLevel);
_config->aquire();
_config->conf[uiPrefix]["FM"]["squelchLevel"] = squelchLevel;

View File

@ -7,7 +7,7 @@
#include <string>
#include <config.h>
#include <imgui.h>
#include <gui/widgets/scroll_behavior.h>
class LSBDemodulator : public Demodulator {
public:
@ -119,7 +119,7 @@ public:
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::SetNextItemWidth(menuWidth);
if (ImGui::InputFloat(("##_radio_lsb_bw_" + uiPrefix).c_str(), &bw, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_lsb_bw_" + uiPrefix).c_str(), &bw, 1, 100, "%.0f", 0)) {
bw = std::clamp<float>(bw, bwMin, bwMax);
setBandwidth(bw);
_config->aquire();
@ -130,7 +130,7 @@ public:
ImGui::Text("Snap Interval");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputFloat(("##_radio_lsb_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_lsb_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, "%.0f", 0)) {
setSnapInterval(snapInterval);
_config->aquire();
_config->conf[uiPrefix]["LSB"]["snapInterval"] = snapInterval;
@ -140,7 +140,7 @@ public:
ImGui::Text("Squelch");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderFloat(("##_radio_lsb_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB") || ImGui::AllowScrollwheel<float>(squelchLevel, 20, -100, 0)) {
if (ImGui::SliderFloat(("##_radio_lsb_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
squelch.setLevel(squelchLevel);
_config->aquire();
_config->conf[uiPrefix]["LSB"]["squelchLevel"] = squelchLevel;

View File

@ -7,7 +7,7 @@
#include <string>
#include <config.h>
#include <imgui.h>
#include <gui/widgets/scroll_behavior.h>
class RAWDemodulator : public Demodulator {
public:
@ -93,7 +93,7 @@ public:
ImGui::Text("Snap Interval");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputFloat(("##_radio_raw_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_raw_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, "%.0f", 0)) {
setSnapInterval(snapInterval);
_config->aquire();
_config->conf[uiPrefix]["RAW"]["snapInterval"] = snapInterval;
@ -103,7 +103,7 @@ public:
ImGui::Text("Squelch");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderFloat(("##_radio_raw_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB") || ImGui::AllowScrollwheel<float>(squelchLevel, 20, -100, 0)) {
if (ImGui::SliderFloat(("##_radio_raw_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
squelch.setLevel(squelchLevel);
_config->aquire();
_config->conf[uiPrefix]["RAW"]["squelchLevel"] = squelchLevel;

View File

@ -7,7 +7,7 @@
#include <string>
#include <config.h>
#include <imgui.h>
#include <gui/widgets/scroll_behavior.h>
class USBDemodulator : public Demodulator {
public:
@ -119,7 +119,7 @@ public:
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::SetNextItemWidth(menuWidth);
if (ImGui::InputFloat(("##_radio_usb_bw_" + uiPrefix).c_str(), &bw, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_usb_bw_" + uiPrefix).c_str(), &bw, 1, 100, "%.0f", 0)) {
bw = std::clamp<float>(bw, bwMin, bwMax);
setBandwidth(bw);
_config->aquire();
@ -130,7 +130,7 @@ public:
ImGui::Text("Snap Interval");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputFloat(("##_radio_usb_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_usb_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, "%.0f", 0)) {
setSnapInterval(snapInterval);
_config->aquire();
_config->conf[uiPrefix]["USB"]["snapInterval"] = snapInterval;
@ -140,7 +140,7 @@ public:
ImGui::Text("Squelch");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderFloat(("##_radio_usb_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB") || ImGui::AllowScrollwheel<float>(squelchLevel, 20, -100, 0)) {
if (ImGui::SliderFloat(("##_radio_usb_squelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
squelch.setLevel(squelchLevel);
_config->aquire();
_config->conf[uiPrefix]["USB"]["squelchLevel"] = squelchLevel;

View File

@ -7,7 +7,7 @@
#include <string>
#include <config.h>
#include <imgui.h>
#include <gui/widgets/scroll_behavior.h>
class WFMDemodulator : public Demodulator {
public:
@ -128,7 +128,7 @@ public:
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::SetNextItemWidth(menuWidth);
if (ImGui::InputFloat(("##_radio_wfm_bw_" + uiPrefix).c_str(), &bw, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_wfm_bw_" + uiPrefix).c_str(), &bw, 1, 100, "%.0f", 0)) {
bw = std::clamp<float>(bw, bwMin, bwMax);
setBandwidth(bw);
_config->aquire();
@ -139,7 +139,7 @@ public:
ImGui::Text("Snap Interval");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::InputFloat(("##_radio_wfm_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, 0)) {
if (ImGui::InputFloat(("##_radio_wfm_snap_" + uiPrefix).c_str(), &snapInterval, 1, 100, "%.0f", 0)) {
setSnapInterval(snapInterval);
_config->aquire();
_config->conf[uiPrefix]["WFM"]["snapInterval"] = snapInterval;
@ -160,7 +160,7 @@ public:
ImGui::Text("Squelch");
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::SliderFloat(("##_radio_wfm_sqelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB") || ImGui::AllowScrollwheel<float>(squelchLevel, 20, -100, 0)) {
if (ImGui::SliderFloat(("##_radio_wfm_sqelch_" + uiPrefix).c_str(), &squelchLevel, -100.0f, 0.0f, "%.3fdB")) {
squelch.setLevel(squelchLevel);
_config->aquire();
_config->conf[uiPrefix]["WFM"]["squelchLevel"] = squelchLevel;

View File

@ -15,6 +15,7 @@
#include <gui/widgets/volume_meter.h>
#include <regex>
#include <options.h>
#include <gui/widgets/folder_select.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
SDRPP_MOD_INFO {
@ -41,10 +42,10 @@ std::string genFileName(std::string prefix) {
class RecorderModule : public ModuleManager::Instance {
public:
RecorderModule(std::string name) {
RecorderModule(std::string name) : folderSelect("%ROOT%/recordings") {
this->name = name;
strcpy(recPath, "%ROOT%/recordings");
recPath = "%ROOT%/recordings";
// Init audio path
vol.init(&dummyStream, 1.0f);
@ -135,27 +136,12 @@ private:
if (_this->recording) { style::endDisabled(); }
// Recording path
ImGui::SetNextItemWidth(menuColumnWidth);
bool lastPathValid = _this->pathValid;
if (!lastPathValid) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
}
if (ImGui::InputText(CONCAT("##_recorder_path_", _this->name), _this->recPath, 4095)) {
std::string expandedPath = expandString(_this->recPath);
if (!std::filesystem::exists(expandedPath)) {
_this->pathValid = false;
}
else if (!std::filesystem::is_directory(expandedPath)) {
_this->pathValid = false;
}
else {
_this->pathValid = true;
// Save config here
if (_this->folderSelect.render("##_recorder_fold_" + _this->name)) {
if (_this->folderSelect.pathIsValid()) {
_this->recPath = _this->folderSelect.path;
}
}
if (!lastPathValid) {
ImGui::PopStyleColor();
}
_this->pathValid = _this->folderSelect.pathIsValid();
// Mode specific menu
if (_this->recMode) {
@ -172,7 +158,7 @@ private:
if (ImGui::Button(CONCAT("Record##_recorder_rec_", name), ImVec2(menuColumnWidth, 0))) {
recording = true;
samplesWritten = 0;
std::string expandedPath = expandString(std::string(recPath) + genFileName("/baseband_"));
std::string expandedPath = expandString(recPath + genFileName("/baseband_"));
sampleRate = sigpath::signalPath.getSampleRate();
basebandWriter = new WavWriter(expandedPath, 16, 2, sigpath::signalPath.getSampleRate());
basebandHandler.start();
@ -225,7 +211,7 @@ private:
if (ImGui::Button(CONCAT("Record##_recorder_rec_", name), ImVec2(menuColumnWidth, 0))) {
recording = true;
samplesWritten = 0;
std::string expandedPath = expandString(std::string(recPath) + genFileName("/audio_"));
std::string expandedPath = expandString(recPath + genFileName("/audio_"));
sampleRate = sigpath::sinkManager.getStreamSampleRate(selectedStreamName);
audioWriter = new WavWriter(expandedPath, 16, 2, sigpath::sinkManager.getStreamSampleRate(selectedStreamName));
audioHandler.start();
@ -273,7 +259,7 @@ private:
std::string name;
bool enabled = true;
char recPath[1024];
std::string recPath = "";
bool recMode = 1;
bool recording = false;
@ -288,6 +274,8 @@ private:
dsp::stream<dsp::stereo_t> dummyStream;
FolderSelect folderSelect;
// Audio path
dsp::stream<dsp::stereo_t>* audioInput;
dsp::Volume<dsp::stereo_t> vol;