Update playback system
Tweak some things in PlaybackService and PlaybackStateManager to make them more elegant.
This commit is contained in:
parent
466629e43d
commit
391ca70822
7 changed files with 27 additions and 44 deletions
|
@ -30,13 +30,10 @@ class MainActivity : AppCompatActivity() {
|
||||||
)
|
)
|
||||||
|
|
||||||
val settingsManager = SettingsManager.getInstance()
|
val settingsManager = SettingsManager.getInstance()
|
||||||
|
val newAccent = Accent.set(settingsManager.accent)
|
||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(settingsManager.theme)
|
AppCompatDelegate.setDefaultNightMode(settingsManager.theme)
|
||||||
|
setTheme(newAccent.theme)
|
||||||
val accent = Accent.set(settingsManager.accent)
|
|
||||||
|
|
||||||
// Apply the theme
|
|
||||||
setTheme(accent.theme)
|
|
||||||
|
|
||||||
if (isEdgeOn()) {
|
if (isEdgeOn()) {
|
||||||
doEdgeToEdgeSetup(binding)
|
doEdgeToEdgeSetup(binding)
|
||||||
|
|
|
@ -28,7 +28,7 @@ class MusicStore private constructor() {
|
||||||
val songs: List<Song> get() = mSongs
|
val songs: List<Song> get() = mSongs
|
||||||
|
|
||||||
/** All parent models (ex Albums, Artists) loaded by Auxio */
|
/** All parent models (ex Albums, Artists) loaded by Auxio */
|
||||||
val parents: MutableList<Parent> by lazy {
|
val parents: List<Parent> by lazy {
|
||||||
mutableListOf<Parent>().apply {
|
mutableListOf<Parent>().apply {
|
||||||
addAll(mGenres)
|
addAll(mGenres)
|
||||||
addAll(mArtists)
|
addAll(mArtists)
|
||||||
|
@ -50,7 +50,7 @@ class MusicStore private constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do the internal music loading process.
|
* Do the actual music loading process internally.
|
||||||
*/
|
*/
|
||||||
private fun loadMusicInternal(context: Context): Response {
|
private fun loadMusicInternal(context: Context): Response {
|
||||||
logD("Starting initial music load...")
|
logD("Starting initial music load...")
|
||||||
|
|
|
@ -183,9 +183,7 @@ class PlaybackStateManager private constructor() {
|
||||||
|
|
||||||
mMode = mode
|
mMode = mode
|
||||||
|
|
||||||
clearLoopMode()
|
|
||||||
updatePlayback(song)
|
updatePlayback(song)
|
||||||
|
|
||||||
// Keep shuffle on, if enabled
|
// Keep shuffle on, if enabled
|
||||||
setShuffling(settingsManager.keepShuffle && mIsShuffling, keepSong = true)
|
setShuffling(settingsManager.keepShuffle && mIsShuffling, keepSong = true)
|
||||||
}
|
}
|
||||||
|
@ -217,7 +215,6 @@ class PlaybackStateManager private constructor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearLoopMode()
|
|
||||||
setShuffling(shuffled, keepSong = false)
|
setShuffling(shuffled, keepSong = false)
|
||||||
updatePlayback(mQueue[0])
|
updatePlayback(mQueue[0])
|
||||||
}
|
}
|
||||||
|
@ -232,8 +229,6 @@ class PlaybackStateManager private constructor() {
|
||||||
|
|
||||||
setShuffling(true, keepSong = false)
|
setShuffling(true, keepSong = false)
|
||||||
updatePlayback(mQueue[0])
|
updatePlayback(mQueue[0])
|
||||||
|
|
||||||
// FIXME: Add clearLoopMode here?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,6 +243,8 @@ class PlaybackStateManager private constructor() {
|
||||||
if (!mIsPlaying) {
|
if (!mIsPlaying) {
|
||||||
setPlaying(true)
|
setPlaying(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearLoopMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- QUEUE FUNCTIONS ---
|
// --- QUEUE FUNCTIONS ---
|
||||||
|
@ -256,8 +253,6 @@ class PlaybackStateManager private constructor() {
|
||||||
* Go to the next song, along with doing all the checks that entails.
|
* Go to the next song, along with doing all the checks that entails.
|
||||||
*/
|
*/
|
||||||
fun next() {
|
fun next() {
|
||||||
clearLoopMode()
|
|
||||||
|
|
||||||
// If there's anything in the user queue, go to the first song in there instead
|
// If there's anything in the user queue, go to the first song in there instead
|
||||||
// of incrementing the index.
|
// of incrementing the index.
|
||||||
if (mUserQueue.isNotEmpty()) {
|
if (mUserQueue.isNotEmpty()) {
|
||||||
|
@ -298,7 +293,6 @@ class PlaybackStateManager private constructor() {
|
||||||
mIndex = mIndex.dec()
|
mIndex = mIndex.dec()
|
||||||
}
|
}
|
||||||
|
|
||||||
clearLoopMode()
|
|
||||||
updatePlayback(mQueue[mIndex])
|
updatePlayback(mQueue[mIndex])
|
||||||
forceQueueUpdate()
|
forceQueueUpdate()
|
||||||
}
|
}
|
||||||
|
@ -315,6 +309,7 @@ class PlaybackStateManager private constructor() {
|
||||||
mIsInUserQueue = false
|
mIsInUserQueue = false
|
||||||
mSong = mQueue[0]
|
mSong = mQueue[0]
|
||||||
|
|
||||||
|
clearLoopMode()
|
||||||
setPlaying(false)
|
setPlaying(false)
|
||||||
forceQueueUpdate()
|
forceQueueUpdate()
|
||||||
}
|
}
|
||||||
|
@ -623,33 +618,30 @@ class PlaybackStateManager private constructor() {
|
||||||
suspend fun restoreFromDatabase(context: Context) {
|
suspend fun restoreFromDatabase(context: Context) {
|
||||||
logD("Getting state from DB.")
|
logD("Getting state from DB.")
|
||||||
|
|
||||||
val now: Long
|
val start: Long
|
||||||
val playbackState: PlaybackState?
|
val playbackState: PlaybackState?
|
||||||
|
val queueItems: List<QueueItem>
|
||||||
|
|
||||||
// The coroutine call is locked at queueItems so that this function does not
|
withContext(Dispatchers.IO) {
|
||||||
// go ahead until EVERYTHING is read.
|
start = System.currentTimeMillis()
|
||||||
// TODO: Improve this
|
|
||||||
val queueItems = withContext(Dispatchers.IO) {
|
|
||||||
now = System.currentTimeMillis()
|
|
||||||
|
|
||||||
val database = PlaybackStateDatabase.getInstance(context)
|
val database = PlaybackStateDatabase.getInstance(context)
|
||||||
|
|
||||||
playbackState = database.readState()
|
playbackState = database.readState()
|
||||||
database.readQueue()
|
queueItems = database.readQueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get off the IO coroutine since it will cause LiveData updates to throw an exception
|
// Get off the IO coroutine since it will cause LiveData updates to throw an exception
|
||||||
|
|
||||||
if (playbackState != null) {
|
if (playbackState != null) {
|
||||||
logD("Found playback state $playbackState")
|
logD("Found playback state $playbackState with queue size ${queueItems.size}")
|
||||||
logD("Found queue size ${queueItems.size}")
|
|
||||||
|
|
||||||
unpackFromPlaybackState(playbackState)
|
unpackFromPlaybackState(playbackState)
|
||||||
unpackQueue(queueItems)
|
unpackQueue(queueItems)
|
||||||
doParentSanityCheck()
|
doParentSanityCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
logD("Restore finished in ${System.currentTimeMillis() - now}ms")
|
logD("Restore finished in ${System.currentTimeMillis() - start}ms")
|
||||||
|
|
||||||
markRestored()
|
markRestored()
|
||||||
}
|
}
|
||||||
|
@ -717,9 +709,9 @@ class PlaybackStateManager private constructor() {
|
||||||
// When unpacking, first traverse albums and then traverse album songs to reduce
|
// When unpacking, first traverse albums and then traverse album songs to reduce
|
||||||
// the amount of comparisons in large queues.
|
// the amount of comparisons in large queues.
|
||||||
queueItems.forEach { item ->
|
queueItems.forEach { item ->
|
||||||
musicStore.albums.find {
|
val album = musicStore.albums.find { it.name == item.albumName }
|
||||||
it.name == item.albumName
|
|
||||||
}?.songs?.find { it.name == item.songName }?.let { song ->
|
album?.songs?.find { it.name == item.songName }?.let { song ->
|
||||||
if (item.isUserQueue) {
|
if (item.isUserQueue) {
|
||||||
mUserQueue.add(song)
|
mUserQueue.add(song)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -220,8 +220,6 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
|
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
|
||||||
)
|
)
|
||||||
|
|
||||||
logD("Song Status: $song")
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,6 @@ class SettingsListFragment : PreferenceFragmentCompat() {
|
||||||
val recycler = RecyclerView(requireContext()).apply {
|
val recycler = RecyclerView(requireContext()).apply {
|
||||||
adapter = AccentAdapter { accent ->
|
adapter = AccentAdapter { accent ->
|
||||||
if (accent != Accent.get()) {
|
if (accent != Accent.get()) {
|
||||||
// TODO: Move this to Accent.set?
|
|
||||||
settingsManager.accent = accent
|
settingsManager.accent = accent
|
||||||
|
|
||||||
requireActivity().recreate()
|
requireActivity().recreate()
|
||||||
|
|
|
@ -24,8 +24,7 @@ import org.oxycblt.auxio.ui.inflater
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A slimmed-down variant of [com.reddit.indicatorfastscroll.FastScrollerThumbView] designed
|
* A slimmed-down variant of [com.reddit.indicatorfastscroll.FastScrollerThumbView] designed
|
||||||
* specifically for Auxio. Also fixes a memory leak that occurs from a bug fix they
|
* specifically for Auxio. Also fixes a memory leak that occurs from a bug fix they added.
|
||||||
* added.
|
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class CobaltScrollThumb @JvmOverloads constructor(
|
class CobaltScrollThumb @JvmOverloads constructor(
|
||||||
|
@ -88,16 +87,18 @@ class CobaltScrollThumb @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("ClickableViewAccessibility")
|
@Suppress("ClickableViewAccessibility")
|
||||||
scrollView.setOnTouchListener { v, event ->
|
scrollView.setOnTouchListener { _, event ->
|
||||||
scrollView.onTouchEvent(event)
|
scrollView.onTouchEvent(event)
|
||||||
scrollView.performClick()
|
scrollView.performClick()
|
||||||
|
|
||||||
val action = event.actionMasked
|
val action = event.actionMasked
|
||||||
|
val actionValid = action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL
|
||||||
|
|
||||||
// If we arent deselecting the scroll view, determine if we are selecting an item.
|
isActivated = if (actionValid) {
|
||||||
isActivated = if (
|
isPointerOnItem(scrollView, event.y.toInt())
|
||||||
action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL
|
} else {
|
||||||
) isPointerOnItem(scrollView, event.y.toInt()) else false
|
false
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import androidx.annotation.StringRes
|
||||||
import androidx.annotation.StyleRes
|
import androidx.annotation.StyleRes
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.settings.SettingsManager
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,6 +70,7 @@ data class Accent(@ColorRes val color: Int, @StyleRes val theme: Int, @StringRes
|
||||||
/**
|
/**
|
||||||
* Get the current accent.
|
* Get the current accent.
|
||||||
* @return The current accent
|
* @return The current accent
|
||||||
|
* @throws IllegalStateException When the accent has not been set.
|
||||||
*/
|
*/
|
||||||
fun get(): Accent {
|
fun get(): Accent {
|
||||||
val cur = current
|
val cur = current
|
||||||
|
@ -79,11 +79,7 @@ data class Accent(@ColorRes val color: Int, @StyleRes val theme: Int, @StringRes
|
||||||
return cur
|
return cur
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized(this) {
|
error("Accent must be set before retrieving it.")
|
||||||
val newCur = SettingsManager.getInstance().accent
|
|
||||||
current = newCur
|
|
||||||
return newCur
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue