--- title: command_queue Control Channel last_updated: 2025-02-06 --- # command_queue Control Channel This document describes the role of `command_queue` in the context generator stack and how it is used by `src/s6/app/track.py` and the GUI. --- ## 1. Purpose and Shape `command_queue` is the control-plane queue used to send runtime commands from the UI (or other callers) to a running `ContextGenerator` instance. It is separate from the data queue used to stream contexts to the GUI. Commands are sent as tuples: ```python command_queue.put((CommandSet., payload)) ``` `CommandSet` and `PlaybackMode` are defined in `src/s6/app/_common.py`. --- ## 2. ContextGenerator Usage In `src/s6/app/_contextgenerators.py`, `ContextGenerator.run(...)` accepts an optional `command_queue` argument. On each produced frame it drains the queue and applies any pending commands: - `RECORD` toggles continuous dataset recording. - `TAKESNAPSHOT` requests a single-frame write. - `SETEVOFFSET` updates the generator EV offset state. After handling commands, `run(...)` can: - invoke the pipeline, - enqueue the current context for the GUI, - write frames to disk when recording or snapshotting. `DatasetContextGenerator.get_frame(...)` extends command handling to include playback control and image adjustments. It checks the queue before each frame to update playback state (play, pause, seek), switch datasets, and apply EV or contrast adjustments. --- ## 3. Commands and Consumers The table below summarizes command payloads and where they are consumed: | CommandSet | Payload | Consumed in | | --- | --- | --- | | `RECORD` | `bool` | `ContextGenerator.run` | | `TAKESNAPSHOT` | `None` | `ContextGenerator.run` | | `SETEVOFFSET` | `float` | `ContextGenerator.run`, `DatasetContextGenerator.get_frame` | | `SETCONTRAST` | `float` | `DatasetContextGenerator.get_frame` | | `PLAYBACKCONTROL` | `PlaybackMode` | `DatasetContextGenerator.get_frame` | | `GOTOFRAME` | `int` | `DatasetContextGenerator.get_frame` | | `CHANGEDATASET` | `str` path | `DatasetContextGenerator.get_frame` | Notes: - `SETEVOFFSET` is stored in `ContextGenerator.run` but only applied to frames by `DatasetContextGenerator` today. - Playback-related commands only affect dataset replay. --- ## 4. track.py Integration `src/s6/app/track.py` wires the queue in UI mode: 1. A `multiprocessing.Manager()` creates a shared `command_queue`. 2. The background process calls `context_generator.run(..., command_queue=...)`. 3. The GUI receives the same queue instance and pushes commands to it. In headless mode, `ContextGenerator.run(...)` is called without a `command_queue`, so no interactive commands are processed. In uplink mode, a `command_queue` is still created and passed to the generator, but there is no built-in producer unless another component supplies commands. --- ## 5. GUI Integration `src/s6/app/_gui.py` uses the queue to send user actions to the generator: - Playback transport buttons send `PLAYBACKCONTROL` with the corresponding `PlaybackMode`. - The seek bar emits `GOTOFRAME` when the user releases the slider. It clears any queued commands before sending the final seek position. - Dataset selection sends `CHANGEDATASET` with the selected path. - Snapshot and record toolbar actions send `TAKESNAPSHOT` and `RECORD`. - Exposure and contrast sliders send `SETEVOFFSET` and `SETCONTRAST` updates. These commands are consumed in the generator process and change playback or recording behavior without restarting the pipeline.