mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 18:44:05 +09:00
musicplayer: working prev and stop button
This commit is contained in:
@@ -9,7 +9,10 @@ import com.badlogic.gdx.utils.JsonValue
|
|||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.reflection.extortField
|
import net.torvald.reflection.extortField
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.audio.*
|
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.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
@@ -74,33 +77,38 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
|
|||||||
private val colourControlButton = Color(0xeeeeee_cc.toInt())
|
private val colourControlButton = Color(0xeeeeee_cc.toInt())
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setAsAlwaysVisible()
|
if (App.getConfigBoolean("musicplayer:usemusicplayer")) {
|
||||||
|
setAsAlwaysVisible()
|
||||||
|
|
||||||
// test code
|
// test code
|
||||||
// val albumDir = App.customMusicDir + "/Gapless Test 2"
|
// 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 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 diskJockeyingMode = playlistFile.get("diskJockeyingMode").asString()
|
||||||
val shuffled = playlistFile.get("shuffled").asBoolean()
|
val shuffled = playlistFile.get("shuffled").asBoolean()
|
||||||
val fileToName = playlistFile.get("titles")
|
val fileToName = playlistFile.get("titles")
|
||||||
|
|
||||||
|
|
||||||
AudioMixer.musicTrack.let { track ->
|
AudioMixer.musicTrack.let { track ->
|
||||||
track.doGaplessPlayback = (diskJockeyingMode == "continuous")
|
track.doGaplessPlayback = (diskJockeyingMode == "continuous")
|
||||||
if (track.doGaplessPlayback) {
|
if (track.doGaplessPlayback) {
|
||||||
track.pullNextTrack = {
|
track.pullNextTrack = {
|
||||||
track.currentTrack = ingame.musicGovernor.pullNextMusicTrack(true)
|
track.currentTrack = ingame.musicGovernor.pullNextMusicTrack(true)
|
||||||
setMusicName(track.currentTrack?.name ?: "")
|
setMusicName(track.currentTrack?.name ?: "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
registerPlaylist(albumDir, fileToName, shuffled, diskJockeyingMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
registerPlaylist(albumDir, fileToName, shuffled, diskJockeyingMode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val playlist: List<MusicContainer>
|
||||||
|
get() = ingame.musicGovernor.extortField<List<MusicContainer>>("songs")!!
|
||||||
|
|
||||||
fun registerPlaylist(path: String, fileToName: JsonValue, shuffled: Boolean, diskJockeyingMode: String) {
|
fun registerPlaylist(path: String, fileToName: JsonValue, shuffled: Boolean, diskJockeyingMode: String) {
|
||||||
ingame.musicGovernor.queueDirectory(path, shuffled, diskJockeyingMode) { filename ->
|
ingame.musicGovernor.queueDirectory(path, shuffled, diskJockeyingMode) { filename ->
|
||||||
fileToName.get(filename).let {
|
fileToName.get(filename).let {
|
||||||
@@ -239,13 +247,16 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
1 -> { // prev
|
1 -> { // prev
|
||||||
// ingame.musicGovernor.playPrevMusic()
|
getPrevSongFromPlaylist()?.let { ingame.musicGovernor.unshiftPlaylist(it) }
|
||||||
|
AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f)
|
||||||
}
|
}
|
||||||
2 -> { // stop
|
2 -> { // stop
|
||||||
if (AudioMixer.musicTrack.isPlaying) {
|
if (AudioMixer.musicTrack.isPlaying) {
|
||||||
|
val thisMusic = AudioMixer.musicTrack.currentTrack
|
||||||
AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f)
|
AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f)
|
||||||
AudioMixer.musicTrack.nextTrack = null
|
AudioMixer.musicTrack.nextTrack = null
|
||||||
ingame.musicGovernor.stopMusic()
|
ingame.musicGovernor.stopMusic()
|
||||||
|
thisMusic?.let { ingame.musicGovernor.queueMusicToPlayNext(it) }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ingame.musicGovernor.startMusic()
|
ingame.musicGovernor.startMusic()
|
||||||
@@ -271,6 +282,18 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
|
|||||||
|
|
||||||
private var playControlButtonLatched = false
|
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 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)
|
// private fun smootherstep(x: Float) = (x*x*x*(x*(6f*x-15f)+10f)).coerceIn(0f, 1f)
|
||||||
|
|
||||||
|
|||||||
1
assets/mods/musicplayer/configplan.csv
Normal file
1
assets/mods/musicplayer/configplan.csv
Normal file
@@ -0,0 +1 @@
|
|||||||
|
usemusicplayer->Lang:MENU_OPTIONS_USE_MUSIC_PLAYER->toggle
|
||||||
|
3
assets/mods/musicplayer/default.json
Normal file
3
assets/mods/musicplayer/default.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usemusicplayer": true
|
||||||
|
}
|
||||||
3
assets/mods/musicplayer/locales/en/musicplayer.json
Normal file
3
assets/mods/musicplayer/locales/en/musicplayer.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"MENU_OPTIONS_USE_MUSIC_PLAYER": "Use Music Player"
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ import net.torvald.terrarum.*
|
|||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.audio.AudioMixer
|
import net.torvald.terrarum.audio.AudioMixer
|
||||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
||||||
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import javax.sound.sampled.AudioSystem
|
import javax.sound.sampled.AudioSystem
|
||||||
@@ -135,6 +136,8 @@ data class MusicContainer(
|
|||||||
samplesRead = 0L
|
samplesRead = 0L
|
||||||
gdxMusic.forceInvoke<Int>("reset", arrayOf())
|
gdxMusic.forceInvoke<Int>("reset", arrayOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?) = this.file.path == (other as MusicContainer).file.path
|
||||||
}
|
}
|
||||||
|
|
||||||
class TerrarumMusicGovernor : MusicGovernor() {
|
class TerrarumMusicGovernor : MusicGovernor() {
|
||||||
@@ -149,7 +152,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var songs: List<MusicContainer> = emptyList()
|
private var songs: List<MusicContainer> = emptyList()
|
||||||
private var musicBin: ArrayList<Int> = ArrayList()
|
private var musicBin: ArrayList<MusicContainer> = ArrayList()
|
||||||
private var shuffled = true
|
private var shuffled = true
|
||||||
private var diskJockeyingMode = "intermittent" // intermittent, continuous
|
private var diskJockeyingMode = "intermittent" // intermittent, continuous
|
||||||
|
|
||||||
@@ -184,8 +187,8 @@ class TerrarumMusicGovernor : MusicGovernor() {
|
|||||||
} ?: emptyList() // TODO test code
|
} ?: emptyList() // TODO test code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restockMUsicBin() {
|
private fun restockMusicBin() {
|
||||||
musicBin = if (shuffled) ArrayList(songs.indices.toList().shuffled()) else ArrayList(songs.indices.toList())
|
musicBin = ArrayList(if (shuffled) songs.shuffled() else songs.slice(songs.indices))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -205,7 +208,30 @@ class TerrarumMusicGovernor : MusicGovernor() {
|
|||||||
this.shuffled = shuffled
|
this.shuffled = shuffled
|
||||||
this.diskJockeyingMode = diskJockeyingMode
|
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<MusicContainer> =
|
private val ambients: List<MusicContainer> =
|
||||||
@@ -300,9 +326,9 @@ class TerrarumMusicGovernor : MusicGovernor() {
|
|||||||
|
|
||||||
// prevent same song to play twice in row (for the most time)
|
// prevent same song to play twice in row (for the most time)
|
||||||
if (musicBin.isEmpty()) {
|
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) }
|
if (callNextMusicHook && musicStartHooks.isNotEmpty()) musicStartHooks.forEach { it(mus) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user