e14e1ee069c4818f0f9d906988d07d7847ba32df
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e14e1ee069 |
trigger: a phosphor display keeps the last N acquisitions; and a Force button
Two changes in the trigger pane, landed together. **Persistence.** Trigger mode keeps the last N published acquisitions and draws them fading toward the background, N being a panel control (1..8, default 1) with N=1 meaning today's behaviour exactly, so the knob is the switch. The layers are the accumulate path's own -- one layer per (signal, age) in the row's free trace slots, named with the accumulate vocabulary so `layer_base_name()` strips the suffix and `signal_color()` resolves the base signal -- so a layer is not a signal: the signal list, the colours and the measurements see one row per signal. `ScopeModel` retains the outgoing snapshot in seven atomic `shared_ptr` slots (no lock, no copy; the snapshot already exists) and a layer's channel is resolved **by name inside the snapshot**, because the channel list is renumbered by any structural change since that acquisition was cut. `RowSet::sync_layers()` re-plans from the rows and the depth alone, so a latch costs no rebuild, and `event_data_window()` skips layer slots so an older acquisition can never re-pin the axis. The schedule is 0.5^age -- the acquisition on screen at full brightness and each older one half the previous, independent of N, so raising the depth adds dimmer acquisitions rather than rescaling the ones already on screen. Memory is bounded by the ring's own `--buffer-mb` rather than by the depth, which is the bound that cannot be driven into an OOM, and the panel says when either bound bites. This also wired up `set_trace_alpha()`, which the accumulate path was setting and nothing was reading -- so the documented 0.35 translucency of an accumulation was opaque in fact. **Force.** In the trigger pane beside Arm/Disarm, shown only while trigger mode is on: one acquisition now, with the configured window. It is a synthetic edge rather than a second publisher -- the engine opens one capture at the present moment and everything else is the ordinary latch, so a forced acquisition is cut, pinned, framed, recorded and cached exactly like a latched one, and the button owns no window and no publish. The pre-trigger gate is deliberately skipped (capture now is a request for the history that exists, and the snapshot reports its own shorter pre_s), a capture already filling is refused rather than restarted, and the state afterwards is the mode's: Normal stays armed, Single disarms. The request is one atomic flag written under the model mutex with `armed` -- the producer reads `armed` at the top of a packet and the request at the bottom, so a request written between the two would be dropped -- and consumed at the end of a packet, after the channel loop and before the pending publish. **A defect fixed in passing, in the function Force was modelled on:** `on_arm_clicked()` passed `TriggerConfig::channel` (an index into `channels()`) to `set_signal_enabled()` (an index into `signals()`). With one signal acquired, arming switched on the stream's clock signal and left the watched signal untouched -- and since a signal the panel was not showing is a change, it rebuilt the buffer under the click, dropping the very pre-trigger window the arming, and now the Force, was about to capture. Measured before: `0.0100 s of history behind it`; after: `2.5299 s`. `trigger_signal_index()` is now the one resolution, used by both buttons. |
||
|
|
fe499bfe41 | help: the search block's (i) on its header, a 12 px mark, and a real search page | ||
|
|
e140642ed0 |
fix: the manual's figures carry a description, and the check that would have caught them
Three pages opened in nothing in Yelp -- overview (twice), math, trigger -- while every check passed. They are exactly the pages whose <figure> had a sentence for a <title> and no <desc>: a Mallard <figure> is title?, desc?, media, and the page is refused without the description. The idiomatic shape, as the shipped sets on this machine write it, moves the sentence into <desc> and leaves the <title> a name. Note trigger-capture.png is referenced from both overview and trigger, which is why those two pages are the ones that were noticed. The gap was in the check, not in its reach: tools/check_help.sh ran links/media/orphans/ids and an HTML render, and all four are silent about a page that is well linked, well parsed and unrenderable. `yelp-check validate` is the one that would have caught it, and it cannot run here: it generates the RelaxNG schema with xsltproc, but the schema includes the base grammar over the network and this machine's libxml cannot fetch. So the structural rules this project has actually needed are checked with xmllint's XPath, offline, each written after a page needed it. One trap, paid for while writing it: a Mallard page declares xmlns="http://projectmallard.org/1.0/", XPath 1.0 has no default namespace, so `//figure` matches nothing and every rule passes -- the first version of this check reported "ok" for the very defect it was written for. Every expression uses local-name() for that reason, and the script says so where the next reader will be. Verified: on the committed pages the rules exit 1 and name the three figures, which is the failing-before case kept as the regression test; on the fixed pages all five rules pass and yelp-build renders all 15; make -C build test-help goes from red to green. |
||
|
|
c1460a6977 |
feat: the manual is a Mallard set opened in Yelp, not a GResource in the binary
The help was 14 Pango-markup `.txt` bodies in a second GResource, drawn into a paged `GtkWindow` built in `help_window.cpp`. That made F1 a viewer of ours with no search index, no cross-references and no translation, and it kept the manual in the *binary* when every other desktop application's is a document on disk. It is now a real Mallard set: help/C/org.udpscope.app/ index.page + 14 topic pages + figures/*.png and `show_help()` hands `help:org.udpscope.app` to whatever the desktop registered for the `help:` scheme -- Yelp on GNOME -- through a `GtkUriLauncher`, reporting a launch failure with a `GtkAlertDialog` rather than a click that silently does nothing. The paged window's builder, the page table and `help_self_check()`'s markup validation are gone with the resource. The document identifier is the desktop file's own basename (its desktop-file id), derived in CMakeLists from `data/org.udpscope.app.desktop.in`, so the same string is the `.desktop` name, the GApplication id and the install directory at once. The set is installed by a new `install()` rule to `<datadir>/help/C/org.udpscope.app/` -- where the freedesktop Help System Specification's `help:` URI resolves `help:<id>` -- so the manual is read from a datadir by another process even though the binary has no install step. `UDPSCOPE_HELP_NAME` and `UDPSCOPE_HELP_DIR` are compiled in from that one place. The 14 pages were migrated fact for fact, but restructured the Mallard way: a `<desc>` per page (what a search result shows), `<steps>` for procedures, `<terms>` for option lists, `<gui>`/`<key>`/`<keyseq>` for interface words and keys, `<note>` for the asides, and a topic graph via `<link type="guide" xref="index#main"/>`. The figures are annotated screenshots produced by `tools/make-help-shots.sh`, which drives the app headlessly against `tools/mock_udpstreamer.py` and draws the boxes with ImageMagick; the side panel's box is measured from the app's own `side=NNNx` dump reading, the header and status bands come from a documented table, and a crop whose standard deviation is 0 fails the script. `cmake --build build --target test-help` checks the set the way `test-ui` checks the `.ui` files: `yelp-check`'s offline subcommands (links, media, orphans, ids) and a `yelp-build html` render. `yelp-check validate` is deliberately absent -- it fetches the Mallard RelaxNG schema over the network and fails offline for that reason, not for a fault in the pages. The `[help]` probe reading changes with the resource it was written for. `parsed == pages` over in-binary markup cannot exist now, so `help_self_check()` scans `UDPSCOPE_HELP_DIR` and the line reads `topics=14 index=1 figures=3`; `topics=0 index=0` is the manual missing from the tree, which is the finding the old count named. Verified: clean build with the documented three warnings (the help bundle's `-Woverlength-strings` is gone, so the baseline moves from four to three); test-ui 14/14; test-help clean (the four subcommands and 15 pages rendered); a temp-prefix install lands 15 `.page` files and 3 figures at `share/help/C/org.udpscope.app/`; the headless run reads `[help] topics=14 index=1 figures=3 dir=...` with 0 Gtk-CRITICAL. Yelp's own window could not be exercised on this box -- it starts under Xvfb, activates its portals and never maps, the same WebKit/portal limitation that stops a grab -- so its rendering and its search index are unverified here; the content pipeline was (`yelp-build` renders the whole set). Docs: the manual's build/install/open story in `build-and-run.md` and README; the warning baseline in `verification.md`/CLAUDE.md; the help bullets in `invariants-gtk-and-chrome.md`; the `[help]` line in `probe-readings.md`. |