udpscope: an oscilloscope view for a UDPStreamer source

GTK4 and libadwaita. It receives one UDP stream through the vendored
udpsclient, buffers it in a large ring, and draws it with the vendored
plotter: a trigger with a pre/post event window, a pause that freezes the
window, cursors, measurements, math channels in a node editor, an event cache,
named configurations, preferences, and an export of the visible window to
.npy/.csv. Waveform files can be opened and analysed in place.

The interface is two threads -- a producer that owns the socket and the GTK
main thread that owns every widget and the GL context -- sharing one model
under one mutex, with samples crossing through lock-free rings.

deps/plotter is a submodule pinned to the commit this tree builds against;
deps/udpsclient is vendored in place. docs/claude/ documents the rules that
cost a defect to learn, and SPECS.md is the requirement document.
This commit is contained in:
Martino Ferrari committed 2026-10-11 15:21:40 +02:00
1 parent 8f54841c2c
commit 0e256764d5
41 files changed
+2081 -154

No files matched your search

+5
View File
@@ -3,6 +3,7 @@
#include "acquisition.hpp"
#include "config.hpp"
#include "settings.hpp"
#include "waveform.hpp"
#include "model.hpp"
#include "plot_host.hpp"
@@ -16,6 +17,10 @@ int main(int argc, char** argv) {
udpscope::Config cfg;
try {
cfg = udpscope::parse_args(argc, argv);
// The preferences fill in what the command line did not decide. `--relative-time` is an explicit
// instruction for this run, so a preference can only turn the mode on, never off -- which is also
// why this is read here, before the buffers are planned: the mode changes how they are filled.
if (udpscope::load_settings().relative_time) cfg.relative_time = true;
} catch (const std::exception& e) {
std::fprintf(stderr, "udpscope: %s\n", e.what());
return 2;