From 824cb6097d70eb131cf480feeaacc16beb83e027 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Fri, 29 Dec 2023 23:49:11 +0900 Subject: [PATCH] musicplayer: working prev and stop button --- .../terrarum/musicplayer/gui/MusicPlayer.kt | 57 +++++++++++++------ assets/mods/musicplayer/configplan.csv | 1 + assets/mods/musicplayer/default.json | 3 + .../musicplayer/locales/en/musicplayer.json | 3 + .../modulebasegame/TerrarumMusicGovernor.kt | 38 +++++++++++-- 5 files changed, 79 insertions(+), 23 deletions(-) create mode 100644 assets/mods/musicplayer/configplan.csv create mode 100644 assets/mods/musicplayer/default.json create mode 100644 assets/mods/musicplayer/locales/en/musicplayer.json diff --git a/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt b/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt index 47ad778fc..6bd40dbe4 100644 --- a/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt +++ b/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt @@ -9,7 +9,10 @@ import com.badlogic.gdx.utils.JsonValue import com.jme3.math.FastMath import net.torvald.reflection.extortField import net.torvald.terrarum.* +import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.audio.* +import net.torvald.terrarum.gameworld.fmod +import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.ui.BasicDebugInfoWindow import net.torvald.terrarum.ui.Toolkit @@ -74,33 +77,38 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() { private val colourControlButton = Color(0xeeeeee_cc.toInt()) init { - setAsAlwaysVisible() + if (App.getConfigBoolean("musicplayer:usemusicplayer")) { + setAsAlwaysVisible() - // test code + // test code // val albumDir = App.customMusicDir + "/Gapless Test 2" - val albumDir = App.customMusicDir + "/FurryJoA 2023 Live" + val albumDir = App.customMusicDir + "/FurryJoA 2023 Live" // val albumDir = App.customMusicDir + "/Audio Test" - val playlistFile = JsonFetcher.invoke("$albumDir/playlist.json") + val playlistFile = JsonFetcher.invoke("$albumDir/playlist.json") - val diskJockeyingMode = playlistFile.get("diskJockeyingMode").asString() - val shuffled = playlistFile.get("shuffled").asBoolean() - val fileToName = playlistFile.get("titles") + val diskJockeyingMode = playlistFile.get("diskJockeyingMode").asString() + val shuffled = playlistFile.get("shuffled").asBoolean() + val fileToName = playlistFile.get("titles") - AudioMixer.musicTrack.let { track -> - track.doGaplessPlayback = (diskJockeyingMode == "continuous") - if (track.doGaplessPlayback) { - track.pullNextTrack = { - track.currentTrack = ingame.musicGovernor.pullNextMusicTrack(true) - setMusicName(track.currentTrack?.name ?: "") + AudioMixer.musicTrack.let { track -> + track.doGaplessPlayback = (diskJockeyingMode == "continuous") + if (track.doGaplessPlayback) { + track.pullNextTrack = { + track.currentTrack = ingame.musicGovernor.pullNextMusicTrack(true) + setMusicName(track.currentTrack?.name ?: "") + } } } + + + registerPlaylist(albumDir, fileToName, shuffled, diskJockeyingMode) } - - - registerPlaylist(albumDir, fileToName, shuffled, diskJockeyingMode) } + private val playlist: List + get() = ingame.musicGovernor.extortField>("songs")!! + fun registerPlaylist(path: String, fileToName: JsonValue, shuffled: Boolean, diskJockeyingMode: String) { ingame.musicGovernor.queueDirectory(path, shuffled, diskJockeyingMode) { filename -> fileToName.get(filename).let { @@ -239,13 +247,16 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() { } 1 -> { // prev -// ingame.musicGovernor.playPrevMusic() + getPrevSongFromPlaylist()?.let { ingame.musicGovernor.unshiftPlaylist(it) } + AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) } 2 -> { // stop if (AudioMixer.musicTrack.isPlaying) { + val thisMusic = AudioMixer.musicTrack.currentTrack AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) AudioMixer.musicTrack.nextTrack = null ingame.musicGovernor.stopMusic() + thisMusic?.let { ingame.musicGovernor.queueMusicToPlayNext(it) } } else { ingame.musicGovernor.startMusic() @@ -271,6 +282,18 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() { private var playControlButtonLatched = false + private fun getPrevSongFromPlaylist(): MusicContainer? { + val list = playlist.slice(playlist.indices) // make copy of the list + val nowPlaying = AudioMixer.musicTrack.currentTrack ?: return null + + // find current index + val currentIndex = list.indexOfFirst { it == nowPlaying } + if (currentIndex < 0) return null + + val prevIndex = (currentIndex - 1).fmod(list.size) + return list[prevIndex] + } + // private fun smoothstep(x: Float) = (x*x*(3f-2f*x)).coerceIn(0f, 1f) // private fun smootherstep(x: Float) = (x*x*x*(x*(6f*x-15f)+10f)).coerceIn(0f, 1f) diff --git a/assets/mods/musicplayer/configplan.csv b/assets/mods/musicplayer/configplan.csv new file mode 100644 index 000000000..9911ae55b --- /dev/null +++ b/assets/mods/musicplayer/configplan.csv @@ -0,0 +1 @@ +usemusicplayer->Lang:MENU_OPTIONS_USE_MUSIC_PLAYER->toggle \ No newline at end of file diff --git a/assets/mods/musicplayer/default.json b/assets/mods/musicplayer/default.json new file mode 100644 index 000000000..080c63222 --- /dev/null +++ b/assets/mods/musicplayer/default.json @@ -0,0 +1,3 @@ +{ + "usemusicplayer": true +} \ No newline at end of file diff --git a/assets/mods/musicplayer/locales/en/musicplayer.json b/assets/mods/musicplayer/locales/en/musicplayer.json new file mode 100644 index 000000000..5c96f2c00 --- /dev/null +++ b/assets/mods/musicplayer/locales/en/musicplayer.json @@ -0,0 +1,3 @@ +{ + "MENU_OPTIONS_USE_MUSIC_PLAYER": "Use Music Player" +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt index 73b375e33..734a97ea3 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt @@ -16,6 +16,7 @@ import net.torvald.terrarum.* import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.audio.AudioMixer import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE +import net.torvald.terrarum.gameworld.fmod import java.io.File import java.io.FileInputStream import javax.sound.sampled.AudioSystem @@ -135,6 +136,8 @@ data class MusicContainer( samplesRead = 0L gdxMusic.forceInvoke("reset", arrayOf()) } + + override fun equals(other: Any?) = this.file.path == (other as MusicContainer).file.path } class TerrarumMusicGovernor : MusicGovernor() { @@ -149,7 +152,7 @@ class TerrarumMusicGovernor : MusicGovernor() { } private var songs: List = emptyList() - private var musicBin: ArrayList = ArrayList() + private var musicBin: ArrayList = ArrayList() private var shuffled = true private var diskJockeyingMode = "intermittent" // intermittent, continuous @@ -184,8 +187,8 @@ class TerrarumMusicGovernor : MusicGovernor() { } ?: emptyList() // TODO test code } - private fun restockMUsicBin() { - musicBin = if (shuffled) ArrayList(songs.indices.toList().shuffled()) else ArrayList(songs.indices.toList()) + private fun restockMusicBin() { + musicBin = ArrayList(if (shuffled) songs.shuffled() else songs.slice(songs.indices)) } /** @@ -205,7 +208,30 @@ class TerrarumMusicGovernor : MusicGovernor() { this.shuffled = shuffled this.diskJockeyingMode = diskJockeyingMode - restockMUsicBin() + restockMusicBin() + } + + /** + * Adds a song to the head of the internal playlist (`musicBin`) + */ + fun queueMusicToPlayNext(music: MusicContainer) { + musicBin.add(0, music) + } + + /** + * Unshifts an internal playlist (`musicBin`). The `music` argument must be the song that exists on the `songs`. + */ + fun unshiftPlaylist(music: MusicContainer) { + val indexAtMusicBin = songs.indexOf(music) + if (indexAtMusicBin < 0) throw IllegalArgumentException("The music does not exist on the interal songs list ($music)") + + // rewrite musicBin + val newMusicBin = Array(songs.size - indexAtMusicBin) { offset -> + val k = offset + indexAtMusicBin + songs[k] + } + + musicBin = ArrayList(newMusicBin.toList()) } private val ambients: List = @@ -300,9 +326,9 @@ class TerrarumMusicGovernor : MusicGovernor() { // prevent same song to play twice in row (for the most time) if (musicBin.isEmpty()) { - restockMUsicBin() + restockMusicBin() } - return songs[musicBin.removeAt(0)].also { mus -> + return musicBin.removeAt(0).also { mus -> if (callNextMusicHook && musicStartHooks.isNotEmpty()) musicStartHooks.forEach { it(mus) } } }