Skip to content

Refactor Player to Programme model #43

@zeevenn

Description

@zeevenn

Parent

#39 — PRD: AI Radio — Host-driven Channel experience with chat timeline

What to build

Add Radio mode to the Player alongside the existing Classic (queue) mode. The Player supports two playback modes that coexist — only one is active at a time.

Architecture Decision: Preserve Classic Mode

The existing playerStore queue logic (addToQueue, insertNext, removeFromQueue, clearQueue, playQueue, setMode, shuffle) is preserved as-is. Radio mode is additive — it does not replace or remove classic playback. Users can still browse the Library and play tracks manually in queue mode.

What to add (Radio mode)

  • A playbackMode: 'radio' | 'classic' discriminator in the player state
  • programme: Segment[] and nowPlayingSegmentIndex: number fields (active only in radio mode)
  • loadProgramme(programme: Programme) → void — called only by the Programme Manager; automatically switches to radio mode
  • onSegmentEnd event (callback or event emitter) so the Programme Manager can react
  • Lookahead: pre-load the next Segment while Now Playing is active. Must handle both file URIs (TrackSegment) and remote TTS URLs (InterlSegment)

Mode switching

  • loadProgramme() → sets playbackMode: 'radio', stops any classic queue playback
  • playTrack() / playQueue() → sets playbackMode: 'classic', stops any radio programme playback
  • Only one mode is active at a time

What NOT to change

  • All existing queue-mutation actions remain
  • PlayMode (single / ordered / shuffle) remains for classic mode
  • PlaybackStore (position, volume, rate) is shared between modes
  • System controls (lock screen, headphone buttons), audio ducking — unchanged
  • Existing tests for classic mode must continue to pass

Acceptance criteria

  • playbackMode field exists and correctly reflects which mode is active
  • Radio mode: playerStore exposes programme, nowPlayingSegmentIndex, and loadProgramme(programme)
  • Radio mode: Player plays a Programme containing both TrackSegments and InterlSegments without errors
  • Radio mode: onSegmentEnd fires after each Segment completes
  • Radio mode: Lookahead pre-loads the next Segment (Track file URI or remote URL) before Now Playing ends
  • Classic mode: all existing queue APIs still work as before
  • Mode switching: loadProgramme() stops classic playback; playTrack()/playQueue() stops radio playback
  • System controls (lock screen / headphones) work in both modes
  • Audio ducking works in both modes
  • Tests pass for: mixed-Segment Programme playback, Segment-end events, and existing classic mode behaviour

Blocked by

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentReady for an AI agent to implement

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions