mirror of
https://github.com/clangen/musikcube.git
synced 2025-02-11 09:40:26 +00:00
More aggressively release playback WakeLock after stream downloads have
finished. The WakeLock will be re-acquired when subsequent songs are pre-loading (or loading).
This commit is contained in:
parent
fd7fa4d6a9
commit
6bf1dceac1
@ -66,6 +66,7 @@
|
||||
<action android:name="io.casey.musikcube.remote.WAKE_UP" />
|
||||
<action android:name="io.casey.musikcube.remote.SHUT_DOWN" />
|
||||
<action android:name="io.casey.musikcube.remote.SLEEP" />
|
||||
<action android:name="io.casey.musikcube.remote.DISCONNECT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
|
@ -253,10 +253,10 @@ class ExoPlayerWrapper : PlayerWrapper() {
|
||||
if (StreamProxy.ENABLED) {
|
||||
if (StreamProxy.isCached(this.originalUri!!)) {
|
||||
percentAvailable = 100
|
||||
|
||||
if (originalUri != null && metadata != null) {
|
||||
PlayerWrapper.storeOffline(originalUri!!, metadata!!)
|
||||
}
|
||||
onFileCached()
|
||||
}
|
||||
else {
|
||||
StreamProxy.registerCacheListener(this.cacheListener, this.originalUri!!)
|
||||
@ -275,11 +275,11 @@ class ExoPlayerWrapper : PlayerWrapper() {
|
||||
|
||||
private val cacheListener = CacheListener { _: File, _: String, percent: Int ->
|
||||
percentAvailable = percent
|
||||
|
||||
if (percentAvailable >= 100) {
|
||||
if (originalUri != null && metadata != null) {
|
||||
storeOffline(originalUri!!, metadata!!)
|
||||
}
|
||||
onFileCached()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,6 +222,7 @@ class MediaPlayerWrapper : PlayerWrapper() {
|
||||
if (originalUri != null && metadata != null) {
|
||||
PlayerWrapper.storeOffline(originalUri!!, metadata!!)
|
||||
}
|
||||
onFileCached()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,13 +27,14 @@ abstract class PlayerWrapper {
|
||||
Disposed
|
||||
}
|
||||
|
||||
private var listener: ((PlayerWrapper, State) -> Unit)? = null
|
||||
private var stateChangedListener: ((PlayerWrapper, State) -> Unit)? = null
|
||||
private var fileCachedListener: ((PlayerWrapper) -> Unit)? = null
|
||||
|
||||
var state = State.Stopped
|
||||
protected set(state) {
|
||||
if (this.state != state) {
|
||||
field = state
|
||||
listener?.invoke(this,state)
|
||||
stateChangedListener?.invoke(this,state)
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,10 +49,21 @@ abstract class PlayerWrapper {
|
||||
abstract val duration: Int
|
||||
abstract val bufferedPercent: Int
|
||||
|
||||
open fun setOnStateChangedListener(listener: ((PlayerWrapper, State) -> Unit)?) {
|
||||
fun setOnStateChangedListener(listener: ((PlayerWrapper, State) -> Unit)?) {
|
||||
Preconditions.throwIfNotOnMainThread()
|
||||
this.listener = listener
|
||||
this.listener?.invoke(this, this.state)
|
||||
this.stateChangedListener = listener
|
||||
this.stateChangedListener?.invoke(this, this.state)
|
||||
}
|
||||
|
||||
fun setOnFileCachedListener(listener: ((PlayerWrapper) -> Unit)?) {
|
||||
this.fileCachedListener = listener
|
||||
onFileCached()
|
||||
}
|
||||
|
||||
protected fun onFileCached() {
|
||||
if (this.bufferedPercent >= 100) {
|
||||
this.fileCachedListener?.invoke(this)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -11,6 +11,7 @@ import android.util.Log
|
||||
import io.casey.musikcube.remote.Application
|
||||
import io.casey.musikcube.remote.R
|
||||
import io.casey.musikcube.remote.ui.model.TrackListSlidingWindow
|
||||
import io.casey.musikcube.remote.util.Debouncer
|
||||
import io.casey.musikcube.remote.util.Strings
|
||||
import io.casey.musikcube.remote.websocket.Messages
|
||||
import io.casey.musikcube.remote.websocket.Prefs
|
||||
@ -25,6 +26,8 @@ import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class StreamingPlaybackService(context: Context) : PlaybackService {
|
||||
private enum class WakeLockDebounce { Wake, Sleep }
|
||||
|
||||
@Inject lateinit var wss: WebSocketService
|
||||
private val prefs: SharedPreferences = context.getSharedPreferences(Prefs.NAME, Context.MODE_PRIVATE)
|
||||
private val listeners = HashSet<() -> Unit>()
|
||||
@ -107,6 +110,14 @@ class StreamingPlaybackService(context: Context) : PlaybackService {
|
||||
return startedNext
|
||||
}
|
||||
|
||||
fun isCurrentCached(): Boolean {
|
||||
return currentPlayer == null || (currentPlayer?.bufferedPercent ?: 0) >= 100
|
||||
}
|
||||
|
||||
fun isNextCached(): Boolean {
|
||||
return nextPlayer == null || (nextPlayer?.bufferedPercent ?: 0) >= 100
|
||||
}
|
||||
|
||||
fun reset(wrapper: PlayerWrapper?) {
|
||||
if (wrapper != null) {
|
||||
wrapper.setOnStateChangedListener(null)
|
||||
@ -451,7 +462,40 @@ class StreamingPlaybackService(context: Context) : PlaybackService {
|
||||
}
|
||||
}
|
||||
|
||||
private val onCurrentPlayerStateChanged = { _: PlayerWrapper, state: PlayerWrapper.State ->
|
||||
private fun wakeUpIfPlayerNeedsConnectivity(player: PlayerWrapper) {
|
||||
when (player.state) {
|
||||
PlayerWrapper.State.Preparing,
|
||||
PlayerWrapper.State.Prepared,
|
||||
PlayerWrapper.State.Playing,
|
||||
PlayerWrapper.State.Buffering -> {
|
||||
sleepWakeDebouncer.call(WakeLockDebounce.Wake)
|
||||
}
|
||||
else -> { }
|
||||
}
|
||||
}
|
||||
|
||||
private val onPlayerFileCached = { _: PlayerWrapper ->
|
||||
if (StreamProxy.ENABLED) {
|
||||
if (playContext.isCurrentCached() && playContext.isNextCached()) {
|
||||
sleepWakeDebouncer.call(WakeLockDebounce.Sleep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val sleepWakeDebouncer = object : Debouncer<WakeLockDebounce>(500) {
|
||||
override fun onDebounced(last: WakeLockDebounce?) {
|
||||
if ((last ?: WakeLockDebounce.Sleep) == WakeLockDebounce.Sleep) {
|
||||
SystemService.sleep()
|
||||
}
|
||||
else {
|
||||
SystemService.wakeup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val onCurrentPlayerStateChanged = { player: PlayerWrapper, state: PlayerWrapper.State ->
|
||||
wakeUpIfPlayerNeedsConnectivity(player)
|
||||
|
||||
when (state) {
|
||||
PlayerWrapper.State.Playing -> {
|
||||
setState(PlaybackState.Playing)
|
||||
@ -474,9 +518,11 @@ class StreamingPlaybackService(context: Context) : PlaybackService {
|
||||
}
|
||||
}
|
||||
|
||||
private val onNextPlayerStateChanged = { mpw: PlayerWrapper, state: PlayerWrapper.State ->
|
||||
private val onNextPlayerStateChanged = { player: PlayerWrapper, state: PlayerWrapper.State ->
|
||||
wakeUpIfPlayerNeedsConnectivity(player)
|
||||
|
||||
if (state === PlayerWrapper.State.Prepared) {
|
||||
if (mpw === playContext.nextPlayer) {
|
||||
if (player === playContext.nextPlayer) {
|
||||
playContext.notifyNextTrackPrepared()
|
||||
}
|
||||
}
|
||||
@ -631,8 +677,11 @@ class StreamingPlaybackService(context: Context) : PlaybackService {
|
||||
if (uri != null) {
|
||||
playContext.reset(playContext.nextPlayer)
|
||||
playContext.nextPlayer = PlayerWrapper.newInstance()
|
||||
playContext.nextPlayer?.setOnStateChangedListener(onNextPlayerStateChanged)
|
||||
playContext.nextPlayer?.prefetch(uri, playContext.nextMetadata!!)
|
||||
with (playContext.nextPlayer!!) {
|
||||
setOnStateChangedListener(onNextPlayerStateChanged)
|
||||
setOnFileCachedListener(onPlayerFileCached)
|
||||
prefetch(uri, playContext.nextMetadata!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -732,8 +781,11 @@ class StreamingPlaybackService(context: Context) : PlaybackService {
|
||||
|
||||
if (uri != null) {
|
||||
playContext.currentPlayer = PlayerWrapper.newInstance()
|
||||
playContext.currentPlayer?.setOnStateChangedListener(onCurrentPlayerStateChanged)
|
||||
playContext.currentPlayer?.play(uri, playContext.currentMetadata!!)
|
||||
with (playContext.currentPlayer!!) {
|
||||
setOnStateChangedListener(onCurrentPlayerStateChanged)
|
||||
setOnFileCachedListener(onPlayerFileCached)
|
||||
play(uri, playContext.currentMetadata!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -846,7 +898,7 @@ class StreamingPlaybackService(context: Context) : PlaybackService {
|
||||
|
||||
private val pauseServiceSleepRunnable = object: Runnable {
|
||||
override fun run() {
|
||||
SystemService.sleep()
|
||||
SystemService.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,8 @@ class SystemService : Service() {
|
||||
when (intent.action) {
|
||||
ACTION_WAKE_UP -> wakeupNow()
|
||||
ACTION_SHUT_DOWN -> shutdownNow()
|
||||
ACTION_SLEEP -> sleepNow()
|
||||
ACTION_DISCONNECT -> disconnectNow()
|
||||
ACTION_SLEEP -> scheduleReleaseWakeLock()
|
||||
else -> {
|
||||
if (handlePlaybackAction(intent.action)) {
|
||||
wakeupNow()
|
||||
@ -98,7 +99,7 @@ class SystemService : Service() {
|
||||
}
|
||||
|
||||
private fun wakeupNow() {
|
||||
Log.d(TAG, "SystemService WAKE_UP")
|
||||
Log.d(TAG, "SystemService wakeupNow()")
|
||||
|
||||
val sleeping = playback == null || wakeLock == null
|
||||
|
||||
@ -106,6 +107,8 @@ class SystemService : Service() {
|
||||
playback = PlaybackServiceFactory.streaming(this)
|
||||
}
|
||||
|
||||
handler.removeCallbacks(releaseWakeLockRunnable)
|
||||
|
||||
if (wakeLock == null) {
|
||||
wakeLock = powerManager.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, "StreamingPlaybackService")
|
||||
@ -121,7 +124,7 @@ class SystemService : Service() {
|
||||
}
|
||||
|
||||
private fun shutdownNow() {
|
||||
Log.d(TAG, "SystemService SHUT_DOWN")
|
||||
Log.d(TAG, "SystemService shutdownNow()")
|
||||
|
||||
mediaSession?.release()
|
||||
mediaSession = null
|
||||
@ -135,13 +138,17 @@ class SystemService : Service() {
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
private fun sleepNow() {
|
||||
Log.d(TAG, "SystemService SLEEP")
|
||||
wakeLock?.release()
|
||||
wakeLock = null
|
||||
private fun disconnectNow() {
|
||||
Log.d(TAG, "SystemService disconnectNow()")
|
||||
scheduleReleaseWakeLock()
|
||||
playback?.disconnect(playbackListener)
|
||||
}
|
||||
|
||||
private fun scheduleReleaseWakeLock() {
|
||||
Log.d(TAG, "SystemService scheduleReleaseWakeLock() -- 5 seconds until release")
|
||||
handler.postDelayed(releaseWakeLockRunnable, 5000)
|
||||
}
|
||||
|
||||
private fun initMediaSession() {
|
||||
val receiver = ComponentName(packageName, MediaButtonReceiver::class.java.name)
|
||||
|
||||
@ -203,6 +210,14 @@ class SystemService : Service() {
|
||||
.build())
|
||||
}
|
||||
|
||||
private val releaseWakeLockRunnable = object: Runnable {
|
||||
override fun run() {
|
||||
Log.d(TAG, "SystemService releasing WakeLock NOW!")
|
||||
wakeLock?.release()
|
||||
wakeLock = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun downloadAlbumArt(title: String, artist: String, album: String, duration: Int) {
|
||||
albumArt = null
|
||||
|
||||
@ -486,6 +501,7 @@ class SystemService : Service() {
|
||||
val ACTION_NOTIFICATION_STOP = "io.casey.musikcube.remote.PAUSE_SHUT_DOWN"
|
||||
var ACTION_WAKE_UP = "io.casey.musikcube.remote.WAKE_UP"
|
||||
var ACTION_SHUT_DOWN = "io.casey.musikcube.remote.SHUT_DOWN"
|
||||
var ACTION_DISCONNECT = "io.casey.musikcube.remote.DISCONNECT"
|
||||
var ACTION_SLEEP = "io.casey.musikcube.remote.SLEEP"
|
||||
|
||||
private val MEDIA_SESSION_ACTIONS =
|
||||
@ -505,6 +521,11 @@ class SystemService : Service() {
|
||||
c?.startService(Intent(c, SystemService::class.java).setAction(ACTION_SHUT_DOWN))
|
||||
}
|
||||
|
||||
fun disconnect() {
|
||||
val c = Application.instance
|
||||
c?.startService(Intent(c, SystemService::class.java).setAction(ACTION_DISCONNECT))
|
||||
}
|
||||
|
||||
fun sleep() {
|
||||
val c = Application.instance
|
||||
c?.startService(Intent(c, SystemService::class.java).setAction(ACTION_SLEEP))
|
||||
|
@ -52,10 +52,6 @@ class SettingsActivity : WebSocketActivityBase() {
|
||||
rebindUi()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.settings_menu, menu)
|
||||
return true
|
||||
|
Loading…
x
Reference in New Issue
Block a user