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
@@ -153,6 +153,15 @@ class RowSet {
|
||||
/// belongs with `assign()` -- set it before the assignments that follow it, or they keep the alpha
|
||||
/// the previous view left behind.
|
||||
void set_trace_alpha(float alpha) noexcept { trace_alpha_ = alpha; }
|
||||
|
||||
/// The rows' shares of the figure's height, normalised by the plotter; an empty vector means equal
|
||||
/// rows. Kept here, and re-applied after every rebuild: a `Figure` is built afresh whenever a row's
|
||||
/// trace set or the row count changes, so weights that lived only in the figure would be lost on the
|
||||
/// first drop or row change after a user had sized their layout.
|
||||
void set_row_weights(std::vector<float> weights);
|
||||
/// Sizes the stored weights to the rows that exist and hands them to the figure.
|
||||
void apply_row_weights();
|
||||
const std::vector<float>& row_weights() const noexcept { return row_weights_; }
|
||||
/// Shows `rows` rows. A changed count rebuilds the figure, since a `Figure`'s row
|
||||
/// count is fixed at construction.
|
||||
void set_row_count(int rows);
|
||||
@@ -376,6 +385,13 @@ class RowSet {
|
||||
/// Whether a window is pinned: a held event, a filling capture or a paused view. The condition
|
||||
/// `fit_x()` branches on, which is why the fit probe reports it.
|
||||
bool window_pinned() const noexcept { return pinned_; }
|
||||
/// True when the pin already *is* this window. A caller that re-states a pin every frame -- the file
|
||||
/// view does, from the ring's own extent -- uses this to update the pin's numbers with
|
||||
/// `set_data_pin()` instead of writing the group's range again with `pin_event_window()`, which would
|
||||
/// undo a gesture that `hold_pinned_window()` has not adopted yet.
|
||||
bool pinned_window_is(double pre_s, double post_s) const noexcept {
|
||||
return pinned_ && pinned_pre_ == pre_s && pinned_post_ == post_s;
|
||||
}
|
||||
|
||||
/// Adopts the instruments a gesture is moving, on `drag_row` (the row whose controller holds
|
||||
/// a cursor), and nothing otherwise.
|
||||
@@ -497,6 +513,7 @@ class RowSet {
|
||||
plot::u32 x_group_ = 0;
|
||||
int rows_ = 1;
|
||||
float trace_alpha_ = 1.0f;
|
||||
std::vector<float> row_weights_;
|
||||
double window_s_ = 2.0;
|
||||
double trigger_marker_x_ = 0.0;
|
||||
bool trigger_marker_on_ = false;
|
||||
|
||||
Reference in new issue
Block a user