# 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
