fix: Fix cross-fade not working when the app was cleared from background
This commit is contained in:
parent
36f15ffe9e
commit
bf165c7eff
6 changed files with 33 additions and 14 deletions
|
@ -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()) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue