Files
udpscope/src/config.hpp
T
Martino Ferrari 0e256764d5 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.
2026-10-11 15:21:40 +02:00

72 lines
3.3 KiB
C++

// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2026 Martino Ferrari
#pragma once
#include <cstdint>
#include <string>
namespace udpscope {
/// Everything the command line can say. Defaults are the ones the spec names
/// (200 MB per buffer, 10 ms trigger hold-off) unless the user overrides them.
struct Config {
std::string server = "127.0.0.1"; ///< IPv4 dotted quad of the stream source.
std::uint16_t port = 8000; ///< UDP port (unicast) or TCP port (multicast).
std::string multicast; ///< Empty selects unicast.
std::string interface_addr; ///< Local IPv4 to join the group on; empty = default route.
/// Whether `--server` was given. Absent, the application asks which source to open rather
/// than silently taking the default above -- so this is "did the user choose", not "is
/// `server` valid". The default stays a usable value for every other path.
bool server_specified = false;
/// Size of *each* of the two sample buffers, in megabytes. The application
/// always allocates two identical buffers (spec item 1).
double buffer_mb = 200.0;
/// Whether `--buffer-mb` was given. A stored configuration's buffer size fills in only when the
/// flag was *absent*: an explicit flag beats a saved setting, and "not asked" is not the same
/// question as "asked for 200".
bool buffer_mb_specified = false;
/// Largest time window the toolbar offers, in seconds. The buffer partition is
/// sized to hold at least this much time (spec: decimation).
double max_window_s = 600.0;
double trigger_holdoff_s = 0.010;
int recv_buffer_bytes = 8 * 1024 * 1024;
/// Number of stacked plots (rows) to start with, 1..`RowSet::kMaxRows`. Only the
/// starting point: rows are added and removed from the layout editor.
int plots = 1;
/// Take the plot's time from the packet counter and the declared sample rate rather than
/// from the stream's own time signal, so arrival and producer-clock jitter cannot move a
/// sample's x. Absolute stream time is still recorded, for export only (`todo.md` item 2).
bool relative_time = false;
/// Whether relative time was *stated* rather than left at its default -- by `--relative-time`, or
/// by the preferences, which the source chooser can reach before this run is planned. A source's
/// stored configuration is a statement from an *older* session, so it only fills in the gap.
bool relative_time_specified = false;
/// `--capture-packets N`: the ring size of the raw-datagram capture, 1..100000.
/// 0 means the flag was absent: the capture is off, and the popover button then
/// uses the 1000-slot default when the user toggles it.
std::uint32_t capture_packets = 0;
/// `--open FILE`: a `.npy` an earlier run exported, opened for viewing and analysis instead of a
/// live source. File mode and source mode are exclusive -- there is no acquisition behind a file,
/// and the chooser's Waveforms page sets this rather than the connection fields.
std::string open_waveform;
};
/// Parses argv. On `--help` prints usage to stdout and exits(0); on a bad
/// argument prints a diagnostic to stderr and exits(2).
Config parse_args(int argc, char** argv);
/// Writes the usage text to `out`.
void print_usage(std::FILE* out, const char* argv0);
} // namespace udpscope