fix: Fix cross-fade not working when the app was cleared from background

This commit is contained in:
Prathamesh More 2023-03-20 00:33:55 +05:30
parent 36f15ffe9e
commit bf165c7eff
6 changed files with 33 additions and 14 deletions

View file

@ -34,6 +34,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
private var durationListener = DurationListener() private var durationListener = DurationListener()
private var mIsInitialized = false private var mIsInitialized = false
private var hasDataSource: Boolean = false /* Whether first player has DataSource */ private var hasDataSource: Boolean = false /* Whether first player has DataSource */
private var nextDataSource:String? = null
private var crossFadeAnimator: Animator? = null private var crossFadeAnimator: Animator? = null
override var callbacks: PlaybackCallbacks? = null override var callbacks: PlaybackCallbacks? = null
private var crossFadeDuration = PreferenceUtil.crossFadeDuration private var crossFadeDuration = PreferenceUtil.crossFadeDuration
@ -92,8 +93,10 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
return true return true
} }
override fun seek(whereto: Int): Int { override fun seek(whereto: Int, force: Boolean): Int {
endFade() if (force) {
endFade()
}
getNextPlayer()?.stop() getNextPlayer()?.stop()
return try { return try {
getCurrentPlayer()?.seekTo(whereto) getCurrentPlayer()?.seekTo(whereto)
@ -143,7 +146,12 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
} }
} }
override fun setNextDataSource(path: String?) {} override fun setNextDataSource(path: String?) {
// Store the next song path in nextDataSource, we'll need this just in case
// if the user closes the app, then we can't get the nextSong from musicService
// As MusicPlayerRemote won't have access to the musicService
nextDataSource = path
}
override fun setAudioSessionId(sessionId: Int): Boolean { override fun setAudioSessionId(sessionId: Int): Boolean {
return try { return try {
@ -281,7 +289,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
fun start() { fun start() {
job?.cancel() job?.cancel()
job = launch { job = launch {
while (true) { while (isActive) {
delay(250) delay(250)
onDurationUpdated(position(), duration()) onDurationUpdated(position(), duration())
} }
@ -298,10 +306,21 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
getNextPlayer()?.let { player -> getNextPlayer()?.let { player ->
val nextSong = MusicPlayerRemote.nextSong val nextSong = MusicPlayerRemote.nextSong
// Switch to other player (Crossfade) only if next song exists // Switch to other player (Crossfade) only if next song exists
if (nextSong != null) { // If we get an empty song it's can be because the app was cleared from background
// And MusicPlayerRemote don't have access to MusicService
if (nextSong != null && nextSong != Song.emptySong) {
nextDataSource = null
setDataSourceImpl(player, nextSong.uri.toString()) { success -> setDataSourceImpl(player, nextSong.uri.toString()) { success ->
if (success) switchPlayer() if (success) switchPlayer()
} }
}
// So we have to use the previously stored nextDataSource value
else if (!nextDataSource.isNullOrEmpty()) {
setDataSourceImpl(player, nextDataSource!!) { success ->
if (success) switchPlayer()
nextDataSource = null
}
} }
} }
} }
@ -335,7 +354,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
} }
} }
internal fun crossFadeScope(): CoroutineScope = CoroutineScope(Job() + Dispatchers.Main) internal fun crossFadeScope(): CoroutineScope = CoroutineScope(Job() + Dispatchers.Default)
fun MediaPlayer.setPlaybackSpeedPitch(speed: Float, pitch: Float) { fun MediaPlayer.setPlaybackSpeedPitch(speed: Float, pitch: Float) {
if (hasMarshmallow()) { if (hasMarshmallow()) {

View file

@ -200,7 +200,7 @@ class MultiPlayer(context: Context) : LocalPlayback(context) {
* @param whereto The offset in milliseconds from the start to seek to * @param whereto The offset in milliseconds from the start to seek to
* @return The offset in milliseconds from the start to seek to * @return The offset in milliseconds from the start to seek to
*/ */
override fun seek(whereto: Int): Int { override fun seek(whereto: Int, force: Boolean): Int {
return try { return try {
mCurrentMediaPlayer.seekTo(whereto) mCurrentMediaPlayer.seekTo(whereto)
whereto whereto

View file

@ -707,7 +707,7 @@ class MusicService : MediaBrowserServiceCompat(),
|| repeatMode == REPEAT_MODE_NONE && isLastTrack || repeatMode == REPEAT_MODE_NONE && isLastTrack
) { ) {
notifyChange(PLAY_STATE_CHANGED) notifyChange(PLAY_STATE_CHANGED)
seek(0) seek(0, false)
if (pendingQuit) { if (pendingQuit) {
pendingQuit = false pendingQuit = false
quit() quit()
@ -727,7 +727,7 @@ class MusicService : MediaBrowserServiceCompat(),
if (pendingQuit || repeatMode == REPEAT_MODE_NONE && isLastTrack) { if (pendingQuit || repeatMode == REPEAT_MODE_NONE && isLastTrack) {
playbackManager.setNextDataSource(null) playbackManager.setNextDataSource(null)
pause(false) pause(false)
seek(0) seek(0, false)
if (pendingQuit) { if (pendingQuit) {
pendingQuit = false pendingQuit = false
quit() quit()
@ -974,9 +974,9 @@ class MusicService : MediaBrowserServiceCompat(),
} }
@Synchronized @Synchronized
fun seek(millis: Int): Int { fun seek(millis: Int, force: Boolean = true): Int {
return try { return try {
val newPosition = playbackManager.seek(millis) val newPosition = playbackManager.seek(millis, force)
throttledSeekHandler?.notifySeek() throttledSeekHandler?.notifySeek()
newPosition newPosition
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -78,7 +78,7 @@ class PlaybackManager(val context: Context) {
} }
} }
fun seek(millis: Int): Int = playback!!.seek(millis) fun seek(millis: Int, force: Boolean): Int = playback!!.seek(millis, force)
fun setDataSource( fun setDataSource(
song: Song, song: Song,

View file

@ -45,7 +45,7 @@ interface Playback {
fun position(): Int fun position(): Int
fun seek(whereto: Int): Int fun seek(whereto: Int, force: Boolean): Int
fun setVolume(vol: Float): Boolean fun setVolume(vol: Float): Boolean

View file

@ -79,7 +79,7 @@ class CastPlayer(castSession: CastSession) : Playback, RemoteMediaClient.Callbac
return remoteMediaClient?.approximateStreamPosition?.toInt() ?: 0 return remoteMediaClient?.approximateStreamPosition?.toInt() ?: 0
} }
override fun seek(whereto: Int): Int { override fun seek(whereto: Int, force: Boolean): Int {
remoteMediaClient?.seek(MediaSeekOptions.Builder().setPosition(whereto.toLong()).build()) remoteMediaClient?.seek(MediaSeekOptions.Builder().setPosition(whereto.toLong()).build())
return whereto return whereto
} }