docs: the source-plugin framework, the --source options and the source-kinds probe

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-10-31 20:22:22 +01:00
1 parent 5cee00aaee
commit 4d859d6a37
6 files changed
+96 -11

No files matched your search

+24 -2
View File
@@ -10,8 +10,8 @@ concluding something is a bug.
### Threads
Exactly two: a producer thread in `Acquisition` owns `udps_client_t` and calls
`udps_client_poll()`; the GTK main thread owns every widget and GL context. They share
Exactly two: a producer thread in `Acquisition` owns a `DataSource` and calls
`source->poll(50)`; the GTK main thread owns every widget and GL context. They share
`ScopeModel` under `ScopeModel::mutex()`, taken once per DATA frame by the producer and
once per frame by the UI (`tick()` in `src/ui.cpp`) around `RowSet::bind()`/`acquire()`.
Samples themselves cross via `plot::data::RingBuffer` (single producer, single
@@ -21,6 +21,28 @@ consumer) and never through the lock. Cross-thread scalars are atomics on `Scope
before `trigger_pending_` and those two carry release/acquire, so a consumer that sees a
capture open sees which edge it belongs to.
### Sources
What feeds `Acquisition` is a `DataSource`, one of the registered *kinds*.
- The kinds live in `src/source/`. `register_builtin_sources()` fills the registry explicitly --
there is no static-initialiser registration, which a linker may drop -- and a future `dlopen`
loader would only call `register_kind()`.
- A `DataSource` delivers into `Acquisition` (a `SourceSink`) from inside `poll()`. `Frame` is
source-neutral, and its pointers are valid **only during `on_data`**: copy what is kept.
- The GTK thread reaches a source **only** through `DataSource::post(Command)`; the queue is drained
at the top of `poll()`. A panel never calls a source directly.
- `UdpsSource` wraps `deps/udpsclient` unchanged; `udps_*` names appear only in
`src/source/udps_*.cpp` (`grep -rn "udps_" src` outside those files is a leak of the old coupling).
- The frame is **single-timebase**. A multi-timebase source (ABScope) will change the interface and
the data path together; do not bend one frame to carry two clocks.
- A kind's capability panels are pages of `side_stack`, named `source-<id>`. A disconnected source
leaves them **insensitive, not hidden** (`apply_source_panels` in `src/ui_source.cpp`).
- Session file naming for a non-UDPS kind: the pseudo-host is `<kind>-<identity>` (characters outside
`[A-Za-z0-9._-]` become `_`) on port **1** (0 is rejected by the session-file parser), the kind is
stored as `source_kind` and its settings as `source_opt_<key>`. A UDPS file keeps `<host>_<port>` and
has neither key, so a legacy session is read as UDPS and nothing existing moves.
### Data path
`ScopeModel` holds **one `BufferStore`** (`live()`): one shared time-base ring plus one