# GUI Architecture

This document defines the high-level architectural decisions for the real-time display system.
The display must provide smooth visual feedback for metronome position, column progress, and track states
while maintaining responsive updates from OSC messages without blocking the rendering thread.

## Overview

The GUI architecture uses two threads to maintain responsive visual updates.
The OSC receiver thread handles incoming state messages from the audio engine and updates shared state.
The GUI thread runs the egui rendering loop and interpolates time-based animations independently.

These subsystems communicate through Tokio watch channels for efficient state synchronization.
The audio engine acts as an OSC server, with the display connecting as a client and automatically reconnecting on failures.

```mermaid
graph LR
    AudioEngine[Audio Engine<br/>OSC Server<br/>Unix Socket]
    OSCThread[OSC Receiver Thread<br/>tokio + rosc<br/>State Updates]
    GUIThread[GUI Thread<br/>egui Rendering<br/>Animation Interpolation]
    
    AudioEngine -->|OSC Messages| OSCThread
    OSCThread -->|Watch Channel| GUIThread
    
    subgraph "Display Process"
        OSCThread
        GUIThread
    end
```

The system receives state updates through standardized OSC messages and renders them using a hierarchical state structure.
Time-critical animations like metronome movement and progress bars use local interpolation to maintain smooth 60fps updates
independent of the OSC message frequency.

## Technology Stack

The display uses egui as the immediate mode GUI framework,
providing excellent performance for real-time updates and straightforward integration with Rust's async ecosystem.

**Core Libraries:**
- **egui**: Immediate mode GUI framework for rendering
- **tokio**: Async runtime for OSC message handling
- **rosc**: OSC message parsing and Unix socket communication
- **tokio::sync::watch**: Lock-free state sharing between threads

## Threading Architecture

### OSC Receiver Thread
The OSC receiver thread manages the Unix socket connection to the audio engine and processes incoming state messages.
This thread runs a tokio async loop that handles connection establishment, message parsing, and state updates.

### GUI Thread
The GUI thread owns the egui context and handles all rendering operations.
This thread polls the watch channel receiver for state changes and triggers repaints when updates arrive.
Time interpolation for smooth animations happens during the render loop using stored timestamps and elapsed time calculations.

## State Management

### Hierarchical State Structure
The display state mirrors the audio engine's organization to maintain consistency and simplify message parsing.

```
DisplayState
├── global
│   ├── mode: OperationMode (Menu | Performance)
│   ├── tempo: f32 (BPM)
│   ├── selected_cell: (usize, usize)
│   ├── click_enabled: bool
│   ├── click_volume: f32
│   └── master_volume: f32
├── columns: [ColumnState; 5]
│   ├── beats: usize (Total beats, 0 = not set)
│   ├── current_beat: usize (1-based position)
│   └── tracks: [TrackState; 5]
│       ├── state: TrackDisplayState (Empty | Ready | Recording | Playing | Solo)
│       └── volume: f32
└── metronome
    ├── position: f32 (0.0-1.0 within current beat)
    └── timestamp: Instant (When received)
```

### State Updates
The OSC receiver thread modifies the state directly based on incoming messages and sends the complete updated state through the watch channel.
This approach ensures atomic updates and eliminates complex synchronization logic.

## OSC Message Processing

### Message Parsing Flow
Incoming OSC messages map directly to state field updates using a straightforward parsing pipeline.
Initial connection triggers a complete state dump from the audio engine using the same message format as regular updates.

### Time-Sensitive Messages
Metronome position messages include timestamp capture to enable smooth interpolation in the GUI thread.
This allows the display to show fluid metronome movement despite receiving position updates at MIDI PPQN rate rather than display refresh rate.

## Time Interpolation Strategy

### Metronome Animation
The metronome requires smooth movement between received position updates to maintain visual continuity.
Time interpolation happens during the render loop by calculating elapsed time since the last position update and advancing the visual position accordingly.
This maintains frame-rate independence and ensures smooth animations regardless of system load.

### Column Progress Animation
Column progress bars use similar interpolation to show smooth advancement between beat boundaries.
The current beat position provides the discrete timing reference, with interpolation filling the gaps for fluid visual feedback.

## Connection Management

### Client Connection Pattern
The display connects to the audio engine's Unix socket server and handles connection lifecycle automatically.
Connection failures trigger retry attempts to avoid overwhelming the system during startup sequences.

### Error States and Recovery
The GUI displays connection status to provide user feedback during system startup or audio engine restarts.
Connection recovery happens transparently in the background, with the GUI resuming normal operation once the OSC stream resumes.

## Process Lifecycle

The display process operates independently of the audio engine, connecting as needed and handling temporary disconnections gracefully.
External process management tools handle startup coordination and service lifecycle,
keeping the display implementation focused on its core visualization responsibilities.