Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -815,19 +815,22 @@ class LibrePodsService: Service() {
when (state.conversationAwarenessState) {
1 -> {
MediaController.startSpeaking()
MediaController.setVolume(
MediaController.duckVolume(
deviceSettings.conversationAwarenessVolume.toInt()
)
}

2 -> {
MediaController.setVolume(
// 1 and 2 both mean "started speaking"; only the first one records
// the volume to come back to, so a sequence starting at 2 still restores
MediaController.startSpeaking()
MediaController.duckVolume(
deviceSettings.conversationAwarenessReducedVolume.toInt()
)
}

3 -> {
MediaController.setVolume(
MediaController.duckVolume(
deviceSettings.conversationAwarenessVolume.toInt()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,18 @@ object MediaController {
)
}

/**
* Conversation awareness levels are a fixed share of the maximum volume, so on their own they
* can sit *above* what the user was listening at. Never let ducking raise the volume.
*/
@Synchronized
fun duckVolume(volumePercent: Int) {
val current = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
val ceiling = initialVolume ?: current
smoothVolumeTransition(current, minOf(maxVolume * volumePercent / 100, ceiling))
}

@Synchronized
fun startSpeaking() {
if (initialVolume == null) {
Expand All @@ -381,14 +393,21 @@ object MediaController {
initialVolume = null
}

// Bumped by every transition; a stale one stops instead of finishing. Without this, a ramp still
// running towards the ducked level could finish after the restore and leave the volume there.
@Volatile
private var volumeTransitionGeneration = 0

private fun smoothVolumeTransition(fromVolume: Int, toVolume: Int) {
Log.d("MediaController", "Smooth volume transition from $fromVolume to $toVolume")
val step = if (fromVolume < toVolume) 1 else -1
val delay = 50L
var currentVolume = fromVolume
val generation = ++volumeTransitionGeneration

handler.post(object : Runnable {
override fun run() {
if (generation != volumeTransitionGeneration) return
if (currentVolume != toVolume) {
currentVolume += step
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume, 0)
Expand Down