From c888d41d515c103fd7ea7ee119bc787754d3a353 Mon Sep 17 00:00:00 2001 From: Seb3thehacker Date: Sat, 24 Oct 2026 16:47:45 -0700 Subject: [PATCH] media: opening another media app keeps the player on the one still playing Opening AntennaPod while Metrolist played switched Gearslip's player to AntennaPod, so the nav bar lost the music and its buttons drove the wrong app. Leaving an app where nothing started goes back to the one that kept playing. --- .../seb3thehacker/gearslip/car/CarServices.kt | 23 +++++++++++++++++++ .../seb3thehacker/gearslip/car/MediaScreen.kt | 1 + 2 files changed, 24 insertions(+) diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarServices.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarServices.kt index bbde9df..0b33326 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarServices.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarServices.kt @@ -60,6 +60,13 @@ object CarServices { private var navStopped = false private var autoplayPending = false + /** + * The app that was playing when the driver opened another one. Opening an app is only a look + * at its library: until something plays there, the music carries on in this one, so leaving + * the new app's screen goes back to it, as Android Auto does. + */ + private var stillPlaying: MediaApp? = null + fun init(appContext: Context) { context = appContext.applicationContext app.seb3thehacker.gearslip.notify.CarMotion.start(appContext) @@ -130,6 +137,8 @@ object CarServices { val live = phase == CarMedia.Phase.READY || phase == CarMedia.Phase.CONNECTING if (_mediaApp.value?.component == app.component && live) return + val previous = _mediaApp.value + stillPlaying = previous?.takeIf { it.component != app.component && media.now.value.playing && !autoplay } _mediaApp.value = app autoplayPending = autoplay media.connect(app) @@ -151,12 +160,26 @@ object CarServices { return true } + /** + * The media screen closed. If nothing started in the app it showed, go back to the one that + * kept playing meanwhile, so the player and its buttons follow the music you can hear. + */ + fun mediaScreenClosed() { + val back = stillPlaying ?: return + stillPlaying = null + // A track loaded here, even one paused since, means the driver used this app. + if (media.now.value.playing || media.now.value.title.isNotEmpty()) return + app.seb3thehacker.gearslip.GearslipLog.i("media: nothing played in ${_mediaApp.value?.label}, back to ${back.label}") + openMedia(back) + } + /** Closes the media app from the car: stops what it's playing and drops the connection. */ fun closeMedia() { if (media.now.value.playing) media.togglePlay() media.disconnect() _mediaApp.value = null autoplayPending = false + stillPlaying = null } /** Called once the media app is connected: starts playback if that was asked for. */ diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MediaScreen.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MediaScreen.kt index 30f9749..a45587f 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MediaScreen.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MediaScreen.kt @@ -93,6 +93,7 @@ fun MediaScreen(app: MediaApp, onExit: () -> Unit) { // The connection outlives this screen: the home screen's player is the same one. LaunchedEffect(app) { CarServices.openMedia(app) } + androidx.compose.runtime.DisposableEffect(Unit) { onDispose { CarServices.mediaScreenClosed() } } val art = rememberArt(now)