added loading screen

This commit is contained in:
Martino Ferrari committed 2026-10-14 00:38:24 +02:00
1 parent 881b52748e
commit 50a1ddca62
10 files changed
+249 -1

No files matched your search

+22
View File
@@ -390,3 +390,25 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
worth knowing: the line composes on its own cadence, so a notice can appear a beat after it was set (do not
read the label in the same tick a handler ran), and a refusal should say what to *do* about it -- "drop it on
another plot, or add a row with the layout editor (L)" rather than the bare statement of the limit.
- **The status line cannot cover the gap before the window exists, so a window does.** Between the chooser
closing and `gtk_window_present()` there is no main loop at all: the chooser destroyed its own window,
then `main()` allocates the sample buffer, waits for the first CONFIG or reads a recording, and
`on_activate()` builds every panel -- at a few gigabytes of buffer that is the ten seconds a user reported
as "the dialog disappeared and nothing happened". `loading_show()`/`loading_hide()` (in
`source_dialog.cpp`, beside the chooser they continue) keep an `AdwWindow` on screen across it, raised in
`main()` **before** the model is constructed and taken down in `on_activate()` **after** the present --
either side is a frame of empty screen. Three rules it exists under:
- **It must be painted before the caller blocks.** `gtk_window_present()` only queues the frame, and
nothing after it runs a loop, so `loading_show()` ends in a nested `GMainLoop` quit by a timeout
(the chooser's own idiom). Iterating pending events is *not* enough: a window needs a frame-clock
cycle, and the frame clock only ticks while a loop runs.
- **It says what the wait is, in words.** The spinner is frozen for the whole of it -- no loop -- and a
progress bar would be a lie for the same reason, so the text carries the information: the address
being connected to or the file being opened, and under it the buffer size, which is the number that
explains the duration. It is `deletable=0` with no title buttons: a close button that cannot be
serviced until the work is over is worse than none.
- **Only the path that *asked* gets one.** `main()` raises it only when the chooser actually ran, which
is why every documented probe (all of them pass `--server`) is on exactly the path it was before --
and a `--server` run never had a window to lose, so the post-present notice is the right place for it.
`loading_hide()` is a no-op when none is up, so `run_ui()` needs no notion of which path it is on.
+24
View File
@@ -910,6 +910,30 @@ sets them to **7.5 and 250** before saving, so a key that never reached the file
| `known:` after a rename | one row, under the new name | a rename that leaves the old file, so the chooser lists the same session twice |
| `known:` for a settings-only configuration | a row, though `signals=0` | the listing filter treating "no signals yet" as "nobody configured this", which hides every host the form set up |
## `[sources] loading`
```
[sources] picked 127.0.0.1:21077 multicast= interface= buffer=16 relative=0 capture=0 config=default note=''
[sources] loading: title='Connecting to 127.0.0.1:21077' detail='planning the 16 MB sample buffer'
[udpscope] CONFIG: 5 signals, publish=accumulate
[sources] loading: closed
```
The loading window covering the gap from the chooser to the first frame of the real window. It is
printed by any run that reaches the chooser, so `UDPSCOPE_PROBE_PICK_MS` reads the host leg and
`UDPSCOPE_PROBE_WAVE=<path>` the file one (`title='Opening rt.npy' detail='reading the recording'`).
| field | value it must read | the defect a wrong reading names |
| --- | --- | --- |
| `loading:` after `picked` | the address or basename just picked, and the buffer size | the window raised from the wrong place: before the chooser's answer it cannot name the wait, after the model it covers nothing |
| its position in the log | **before** the `CONFIG:` or `waveform loaded:` lines | a window shown after the work it is meant to cover — the ten seconds of empty screen, unchanged |
| `loading: closed` | **after** `CONFIG:`, i.e. once the real window is presented | a hide that runs earlier, which puts the screen back to empty for the frames the main window takes to map |
| no `loading:` line at all | correct for a `--server` or `--open` run | only the path that *asked* gets one; a line here means every probe just changed path |
`loading ui: loading.ui is missing an id this code reads` is the file-and-code mismatch the chooser's
own check names, and like it the run continues: a loading window that cannot be built must not stop
the app from opening.
## `[sources] prefs`
```
+9
View File
@@ -307,6 +307,15 @@ as distinct from the fault injection below, which exercises ingest:
configuration carried, into the `Config` the model is built from. A legacy file
(`<host>_<port>.toml`) produces `layout loaded from …/<host>_<port>/default.toml`, an `active`
holding `default`, and the old file renamed `.imported`.
- **The loading window covers the gap, and only on the path that asked.** The same
`UDPSCOPE_PROBE_PICK_MS` run must print
`[sources] loading: title='Connecting to 127.0.0.1:<port>' detail='planning the N MB sample buffer'`
**between** the `picked` line and the stream's `CONFIG:`, and `[sources] loading: closed` **after**
it — the window is raised before the buffer is planned and taken down only once the real window has
been presented, which is the whole of what it exists for. `UDPSCOPE_PROBE_WAVE=<path>` is the file
leg of it (`title='Opening <basename>' detail='reading the recording'`, before `waveform loaded:`).
A run that names its source with `--server` prints **no** `loading:` line at all: every other probe
here is on that path and must stay on it.
- **The event cache round-trips, and only where it is available.** `UDPSCOPE_PROBE_EVENTS_MS` reads
the pane's availability first, in the state the app starts in -- `[events] live: button_visible=0
pane=0 recording=1`, **no pane and no button without trigger mode** -- then turns trigger mode on