subsequence.display

Live terminal dashboard for composition playback.

Provides a persistent status line showing the current bar, section, chord, BPM, and key. Optionally renders an ASCII grid visualisation of all running patterns above the status line, showing which steps have notes and at what velocity.

Log messages scroll above the dashboard without disruption.

Enable it with a single call before play():

composition.display()          # status line only
composition.display(grid=True) # status line + pattern grid
composition.play()

The status line updates every beat and looks like:

125 BPM  Key: E  Bar: 17  [chorus 1/8]  Chord: Em7

The grid (when enabled) updates every bar and looks like:

kick_2          |X . . . X . . . X . . . X . . .|
snare_1         |. . . . X . . . . . . . X . . .|
bass            |X . . X . . X . X . . . X . . .|

Module Contents

class subsequence.display.Display(composition: subsequence.composition.Composition, grid: bool = False, grid_scale: float = 1.0)[source]

Live-updating terminal dashboard showing composition state.

Reads bar, section, chord, BPM, and key from the Composition and renders a persistent region to stderr. When grid=True an ASCII pattern grid is rendered above the status line. A custom DisplayLogHandler ensures log messages scroll cleanly above the dashboard.

Example

composition.display(grid=True)
composition.play()

Store composition reference for reading playback state.

Parameters:
  • composition – The Composition instance to read state from.

  • grid – When True, render an ASCII grid of running patterns above the status line.

  • grid_scale – Horizontal zoom factor for the grid (default 1.0). Snapped internally to the nearest integer cols_per_step for uniform marker spacing.

clear_line() None[source]

Erase the entire dashboard region from the terminal.

draw() None[source]

Write the current dashboard to the terminal.

start() None[source]

Install the log handler and activate the display.

Saves existing root logger handlers and replaces them with a DisplayLogHandler that clears/redraws the status line around each log message. Original handlers are restored by stop().

stop() None[source]

Clear the status line and restore original log handlers.

update(_: int = 0) None[source]

Rebuild and redraw the dashboard; called on "bar" and "beat" events.

The integer argument (bar or beat number) is ignored — state is read directly from the composition.

Note: “bar” and “beat” events are emitted as asyncio.create_task at the start of each pulse, but the tasks only execute after _advance_pulse() completes (which includes sending MIDI via _process_pulse()). The display therefore always trails the audio slightly — this is inherent to the architecture and cannot be avoided without restructuring the sequencer loop.

class subsequence.display.DisplayLogHandler(display: Display)[source]

Bases: logging.Handler

Logging handler that clears and redraws the status line around log output.

Installed by Display.start() and removed by Display.stop(). Ensures log messages do not overwrite or corrupt the persistent status line.

Store reference to the display for clear/redraw calls.

emit(record: logging.LogRecord) None[source]

Clear the status line, write the log message, then redraw.

class subsequence.display.GridDisplay(composition: subsequence.composition.Composition, scale: float = 1.0)[source]

Multi-line ASCII grid visualisation of running pattern steps.

Renders one block per pattern showing which grid steps have notes and at what velocity. Drum patterns (those with a drum_note_map) show one row per drum sound; pitched patterns show a single summary row.

Not used directly — instantiated by Display when grid=True.

Store composition reference for reading pattern state.

Parameters:
  • composition – The Composition instance to read running patterns from.

  • scale – Horizontal zoom factor. Snapped to the nearest integer cols_per_step so that all on-grid markers are uniformly spaced. Default 1.0 = one visual column per grid step (current behaviour).

build() None[source]

Rebuild grid lines from the current state of all running patterns.

property line_count: int[source]

Number of terminal lines the grid currently occupies.