spec.md 2.2 KB

Cloud Music Streaming — iOS Port Spec

Overview

Port the Chad Music cloud streaming feature from macOS MixBoard to iOS MixBoard. Users connect to a self-hosted Chad Music REST API server (Tailnet) to browse and stream their cloud music library. Cloud tracks can be mixed into the same playlists as local tracks.

Architecture

New Files (5)

File Location Purpose
ChadMusic.swift Models/ API response models (ChadCategory, ChadAlbum, ChadTrack, ChadStats, ChadCategoryType)
ChadMusicAPIClient.swift Services/ HTTP client — Bearer auth, URL composition, JSON decoding
StreamingPlayer.swift Services/ AVPlayer-based streaming (separate from AVAudioEngine)
KeychainService.swift Services/ Keychain wrapper for API key storage
CloudBrowserView.swift Views/ Browse categories → albums → tracks with play/add-to-playlist

Modified Files (6)

File Changes
Track.swift Add isCloud, cloudStreamPath, cloudTrackId + fromCloud() factory
PlayerViewModel.swift Add StreamingPlayer, dual-source routing, cloud transport
SettingsView.swift Add "Chad Music" section (URL, API key, test connection)
ContentView.swift Add cloud browser sheet trigger
MiniPlayerView.swift Buffering indicator, cloud icon
MixBoardApp.swift Bump DB reset to dbResetV7

How It Works

  1. User enters server URL + API key in Settings → Chad Music
  2. CloudBrowserView fetches categories/albums/tracks from the API
  3. Tapping a cloud track → PlayerViewModel routes to StreamingPlayer (AVPlayer)
  4. "Add to Playlist" creates a Track with isCloud=true in SwiftData
  5. Playing a cloud Track from a playlist → PlayerViewModel detects isCloud, builds stream URL, uses StreamingPlayer
  6. All transport controls (play/pause/seek/skip/next/prev) route based on isCloudPlayback flag

Navigation Pattern

CloudBrowserView is presented as a sheet from a toolbar button in PlaylistListView — consistent with the existing Library/Settings sheet pattern.

DB Migration

Nuclear reset approach (existing pattern): bump dbResetV6dbResetV7 to force schema recreation with new Track fields.