Fix/aa images and flickering #1

Open
gronod wants to merge 19 commits from fix/aa-images-and-flickering into master
Owner
No description provided.
gronod added 19 commits 2026-10-09 07:16:35 +01:00
Fix imageproxy URLs using wrong port: Dart's Uri.hasPort returns false
for default ports (80/443) even when explicitly specified, causing
fallback to port 8095. Use raw string check instead.

Fix player background flash: use theme surface color as fallback instead
of hardcoded black, and add race guard to color extraction to prevent
stale results on rapid track changes.

Fixes #25, fixes #73

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only show the bottom fade gradient when 4+ rows are enabled, since
with ≤3 rows the content doesn't scroll behind the mini player. Reduce
gradient height to mini player height only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Make checkAndReconnect idempotent: concurrent callers now join the
existing reconnect attempt instead of each creating a new WebSocket
connection. This prevents the cascading "API disposed" errors seen
when Android Auto browses multiple categories simultaneously.

Activate audio session when Sendspin/remote playback starts so Android
delivers audio focus interruption events. Ensemble now pauses when
another app (Spotify, YouTube, etc.) takes audio focus, and resumes
when focus returns.

Remove switch-player button from Android Auto controls (not useful
in car context).

Fixes #25

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ArtworkContentProvider to serve artwork via content:// URIs
  (fixes broken images on many AA head units that reject HTTP URLs)
- Wrap all artUri sites in handler and provider with content:// URIs
- Populate AA play queue after playTracks for queue view support
- Wire updateQueueIndex from provider's _updatePlayerState
- Add error state communication to AA on playback failures
- Rewrite search() to return grouped results (artists, albums, tracks)
- Add playFromSearch() for voice command support ("Play X on Ensemble")
- Add search race condition guard
- Declare SEARCH_SUPPORTED in browsable root extras for search button
- Add invalidateAutoChildren for library add/delete events
- Add cache size limit (50 entries) with LRU eviction for track cache
- Clean up track cache and children subjects in dispose()
- Add audiobook completion status extras (progress bars in AA)
- Add subtitle link extras on track items (tappable artist)
- Reset idle timer on AA browse activity
- Fix PCM player auto-recovery triggering on user-initiated pause

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use updateLocalModeNotification instead of setRemotePlaybackState for
Sendspin/builtin players to avoid conflicting mediaItem.add() calls that
cause artwork flickering. Add fallback to builtin player when last
selected player is unavailable. Extract shared _controls getter, use
MediaControl.custom for switch player, and only claim audio focus on
play transitions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add _trackDisplayArtist() helper to show podcast name, audiobook author,
  or radio station instead of "Unknown Artist" in all notification/AA contexts
- Auto-restore audiobook context from cached data when URI matches
- Set podcast name context when playing episodes from AA browse tree
- Encode podcast ID in episode media IDs for context lookup
- Fix Sendspin pause position using server-synced position tracker instead
  of PCM elapsed time (which resets to 0 each stream)
- Fix Sendspin resume position to use position tracker instead of Duration.zero
- Add 10s seek-back on audiobook resume to compensate for Sendspin buffering
- Populate AA queue for podcast and radio playback via _refreshQueueAfterDelay
- Show podcast name as artist in AA episode browse list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Radio calls now fall back gracefully when the provider doesn't support radio:
playRadio falls back to playing the single track, playArtistRadio falls back
to shuffled artist tracks via search. Direct API calls in context menu and
library screen routed through provider to pick up the fallback. Android Auto
gets a "Smart Shuffle" item at the top of track lists (albums, playlists,
favorites) with a custom sparkle-shuffle icon that attempts radio then falls
back to shuffled playback. Also fixes builtin player selection to avoid
premature fallback before Sendspin registration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Detect Android Auto via car mode broadcasts and getChildren; hide
  switch player button from controls while AA is connected
- Suppress audio auto-resume after becoming noisy / AA disconnect to
  prevent music playing from phone speaker when car turns off
- Rename "Smart Shuffle" to "Start Radio" with radio icon

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Android Auto on projection-mode devices (com.google.android.projection.gearhead)
doesn't trigger ACTION_EXIT_CAR_MODE, so the disconnect was never detected.

- Add DisplayManager.DisplayListener to detect AA disconnect when virtual
  displays are removed (projection mode)
- Add bidirectional method channel so Dart notifies native of AA connection
- Add onAADisconnected callback that force-pauses (not toggles) the player
- Suppress Sendspin stream/start for 2s after disconnect to handle the race
  where the server sends audio before processing our pause command
- Guard interruption begin handler to only pause/toggle when actually playing,
  preventing the interrupted-while-paused -> accidental resume bug

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AA caches the browse tree after first session, so getChildren for the
browsable root is never called on subsequent connects. This meant
_isAndroidAutoConnected was never set, breaking both disconnect detection
(display listener ignored) and playback button refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Don't cache empty artist album results when the library hasn't loaded
yet. On cold start, SyncService may not have finished populating the
album list, causing getArtistAlbumsWithCache to return and cache 0
results permanently until the cache expires.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
List builders for artists, albums, and playlists now await
SyncService.loadFromCache() when data is empty (matching the existing
audiobook pattern). getArtistAlbumsWithCache also falls back to
SyncService when _albums is empty. After library loads (both from cache
and background sync), AA browse children are invalidated so stale
empty results get replaced.

Fixes #25

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without HitTestBehavior.opaque, the GestureDetector only registered
hits on the 20px painted track area instead of the full 48px touch target.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Position tracker, queue persistence, notification timer, and message
receipt logs fired every few seconds, pushing out meaningful events
(AA lifecycle, playback state changes) within minutes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make onPlay/onPause callbacks non-toggle (resumePlayer/pausePlayer
  instead of playPauseSelectedPlayer) so AA buttons work correctly
- Fix interruption guard to treat builtin-active as "was playing" for
  PCM/Sendspin mode where playbackState can be stale
- Keep media session alive during transient idle when PCM is playing
- Only cache non-empty artist album results to prevent stale 0 counts
- Only pause builtin player on AA disconnect (not remote speakers)
- Auto-select builtin player on AA connect broadcast

Fixes #25

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The local _shuffleOn and _repeatMode flags were initialized to off,
so AA buttons always showed disabled on connect even when shuffle/repeat
were actually enabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace boolean toggle with continuous ValueNotifier<double> so bars
slide 1:1 with finger movement instead of snapping. Use
ValueListenableBuilder to avoid full-screen rebuilds on every scroll
frame, and Align(heightFactor) for uniform top-clip instead of
SizedBox squishing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix AA shuffle/repeat buttons and artist images
Build Android APK / Build APK (pull_request) Failing after 23m4s
40a2e2f43a
Shuffle/repeat buttons showed disabled after starting playback because
_refreshQueueAfterDelay only updated queue items without syncing the
shuffle/repeat state. Now syncs both flags and refreshes playback state.

Artist images failed in AA because _autoBuildArtistList used the basic
getImageUrl which returns null for artists without MA metadata images.
Now uses getArtistImageUrlWithFallback which tries external sources.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Some required checks failed
Build Android APK / Build APK (pull_request) Failing after 23m4s
You are not authorized to merge this pull request.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/aa-images-and-flickering:fix/aa-images-and-flickering
git checkout fix/aa-images-and-flickering
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gronod/Ensemble#1