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:

command_queue.put((CommandSet.<NAME>, 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.