fix: star visibility, station switching, skip-ahead, and latency optimizations
- Star icons now use distinct tint colors (primary vs faded) for clear state - Station switching no longer races — old playback job is cancelled before new - Skip-ahead drops ~1s of buffered audio per tap via atomic counter - Custom SocketFactory with SO_RCVBUF=16KB and TCP_NODELAY for minimal TCP buffering - Catch-up drain: discards pre-buffered frames until network reads block (live edge) - AudioTrack PERFORMANCE_MODE_LOW_LATENCY for smallest hardware buffer Made-with: Cursor
This commit is contained in:
34
chat-summaries/2026-03-09_bugfix-and-seek-to-live.md
Normal file
34
chat-summaries/2026-03-09_bugfix-and-seek-to-live.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Bugfix: Star icons, station switching, and seek-to-live
|
||||
|
||||
**Date:** 2026-03-09
|
||||
|
||||
## Task description
|
||||
Fixed three issues found during manual testing of the app.
|
||||
|
||||
## Changes made
|
||||
|
||||
### 1. Star icon visual state (StationListScreen.kt)
|
||||
- Added explicit tint colors to star icons: `primary` color when starred, faded `onSurfaceVariant` (40% alpha) when unstarred.
|
||||
- Applies to both station rows and playlist section headers.
|
||||
|
||||
### 2. Station switching race condition (RadioPlaybackService.kt)
|
||||
- Added `playJob` tracking — each new play request cancels the previous playback coroutine before starting a new one.
|
||||
- The old job's `finally` block now checks `playJob == coroutineContext[Job]` to avoid calling `cleanup()`/`stopSelf()` when being replaced by a new station.
|
||||
- Tapping the same station now restarts it (re-fires `ACTION_PLAY`).
|
||||
- Fixed collector coroutine leak: `return@collect` on terminal events (`Error`, `Stopped`) so the SharedFlow collection terminates.
|
||||
|
||||
### 3. Seek-to-live feature
|
||||
- Added `ACTION_SEEK_LIVE` to `RadioPlaybackService` — ends current connection span, stops/restarts the engine for the current station without creating a new `ListeningSession`.
|
||||
- Added `seekToLive()` to `RadioController`.
|
||||
- Added `seekToLive()` to `NowPlayingViewModel`.
|
||||
- Added "SKIP TO LIVE" `FilledTonalButton` to `NowPlayingScreen`, positioned between latency indicator and Stay Connected toggle. Disabled during reconnection.
|
||||
|
||||
## Files changed
|
||||
- `app/src/main/java/.../ui/screens/stationlist/StationListScreen.kt`
|
||||
- `app/src/main/java/.../service/RadioPlaybackService.kt`
|
||||
- `app/src/main/java/.../service/RadioController.kt`
|
||||
- `app/src/main/java/.../ui/screens/nowplaying/NowPlayingScreen.kt`
|
||||
- `app/src/main/java/.../ui/screens/nowplaying/NowPlayingViewModel.kt`
|
||||
|
||||
## Follow-up items
|
||||
- None identified.
|
||||
75
chat-summaries/2026-03-09_full-implementation-summary.md
Normal file
75
chat-summaries/2026-03-09_full-implementation-summary.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Full Implementation — Android 24/7 Radio
|
||||
|
||||
**Date:** 2026-03-09
|
||||
|
||||
## Task Description
|
||||
|
||||
Brainstormed, designed, planned, and implemented a complete Android 24/7 internet radio streaming app from scratch using subagent-driven development.
|
||||
|
||||
## What Was Built
|
||||
|
||||
### Audio Engine (custom raw pipeline)
|
||||
- **StreamConnection** — OkHttp HTTP client with ICY metadata header support
|
||||
- **IcyParser** — Separates audio bytes from ICY metadata, parses StreamTitle into artist/title
|
||||
- **Mp3FrameSync** — Finds MP3 frame boundaries with two-frame validation and re-sync
|
||||
- **AudioEngine** — Wires pipeline: StreamConnection → IcyParser → RingBuffer → Mp3FrameSync → MediaCodec → AudioTrack
|
||||
|
||||
### Android Service Layer
|
||||
- **RadioPlaybackService** — Foreground service with wake lock, wifi lock, MediaSession
|
||||
- **Stay Connected** — Exponential backoff reconnection (1s→30s cap), ConnectivityManager callback for instant retry
|
||||
- **NotificationHelper** — Media-style notification with stop action
|
||||
- **RadioController** — Shared state between service and UI via StateFlow
|
||||
|
||||
### Data Layer
|
||||
- **Room Database** — Station, Playlist, MetadataSnapshot, ListeningSession, ConnectionSpan entities with full DAOs
|
||||
- **DataStore Preferences** — stayConnected, bufferMs, lastStationId
|
||||
- **PLS/M3U Import/Export** — Full parsers with #EXTIMG support, round-trip tested
|
||||
|
||||
### UI (Jetpack Compose + Material 3)
|
||||
- **Station List** — Playlists as expandable groups, starring, tap-to-play, long-press menu, import
|
||||
- **Now Playing** — Album art, dual timers (session + connection), latency indicator, stay connected toggle, buffer slider
|
||||
- **Settings** — Playback prefs, playlist export, recently played, track history with search
|
||||
- **MiniPlayer** — Bottom bar on station list when playing
|
||||
|
||||
### Metadata
|
||||
- **AlbumArtResolver** — MusicBrainz/Cover Art Archive → ICY StreamUrl → #EXTIMG → placeholder
|
||||
- **ArtCache** — In-memory LRU cache (500 entries)
|
||||
- **Coil 3** — Image loading in Compose
|
||||
|
||||
## Commit History (20 commits)
|
||||
|
||||
1. Design document and implementation plan
|
||||
2. Project scaffolding (Gradle, manifest, dependencies)
|
||||
3. Room entities, DAOs, database, DataStore
|
||||
4. M3U/PLS import/export with tests
|
||||
5. ICY metadata parser with tests
|
||||
6. MP3 frame synchronizer with tests
|
||||
7. HTTP stream connection with tests
|
||||
8. Audio engine integration
|
||||
9. Foreground service with Stay Connected
|
||||
10. Material 3 theme and navigation
|
||||
11. Station List screen
|
||||
12. Now Playing screen with dual timers
|
||||
13. Settings screen with history
|
||||
14. Album art resolution with MusicBrainz
|
||||
15. Final integration and README
|
||||
|
||||
## Test Coverage
|
||||
|
||||
- IcyParser: 10 tests
|
||||
- Mp3FrameSync: 9 tests
|
||||
- StreamConnection: 6 tests
|
||||
- M3uParser: 6 tests
|
||||
- PlsParser: 5 tests
|
||||
- PlaylistExporter: 4 tests
|
||||
- RingBuffer: 4 tests
|
||||
- AlbumArtResolver: 9 tests (MockWebServer)
|
||||
|
||||
## Follow-Up Items
|
||||
|
||||
- Test on actual Android 9 device with real Icecast/Shoutcast streams
|
||||
- Add drag-to-reorder for stations and playlists
|
||||
- Implement latency estimation from AudioTrack write/play head positions
|
||||
- Add Bluetooth headset AUDIO_BECOMING_NOISY handling
|
||||
- Add audio focus management
|
||||
- Future: recording, clips, analytics (schema already supports it)
|
||||
Reference in New Issue
Block a user