audio: with music on Bluetooth, leave the car's media channel closed so the car keeps its Bluetooth source

This commit is contained in:
Seb3thehacker committed 2026-10-15 12:38:06 -07:00
1 parent e8f51f4947
commit 4e71689f8e
2 files changed
+17 -1

No files matched your search

@@ -2,6 +2,7 @@ package app.seb3thehacker.gearslip
import android.os.Build
import app.seb3thehacker.gearslip.audio.AudioLink
import app.seb3thehacker.gearslip.audio.CarAudio
import app.seb3thehacker.gearslip.audio.CarMic
import app.seb3thehacker.gearslip.media.CarMediaStatus
import app.seb3thehacker.gearslip.car.BluetoothAudioCheck
@@ -160,6 +161,7 @@ class GearslipRunner(
synchronized(ackLock) { ackLock.notifyAll() } // free an encoder waiting on an ack
videoSource?.stop()
videoSource = null
CarAudio.openSink = null
audioLink?.close()
audioLink = null
guidanceLink?.close()
@@ -527,7 +529,17 @@ class GearslipRunner(
// as Android Auto does, instead of letting it play on to no one.
onTakenBack = { CarServices.pausePhoneMedia("the car switched to another source") },
)
openChannel(media.serviceId)
if (CarSettings.pipeAudio.value) {
openChannel(media.serviceId)
} else {
// Many cars switch their source to Android Auto the moment this channel opens, which
// cut off music the driver chose to play over Bluetooth. Open it only if they switch.
log.i("music goes over Bluetooth: the media channel stays closed, so the car keeps its own source")
CarAudio.openSink = {
CarAudio.openSink = null
openChannel(media.serviceId)
}
}
}
/** The car's directions channel, where [DirectionsVoice] reads out each turn. */
@@ -44,6 +44,9 @@ object CarAudio {
@Volatile private var link: Link? = null
/** Opens the car's media channel, left closed while music went over Bluetooth; null once open. */
@Volatile var openSink: (() -> Unit)? = null
/** Rate and channel count the capture should use: the car's, or a sensible default. */
val sampleRate get() = link?.sampleRate ?: 48_000
val channels get() = link?.channels ?: 2
@@ -71,6 +74,7 @@ object CarAudio {
when (_capture.value) {
Capture.ON, Capture.ASKING, Capture.DENIED -> return
Capture.OFF -> if (link == null) {
openSink?.invoke()
GearslipLog.i("audio: waiting for the car to offer an audio sink")
} else {
ask()