Flick 0.21.0-beta.1
0.21.0-beta.1 is a major release, shipped while continuously keeping up with improvements and bug fixing across the app: network sources for self-hosted music servers (Subsonic, Jellyfin, DLNA, WebDAV, Tidal), DLNA and Chromecast casting, an HTTP audio streaming engine, a parametric equalizer refactor, configurable player action buttons, a volume tier system, bit-perfect passthrough mode, USB DAC fixes, and reliability improvements.
Overview
This release adds ten headline features:
- Network sources — stream from Subsonic, Jellyfin/Emby, UPnP/DLNA, WebDAV, and Tidal servers
- Casting — DLNA/UPnP and Google Chromecast support with device discovery
- HTTP audio streaming — ranged HTTP playback with seekable remote streams
- Parametric EQ — variable band types with RBJ biquad coefficients
- Player action buttons — configurable center, top-left, top-right, and bottom actions
- Volume tier system — deterministic volume capability detection with unavailable tier
- Passthrough mode — bit-perfect PCM on direct USB with software gain removed
- USB DAC fixes — Fosi Audio DS2 quirk, 0 Hz readback fix, sample rate guards
- Reliability — wake lock, auto-resume fix, persistent WAV cache, dev log gating
- UI polish — ambient EQ background, USB volume preferences, settings scaling
Highlights
- Network sources: Connect to your own music server. Subsonic, Jellyfin/Emby, UPnP/DLNA MediaServer, WebDAV, and Tidal are all supported through a unified
NetworkSourceServiceabstraction. Each protocol has its own implementation handling auth, album art, and stream resolution. Server credentials are stored inNetworkServerEntity(Isar). A Network Sources screen provides server add/edit/delete with validation and failure banners. Remote songs carrysourceType,remoteId, andremoteServerIdfor sync tracking. A bounded LRUNetworkCacheServicecaches downloads for offline-ready playback. Subsonic prefetch enables gapless crossfade between streamed tracks. Album art resolution is generalized across all protocols. - Casting: A
CastingServiceorchestrates DLNA/UPnP renderers and Google Chromecast. The Chromecast backend usesCastControllerwith cast channels and the Google Cast SDK. The DLNA backend handles renderer discovery and control. A casting settings screen provides device discovery and output routing. A cast button in the player action row lets you start casting from the player. - HTTP streaming: Remote audio plays directly via HTTP with ranged requests using the
ureqRust client. A seekable HTTP media source lets you scrub through network streams. HTTP-first source resolution means network songs stream directly without requiring a local download.streamDescriptoronNetworkSourceServiceenables per-protocol HTTP playback. HTTP play and queue methods are exposed via FFI and integrated intoRustAudioEngineandRustAudioService. Network-source prefetch ensures gapless crossfade between streamed tracks. - Parametric EQ: The graphic EQ was converted to a full parametric EQ with variable band types (peak, low-shelf, high-shelf, low-pass, high-pass) using RBJ biquad coefficients.
EqBandSpecandEqBandTypeFFI types replace the old raw gain arrays. Bands can be added and removed dynamically with animated transitions. The BMT tone controls are preserved alongside the parametric bands. - Player action buttons: The player now has configurable action button slots: center (default: equalizer), top-left, top-right, and the existing bottom pair. Each slot can be assigned any action or set to
noneto hide it. The player layout sheet provides a selector for each slot. Sleep timer is available as an action. All preferences are persisted. - Volume tier system: The old
HwVolumeCapabilityenum was replaced withdetermineVolumeTier(), a pure function that's fully testable. A newunavailabletier handles DACs that report no volume control. A_hwVolumeFailedlie-detector flag catches DACs that claim volume support but fail at runtime. When hardware volume is unavailable, the slider is disabled with an explanatory message. All volume control is now routed throughPlayerServiceas the single source of truth. - Passthrough: The new
audio_set_pipeline_mode_passthroughAPI forces a bit-perfect PCM path on direct USB. Software gain was removed from the passthrough PCM path for true bit-perfect output. Verified with wire audit (supportsVerifiedBitPerfect = true). - USB DAC fixes: A Fosi Audio DS2 quirk was added for its broken clock control (SkipClockValidation). The 0 Hz DAC readback bug is fixed — handles DACs that return zero sample rate. Division-by-zero is guarded when
output_sample_rateis 0. The preferred sample rate is no longer overwritten by the DAC's stored format. Non-finite and negative position/duration values are guarded in audio progress updates. - Reliability: A wake lock keeps the CPU awake during audio playback, preventing sleep-related dropouts. Auto-resume after audio interruptions (phone calls, notifications) is fixed. Converted WAV files are cached persistently across app restarts. A custom artwork cache in the support directory replaces
flutter_cache_manager.dev_eprintln!now prints to the terminal, andAppLogis gated behind developer mode. The audio stream supervisor is enabled on non-Android platforms for desktop testing.
What's New
Network Sources — Self-Hosted Music Servers
- Subsonic, Jellyfin/Emby, UPnP/DLNA, WebDAV, Tidal protocol support
NetworkSourceServiceabstraction with per-protocol implementationsNetworkServerEntityIsar collection for credentials- Network Sources screen with server management
RemoteSourceServicefor network song resolutionNetworkCacheServicewith bounded LRU caching- Remote sync tracking on
SongEntity - Generalized album art resolution
- Subsonic prefetch for gapless playback
Casting — DLNA & Chromecast
- CastingService for DLNA and Chromecast
- Chromecast with CastController and Google Cast SDK
- DLNA/UPnP renderer discovery and control
- Casting settings screen
- Cast button in player action row
HTTP Audio Streaming Engine
- HTTP streaming via ureq with ranged requests
- Seekable HTTP media source
- HTTP-first source resolution
streamDescriptorper protocol- HTTP play/queue via FFI
- Gapless crossfade for streamed tracks
Parametric Equalizer Refactor
- Variable band types with RBJ biquad coefficients
EqBandSpecandEqBandTypeFFI types- Dynamic band add/removal with animations
- BMT tone controls preserved
Player Action Button Layout
- Configurable center action (default: equalizer)
- Top-left and top-right action buttons
noneoption to hide slots- Player layout settings reorganized
Volume Tier System
determineVolumeTier()pure functionunavailabletier_hwVolumeFailedlie-detector flag- Volume slider disabled when unavailable
- Volume routed through PlayerService
Passthrough Pipeline Mode
audio_set_pipeline_mode_passthroughAPI- Software gain removed for bit-perfect
- Wire audit verified
USB DAC Fixes & Quirks
- Fosi Audio DS2 quirk (SkipClockValidation)
- 0 Hz DAC readback fix
- Division-by-zero guard
- Sample rate preservation guards
- Non-finite/negative value guards
Reliability & Performance
- Wake lock during playback
- Auto-resume fix after interruptions
- Persistent WAV cache
- Custom artwork cache
- dev_eprintln to terminal; AppLog gated on dev mode
- Audio stream supervisor on desktop
UI Polish
- Ambient background on equalizer screen
- BlurredSongBackground removed from lists
- USB volume visibility preferences
- Responsive settings icon scaling
- Launcher icons updated
- VIEW intent queries for Android 11+
Files Changed
| Area | Key Paths |
|---|---|
| Network Sources | lib/services/network/, lib/data/entities/network_server_entity.dart, lib/features/settings/screens/network_sources_screen.dart
|
| Casting | lib/services/casting/, lib/features/settings/screens/casting_settings_screen.dart, android/.../CastController
|
| HTTP Streaming | rust/src/audio/http_source.rs, rust/src/audio/audio_api.rs, lib/services/rust_audio_service.dart
|
| Parametric EQ | rust/src/audio/equalizer.rs, rust/src/api/equalizer.rs, lib/features/settings/equalizer_screen.dart
|
| Player Buttons | lib/features/player/screens/full_player_screen.dart, lib/providers/app_preferences_provider.dart
|
| Volume Tier | lib/services/player_service.dart, lib/features/player/widgets/iso_volume_popup.dart
|
| Passthrough | rust/src/audio/android_direct_usb.rs, rust/src/api/audio_api.rs
|
| USB DAC | rust/src/uac2/quirk.rs, rust/src/audio/android_output.rs
|
| Reliability | lib/services/wake_lock_service.dart, rust/src/audio/, lib/services/cache_manager_service.dart
|
| UI | lib/features/settings/, lib/widgets/
|
Upgrading
- Network sources: Settings → Network Sources → Add Server → choose protocol (Subsonic, Jellyfin, DLNA, WebDAV, Tidal)
- Casting: Settings → Casting → Discover Devices, or tap the cast button in the player
- Parametric EQ: add/remove bands dynamically from the equalizer screen
- Player buttons: Settings → Player → Layout to configure center, top, and bottom actions
- Passthrough mode applies automatically on direct USB when supported
- Volume tier detection is automatic — unavailable DACs show a disabled slider with message
- Wake lock is automatic during playback — no configuration needed
- Network songs stream via HTTP by default; enable caching from Network Sources settings