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:
1 parent
8f54841c2c
commit
0e256764d5
41 files changed
+2081
-154
No files matched your search
+11
-2
@@ -29,7 +29,7 @@ struct EventRecord {
|
||||
std::uint64_t seq = 0; ///< the run's own event counter, so two events in one second differ
|
||||
};
|
||||
|
||||
/// The cache of captured events: `<cache_dir>/<source>/events/`, one `.npy` per event written in
|
||||
/// The cache of captured events: `<cache_dir>/events/<source>/`, one `.npy` per event written in
|
||||
/// the **export format** -- so `--open` and the chooser's Waveforms page read it back with the
|
||||
/// loader that already exists -- beside a `.txt` sidecar holding what the list shows without
|
||||
/// loading the samples, and whatever thumbnail the caller rendered.
|
||||
@@ -37,10 +37,19 @@ struct EventRecord {
|
||||
/// No GTK: the caller renders the thumbnail and hands over a path, exactly as it hands over the
|
||||
/// table. The store owns naming, the sidecar, pruning and listing, which is what makes it testable
|
||||
/// without a window.
|
||||
/// The directory every source's event folder is created under when no preference says otherwise:
|
||||
/// `<cache>/udpscope/events`. Exposed because the preferences dialog shows it -- "the standard
|
||||
/// location" is not an answer a user can act on, and a second copy of the path computed in the dialog
|
||||
/// is a second thing to get wrong.
|
||||
std::string default_events_dir();
|
||||
|
||||
class EventStore {
|
||||
public:
|
||||
/// `source` is the `<host>-<port>` pair, the same key the packet capture uses.
|
||||
explicit EventStore(std::string source = {});
|
||||
/// `base_dir` is the directory every source's own folder is created under; empty means
|
||||
/// `<cache>/udpscope/events`. It comes from the preferences (item 9), because a user with a small
|
||||
/// home partition and a second disk should not have to choose between events and free space.
|
||||
explicit EventStore(std::string source = {}, std::string base_dir = {});
|
||||
|
||||
/// How many events to keep, newest first. The oldest beyond it are deleted on every save; item 9's
|
||||
/// preferences are where this becomes the user's number.
|
||||
|
||||
Reference in new issue
Block a user