mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-10 16:02:25 +01:00
voice: "pause" keeps the music paused after the mic lets go
This commit is contained in:
1 parent
62b1835444
commit
01a41c01c8
3 files changed
+31
-5
No files matched your search
@@ -2,6 +2,7 @@ package app.seb3thehacker.gearslip.car
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import app.seb3thehacker.gearslip.media.CarMedia
|
import app.seb3thehacker.gearslip.media.CarMedia
|
||||||
|
import app.seb3thehacker.gearslip.speech.VoiceFocus
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -215,7 +216,8 @@ object AssistantCommands {
|
|||||||
val media = CarServices.media
|
val media = CarServices.media
|
||||||
return when {
|
return when {
|
||||||
"pause" in heard || heard.startsWith("stop") || heard == "quiet" || heard == "shut up" -> {
|
"pause" in heard || heard.startsWith("stop") || heard == "quiet" || heard == "shut up" -> {
|
||||||
if (media.now.value.playing) media.togglePlay()
|
media.pause()
|
||||||
|
VoiceFocus.afterRelease { media.pause() }
|
||||||
"Paused."
|
"Paused."
|
||||||
}
|
}
|
||||||
"resume" in heard || "unpause" in heard || heard in RESUME_PHRASES ||
|
"resume" in heard || "unpause" in heard || heard in RESUME_PHRASES ||
|
||||||
|
|||||||
@@ -433,6 +433,12 @@ class CarMedia(private val context: Context) {
|
|||||||
val controls = controller?.transportControls ?: return
|
val controls = controller?.transportControls ?: return
|
||||||
if (_now.value.playing) controls.pause() else controls.play()
|
if (_now.value.playing) controls.pause() else controls.play()
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Pauses whatever the app thinks it's doing. Voice pauses the music to listen, so by the time
|
||||||
|
* "pause" is heard the app already looks stopped; a toggle did nothing and the song came back
|
||||||
|
* as soon as the microphone let go. A real pause tells the app to stay stopped.
|
||||||
|
*/
|
||||||
|
fun pause() = controller?.transportControls?.pause()
|
||||||
fun next() = controller?.transportControls?.skipToNext()
|
fun next() = controller?.transportControls?.skipToNext()
|
||||||
fun previous() = controller?.transportControls?.skipToPrevious()
|
fun previous() = controller?.transportControls?.skipToPrevious()
|
||||||
fun seek(ms: Long) = controller?.transportControls?.seekTo(ms)
|
fun seek(ms: Long) = controller?.transportControls?.seekTo(ms)
|
||||||
|
|||||||
@@ -19,17 +19,35 @@ import app.seb3thehacker.gearslip.GearslipLog
|
|||||||
object VoiceFocus {
|
object VoiceFocus {
|
||||||
|
|
||||||
private const val RELEASE_DELAY_MS = 1_500L
|
private const val RELEASE_DELAY_MS = 1_500L
|
||||||
|
private const val AFTER_RELEASE_MS = 300L
|
||||||
|
|
||||||
private val main = Handler(Looper.getMainLooper())
|
private val main = Handler(Looper.getMainLooper())
|
||||||
private var request: AudioFocusRequest? = null
|
private var request: AudioFocusRequest? = null
|
||||||
private var audio: AudioManager? = null
|
private var audio: AudioManager? = null
|
||||||
private var holders = 0
|
private var holders = 0
|
||||||
|
private val afterRelease = mutableListOf<() -> Unit>()
|
||||||
|
|
||||||
private val releaseNow = Runnable {
|
private val releaseNow = Runnable {
|
||||||
val r = request ?: return@Runnable
|
request?.let { r ->
|
||||||
audio?.abandonAudioFocusRequest(r)
|
audio?.abandonAudioFocusRequest(r)
|
||||||
request = null
|
request = null
|
||||||
GearslipLog.i("voice: gave audio focus back")
|
GearslipLog.i("voice: gave audio focus back")
|
||||||
|
}
|
||||||
|
val pending = afterRelease.toList()
|
||||||
|
afterRelease.clear()
|
||||||
|
// Just after the music app has had its focus back and acted on it.
|
||||||
|
if (pending.isNotEmpty()) main.postDelayed({ pending.forEach { it() } }, AFTER_RELEASE_MS)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs [action] once the music has its focus back, or now if Gearslip isn't holding it.
|
||||||
|
* Metrolist takes a pause sent while it's held as nothing and resumes when focus returns,
|
||||||
|
* so "pause" sends it again from here.
|
||||||
|
*/
|
||||||
|
fun afterRelease(action: () -> Unit) {
|
||||||
|
main.post {
|
||||||
|
if (request == null && holders == 0) action() else afterRelease += action
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Pauses the music until a matching [release]. Safe from any thread. */
|
/** Pauses the music until a matching [release]. Safe from any thread. */
|
||||||
|
|||||||
Reference in new issue
Block a user