# BearWave for macOS Native macOS 26 port of the Linux/KDE app BearWave. This repository is the current SwiftUI + AVFoundation version built as a SwiftPM app. The product scope is focused internet radio on macOS. ## Current Scope - Radio Browser integration for Top, Germany, Netherlands, World, search, favorites, recents, and manual stations - Native SwiftUI macOS UI with sidebar, list, detail panel, player bar, settings, and menu bar extra - Station folders for organizing favorites and saved stations - Stream playback through `AVPlayer` - Playback states: connecting, buffering, playing, paused, stopped, failed - Stream metadata display via `AVPlayerItemMetadataOutput` - Station favicons/artwork with local disk cache - Now Playing artwork resolution with fallback chain: metadata lookup, station favicon, app default artwork - Mini Player with `Cmd+M` ## Project Layout - `Package.swift` SwiftPM package with: - `BearWaveCore` shared app logic and resources - `BearWave` app executable - `BearWaveChecks` lightweight verification executable - `Sources/BearWaveApp` App entrypoint and scene setup - `Sources/BearWaveCore` App logic split into: - `App/` high-level app coordinator (`AppModel.swift`) - `Models/` domain models (`RadioStation`, `StationGroup`, `PlaybackStatus`, `PlaybackError`, `StationPage`) - `Services/` Radio Browser client, playback controller, artwork loading, Now Playing artwork resolution - `Stores/` persistence, settings, station library - `Views/` SwiftUI UI (sidebar, list, detail, player bar, settings, menu bar, mini player) - `Support/` resource helpers - `Resources/` localized strings, assets, entitlements placeholder - `Tests/BearWaveChecks` Executable smoke checks for decoding, search normalization, filtering, and library behavior - `script/build_and_run.sh` Local build, bundle, and launch entrypoint ## Build and Run ```bash ./script/build_and_run.sh ``` Useful modes: ```bash ./script/build_and_run.sh --verify ./script/build_and_run.sh --debug ./script/build_and_run.sh --logs ./script/build_and_run.sh --telemetry ``` ## Development Notes - Target platform is `macOS 26` - Preferred workspace is: `/Users/sebastian/Development/radioappmac` - Build with: `swift build --disable-index-store` - Lightweight verification: `CLANG_MODULE_CACHE_PATH=/private/tmp/bearwave-clang-cache swift run --disable-index-store BearWaveChecks` - The generated app bundle lives in: `./dist/BearWave.app` - The run script stages SwiftPM resource bundles and localization directories manually into the app bundle ## Playback and Metadata Notes - Audio playback uses `AVPlayer` - Stream metadata is read through `AVPlayerItemMetadataOutput` - `PlaybackController` exposes explicit playback states instead of a simple play/pause boolean - Some radio streams provide current-song metadata; many do not - `MediaPlayer` is imported with `@preconcurrency` because the app updates `MPNowPlayingInfoCenter` - `MPMediaItemArtwork` is created from a stable `CGImage` request handler - ATS is explicitly opened for media and `http://` streams in the generated app `Info.plist`, otherwise many radio streams do not play ## Persistence Data is stored under native macOS locations: - `Application Support/BearWave/` - `favorites.json` - `manual-stations.json` - `groups.json` - `state.json` - `Caches/BearWave/` - `api_cache/` - artwork cache files The app also tries to import old Linux-style files on first run if present: - `~/.config/bearwave/favorites.json` - `~/.config/bearwave/state.json` ## Current UX Behavior - Search is global against Radio Browser and independent from the current browse page - Search results appear on a dedicated `Search Results` page - Search ranking intentionally filters naive mid-word matches such as `slam` matching `Islamabad` - A right-side detail panel shows station metadata and current stream metadata when available - German localization is active across the app ## Known Technical Edges - The app is currently a SwiftPM-staged `.app`, not an Xcode-managed release app - Debug signing and sandbox behavior are intentionally pragmatic, not release-ready - Resource handling is functional but still tied to the custom staging script ## Suggested Next Work - Improve packaging, signing, and notarization - Add more targeted playback diagnostics per stream failure mode - Expand tests around playback-state transitions and search ranking - Add cache eviction for memory and disk caches - Keep station folders lightweight and radio-focused