v2026.06.03 — Media3 like button + Bluetooth/UPnP picker + system playlist daily rotation #77

Merged
bvandeusen merged 29 commits from dev into main 2026-06-03 14:09:23 -04:00
Showing only changes of commit e69a5204db - Show all commits
@@ -3,6 +3,8 @@ package com.fabledsword.minstrel.player
import android.content.ComponentName
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.media3.common.MediaItem
import androidx.media3.common.MediaMetadata
import androidx.media3.common.Player
@@ -187,9 +189,26 @@ class PlayerController @Inject constructor(
val controller = mediaController ?: return
queueRefs = tracks
val items = tracks.map { it.toMediaItem(source) }
controller.setMediaItems(items, initialIndex, /* startPositionMs = */ 0L)
controller.prepare()
if (autoplay) controller.play()
// Drift #562 cold-boot resume calls this from a non-Main suspend
// context after awaitReady() unblocks (ResumeController launches
// on Dispatchers.Default by the time it reaches us). MediaController
// enforces application-thread access and throws
// IllegalStateException otherwise — post to its applicationLooper
// if we're already there, run directly to avoid the re-dispatch
// latency UI callers depend on.
runOnControllerThread(controller) {
controller.setMediaItems(items, initialIndex, /* startPositionMs = */ 0L)
controller.prepare()
if (autoplay) controller.play()
}
}
private fun runOnControllerThread(controller: MediaController, block: () -> Unit) {
if (Looper.myLooper() == controller.applicationLooper) {
block()
} else {
Handler(controller.applicationLooper).post(block)
}
}
/**