working arbitrary track queueing

This commit is contained in:
minjaesong
2024-07-08 18:06:44 +09:00
parent 657c8051f8
commit 86c6f008f9
4 changed files with 37 additions and 11 deletions

View File

@@ -1051,6 +1051,8 @@ class MusicPlayerControl(private val ingame: TerrarumIngame) : UICanvas() {
private val playControlAnimAkku = FloatArray(5) // how many control buttons? private val playControlAnimAkku = FloatArray(5) // how many control buttons?
private val playControlAnimLength = 0.2f private val playControlAnimLength = 0.2f
private val colInactive = Color(0xaaaaaaff.toInt())
private fun drawControls(delta: Float, batch: SpriteBatch, posX: Float, posY: Float) { private fun drawControls(delta: Float, batch: SpriteBatch, posX: Float, posY: Float) {
val (alpha, reverse) = if (mode < MODE_MOUSE_UP && modeNext == MODE_MOUSE_UP) val (alpha, reverse) = if (mode < MODE_MOUSE_UP && modeNext == MODE_MOUSE_UP)
(transitionAkku / TRANSITION_LENGTH).let { if (it.isNaN()) 0f else it } to false (transitionAkku / TRANSITION_LENGTH).let { if (it.isNaN()) 0f else it } to false
@@ -1070,7 +1072,7 @@ class MusicPlayerControl(private val ingame: TerrarumIngame) : UICanvas() {
else else
0f 0f
val baseCol = if (MusicService.transactionLocked) Color.RED else Color.WHITE val baseCol = if (MusicService.transactionLocked) colInactive else Color.WHITE
if (alpha > 0f) { if (alpha > 0f) {
val alpha0 = alpha.coerceIn(0f, 1f).organicOvershoot().coerceAtMost(1f) val alpha0 = alpha.coerceIn(0f, 1f).organicOvershoot().coerceAtMost(1f)

View File

@@ -114,14 +114,14 @@ object MusicService : TransactionListener() {
override fun onFailure(e: Throwable, state: TransactionState) { override fun onFailure(e: Throwable, state: TransactionState) {
printdbg(this, "FIREPLAY resume OK but startMusic failed, entering intermission") printdbg(this, "FIREPLAY resume OK but startMusic failed, entering intermission")
enterSTATE_INTERMISSION(getRandomMusicInterval()) // will try again after a random interval enterIntermissionAndWaitForPlaylist() // will try again
} }
}) })
}, },
/* onFailure: (Throwable) -> Unit */ /* onFailure: (Throwable) -> Unit */
{ {
printdbg(this, "FIREPLAY resume failed, entering intermission") printdbg(this, "FIREPLAY resume failed, entering intermission")
enterSTATE_INTERMISSION(getRandomMusicInterval()) // will try again after a random interval enterIntermissionAndWaitForPlaylist() // will try again
}, },
// onFinally: () -> Unit // onFinally: () -> Unit
{ {
@@ -297,7 +297,6 @@ object MusicService : TransactionListener() {
} }
override fun onSuccess(state: TransactionState) { override fun onSuccess(state: TransactionState) {
enterSTATE_INTERMISSION(0f) enterSTATE_INTERMISSION(0f)
enterSTATE_FIREPLAY() enterSTATE_FIREPLAY()
onSuccess() onSuccess()
@@ -320,8 +319,8 @@ object MusicService : TransactionListener() {
App.audioMixer.requestFadeOut(App.audioMixer.musicTrack) { App.audioMixer.requestFadeOut(App.audioMixer.musicTrack) {
try { try {
// callback: play prev song in the playlist // callback: play prev song in the playlist
// TODO queue the nth song on the playlist, the actual playback will be done by the state machine update // queue the nth song on the playlist, the actual playback will be done by the state machine update
(state["currentPlaylist"] as TerrarumMusicPlaylist).queueNthSong(index)
fadedOut = true fadedOut = true
} }
@@ -335,6 +334,8 @@ object MusicService : TransactionListener() {
} }
override fun onSuccess(state: TransactionState) { override fun onSuccess(state: TransactionState) {
enterSTATE_INTERMISSION(0f)
enterSTATE_FIREPLAY()
onSuccess() onSuccess()
} }
override fun onFailure(e: Throwable, state: TransactionState) { override fun onFailure(e: Throwable, state: TransactionState) {

View File

@@ -84,9 +84,21 @@ class TerrarumMusicPlaylist(
} }
fun queueNthSong(n: Int): MusicContainer { fun queueNthSong(n: Int): MusicContainer {
checkRefill() if (shuffled) {
internalIndices.add(currentIndexCursor, n) internalIndices.clear()
currentIndexCursor -= 1 refillInternalIndices()
internalIndices.add(n)
refillInternalIndices()
currentIndexCursor = musicList.size - 1
}
else {
internalIndices.clear()
refillInternalIndices()
refillInternalIndices()
currentIndexCursor = musicList.size - 1 + n
checkRefill()
}
return musicList[internalIndices[currentIndexCursor]] return musicList[internalIndices[currentIndexCursor]]
} }

View File

@@ -33,6 +33,17 @@ abstract class TransactionListener {
val transactionLockingClass: AtomicReference<Transaction?> = AtomicReference(null) val transactionLockingClass: AtomicReference<Transaction?> = AtomicReference(null)
val transactionLocked: Boolean; get() = (transactionLockingClass.get() != null) val transactionLocked: Boolean; get() = (transactionLockingClass.get() != null)
private fun acquireLock(locker: Transaction) {
synchronized(this) {
transactionLockingClass.set(locker)
}
}
private fun releaseLock() {
synchronized(this) {
transactionLockingClass.set(null)
}
}
/** /**
* Transaction modifies a given state to a new state, then applies the new state to the object. * Transaction modifies a given state to a new state, then applies the new state to the object.
@@ -47,7 +58,7 @@ abstract class TransactionListener {
val state = getCurrentStatusForTransaction() val state = getCurrentStatusForTransaction()
val currentLock = transactionLockingClass.get() val currentLock = transactionLockingClass.get()
if (currentLock == null) { if (currentLock == null) {
transactionLockingClass.set(transaction) acquireLock(transaction)
try { try {
transaction.start(state) transaction.start(state)
// if successful: // if successful:
@@ -62,7 +73,7 @@ abstract class TransactionListener {
transaction.onFailure(e, state) transaction.onFailure(e, state)
} }
finally { finally {
transactionLockingClass.set(null) releaseLock()
onFinally() onFinally()
} }
} }