[Android] Pause podcasts instead of ducking
Robert Stone
git at videolan.org
Tue May 30 09:37:05 UTC 2023
vlc-android | branch: master | Robert Stone <rhstone at gmail.com> | Mon May 22 20:37:13 2023 -0700| [9d32eafe6c065687251dfccb271a9b71d517f00c] | committer: Robert Stone
Pause podcasts instead of ducking
Fixes #2927
> https://code.videolan.org/videolan/vlc-android/commit/9d32eafe6c065687251dfccb271a9b71d517f00c
---
.../src/org/videolan/vlc/PlaybackService.kt | 8 +++-
.../org/videolan/vlc/util/VLCAudioFocusHelper.kt | 54 ++++++++++++++++++----
2 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
index 32f9962322..e6d75d6476 100644
--- a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
+++ b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
@@ -272,7 +272,11 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
val isPodcastMode: Boolean
@MainThread
- get() = playlistManager.getMediaListSize() == 1 && playlistManager.getCurrentMedia()?.isPodcast == true
+ get() = playlistManager.getMediaListSize() == 1 && isPodcastPlaying
+
+ val isPodcastPlaying: Boolean
+ @MainThread
+ get() = playlistManager.getCurrentMedia()?.isPodcast == true
val speed: Float
@MainThread
@@ -1091,7 +1095,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner, CoroutineSc
pscb.setState(state, time, playlistManager.player.getRate())
pscb.setActiveQueueItemId(playlistManager.currentIndex.toLong())
val repeatType = playlistManager.repeating
- val podcastMode = playlistManager.getMediaListSize() == 1 && playlistManager.getCurrentMedia()?.isPodcast == true
+ val podcastMode = isPodcastMode
if (repeatType != PlaybackStateCompat.REPEAT_MODE_NONE || hasNext())
actions = actions or PlaybackStateCompat.ACTION_SKIP_TO_NEXT
if (repeatType != PlaybackStateCompat.REPEAT_MODE_NONE || hasPrevious() || (isSeekable && !podcastMode))
diff --git a/application/vlc-android/src/org/videolan/vlc/util/VLCAudioFocusHelper.kt b/application/vlc-android/src/org/videolan/vlc/util/VLCAudioFocusHelper.kt
index dba0930e76..7b74d9e76c 100644
--- a/application/vlc-android/src/org/videolan/vlc/util/VLCAudioFocusHelper.kt
+++ b/application/vlc-android/src/org/videolan/vlc/util/VLCAudioFocusHelper.kt
@@ -28,6 +28,8 @@ import android.media.AudioAttributes
import android.media.AudioFocusRequest
import android.media.AudioManager
import android.os.Build
+import android.os.Handler
+import android.os.Looper
import android.util.Log
import androidx.core.content.getSystemService
import org.videolan.libvlc.util.AndroidUtil
@@ -43,9 +45,11 @@ private const val TAG = "VLCAudioFocusHelper"
class VLCAudioFocusHelper(private val service: PlaybackService) {
private lateinit var audioManager: AudioManager
- private lateinit var audioFocusRequest : AudioFocusRequest
+ private lateinit var audioFocusRequest: AudioFocusRequest
private var hasAudioFocus = false
@Volatile
+ private var podcastPlaying = false
+ @Volatile
internal var lossTransient = false
private val audioFocusListener = createOnAudioFocusChangeListener()
@@ -54,7 +58,8 @@ class VLCAudioFocusHelper(private val service: PlaybackService) {
if (!this::audioManager.isInitialized) audioManager = service.getSystemService() ?: return
if (acquire && !service.hasRenderer()) {
- if (!hasAudioFocus) {
+ podcastPlaying = service.isPodcastPlaying
+ if (!hasAudioFocus || podcastPlaying) {
val result = requestAudioFocus()
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
audioManager.setParameters("bgm_state=true")
@@ -82,6 +87,7 @@ class VLCAudioFocusHelper(private val service: PlaybackService) {
.build()
audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setOnAudioFocusChangeListener(audioFocusListener)
+ .setWillPauseWhenDucked(podcastPlaying)
.setAudioAttributes(attributes)
.build()
audioManager.requestAudioFocus(audioFocusRequest)
@@ -92,7 +98,9 @@ class VLCAudioFocusHelper(private val service: PlaybackService) {
private fun createOnAudioFocusChangeListener(): AudioManager.OnAudioFocusChangeListener {
return object : AudioManager.OnAudioFocusChangeListener {
+ private val handler by lazy(LazyThreadSafetyMode.NONE) { Handler(Looper.getMainLooper()) }
private var lossTransientVolume = -1
+ private var lossTime: Long = 0
private var wasPlaying = false
override fun onAudioFocusChange(focusChange: Int) {
@@ -106,24 +114,27 @@ class VLCAudioFocusHelper(private val service: PlaybackService) {
changeAudioFocus(false)
service.pause()
}
+
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
if (BuildConfig.DEBUG) Log.i(TAG, "AUDIOFOCUS_LOSS_TRANSIENT")
// Pause playback
pausePlayback()
}
+
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
if (BuildConfig.DEBUG) Log.i(TAG, "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK")
// Lower the volume
if (service.isPlaying) {
- if (AndroidDevices.isAmazon) {
+ if (AndroidDevices.isAmazon || podcastPlaying) {
pausePlayback()
} else if (service.settings.getBoolean(AUDIO_DUCKING, true)) {
val volume = service.volume
lossTransientVolume = volume
- service.setVolume(volume/3)
+ service.setVolume(volume / 3)
}
}
}
+
AudioManager.AUDIOFOCUS_GAIN -> {
if (BuildConfig.DEBUG) Log.i(TAG, "AUDIOFOCUS_GAIN: ")
// Resume playback
@@ -131,10 +142,15 @@ class VLCAudioFocusHelper(private val service: PlaybackService) {
service.setVolume(lossTransientVolume)
lossTransientVolume = -1
}
- if (lossTransient) {
- if (wasPlaying && service.settings.getBoolean(RESUME_PLAYBACK, true))
- service.play()
- lossTransient = false
+
+ if (lossTransient && wasPlaying) {
+ if (podcastPlaying) {
+ // If the interruption was short just restart playback
+ val deltaTime = System.currentTimeMillis() - lossTime
+ if (deltaTime > 1_000L) schedulePlayback(2_000L) else resumePlayback()
+ } else if (service.settings.getBoolean(RESUME_PLAYBACK, true)) {
+ resumePlayback()
+ }
}
}
}
@@ -144,7 +160,27 @@ class VLCAudioFocusHelper(private val service: PlaybackService) {
if (lossTransient) return
lossTransient = true
wasPlaying = service.isPlaying
- if (wasPlaying) service.pause()
+ if (wasPlaying) {
+ service.pause()
+ lossTime = System.currentTimeMillis()
+ }
+ }
+
+ private fun schedulePlayback(delay: Long) {
+ handler.removeCallbacks(delayedPodcastRunnable)
+ handler.postDelayed(delayedPodcastRunnable, delay)
+ }
+
+ private val delayedPodcastRunnable = Runnable {
+ val position = (service.getTime() - 5_000L).coerceAtLeast(0)
+ resumePlayback()
+ service.seek(position, fromUser = true)
+ service.playlistManager.player.updateProgress(position)
+ }
+
+ private fun resumePlayback() {
+ service.play()
+ lossTransient = false
}
}
}
More information about the Android
mailing list