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 mIsInitialized = false
private var hasDataSource: Boolean = false /* Whether first player has DataSource */
private var nextDataSource:String? = null
private var crossFadeAnimator: Animator? = null
override var callbacks: PlaybackCallbacks? = null
private var crossFadeDuration = PreferenceUtil.crossFadeDuration
@ -92,8 +93,10 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
return true
}
override fun seek(whereto: Int): Int {
endFade()
override fun seek(whereto: Int, force: Boolean): Int {
if (force) {
endFade()
}
getNextPlayer()?.stop()
return try {
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 {
return try {
@ -281,7 +289,7 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
fun start() {
job?.cancel()
job = launch {
while (true) {
while (isActive) {
delay(250)
onDurationUpdated(position(), duration())
}
@ -298,10 +306,21 @@ class CrossFadePlayer(context: Context) : LocalPlayback(context) {
getNextPlayer()?.let { player ->
val nextSong = MusicPlayerRemote.nextSong
// 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 ->
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) {
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
* @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 {
mCurrentMediaPlayer.seekTo(whereto)
whereto

View file

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

View file

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

View file

@ -79,7 +79,7 @@ class CastPlayer(castSession: CastSession) : Playback, RemoteMediaClient.Callbac
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())
return whereto
}