implement MidiPlayer for android

This commit is contained in:
hasinarak3@gmail.com 2026-02-06 09:51:33 +03:00
parent 2f0be71dd8
commit d25753aee4

View file

@ -1,129 +1,142 @@
package mg.dot.feufaro.midi
import java.io.File
import android.media.MediaPlayer
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileInputStream
private var androidMediaPlayer: MediaPlayer?= null
actual class MediaPlayer actual constructor(filename: String, onFinished: () -> Unit) {
private val player = androidMediaPlayer?.apply {
setDataSource(filename)
prepare()
setOnCompletionListener {
seekTo(0)
onFinished()
}
// val file = File(android.app.Instrumentation().context.filesDir, filename)
// if(file.exists()){
// androidMediaPlayer?.setDataSource(file.path)
// androidMediaPlayer?.prepare()
// androidMediaPlayer?.setOnCompletionListener {
// onFinished()
// }
// } else {
// println("Fichier midi non trouvée")
// }
}
private var mediaPlayer: MediaPlayer? = MediaPlayer()
private val voiceStates = mutableListOf(true, true, true, true)
private var currentGlobalVolume: Float = 0.8f
// private var currentGlobalVolume: Float = 0.8f
private var pointA: Long = -1L
private var pointB: Long = -1L
private val playerScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
private var abJob: Job? = null
private var isLoopingAB: Boolean = false
init {
try {
val file = File(filename)
if (file.exists()) {
val fis = FileInputStream(file)
mediaPlayer?.setDataSource(fis.fd)
mediaPlayer?.prepare()
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
val params = mediaPlayer?.playbackParams ?: android.media.PlaybackParams()
params.speed = 1.0f
mediaPlayer?.playbackParams = params
}
fis.close()
mediaPlayer?.setOnCompletionListener {
onFinished()
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
actual fun play() {
// player?.start()
mediaPlayer?.start()
}
actual fun pause() {
// player?.pause()
mediaPlayer?.pause()
}
actual fun stop() {
// player?.stop()
mediaPlayer?.stop()
mediaPlayer?.prepare()
mediaPlayer?.seekTo(0)
clearLoop()
}
actual fun getDuration(): Long {
// player!!.duration.toLong() ?: 0L
return 4.toLong()
return mediaPlayer?.duration?.toLong() ?: 0L
}
actual fun getCurrentPosition(): Long {
// player!!.currentPosition.toLong()
return 4.toLong()
return mediaPlayer?.currentPosition?.toLong() ?: 0L
}
actual fun seekTo(position: Long) {
// player!!.seekTo(position.toInt())
mediaPlayer?.seekTo(position.toInt())
}
actual fun setVolume(level: Float) {
mediaPlayer?.setVolume(level, level)
}
actual fun setVolume(level: Float){
// currentGlobalVolume =level
// player?.setVolume(level, level)
actual fun setPointA() {
pointA = mediaPlayer?.currentPosition?.toLong() ?: 0L
}
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
actual fun toggleVoice(index: Int): Unit{
voiceStates[index] = !voiceStates[index]
}
actual fun getVoiceStates(): List<Boolean> = voiceStates
actual fun changeInstru(noInstru: Int): Unit{
}
actual fun setPointA(): Unit{
// pointA = getCurrentPosition()
}
actual fun setPointB(): Unit{
pointB = getCurrentPosition()
if(pointB > pointA) {
actual fun setPointB() {
pointB = mediaPlayer?.currentPosition?.toLong() ?: 0L
if (pointB > pointA && pointA != -1L) {
isLoopingAB = true
startABMonitor()
}
}
actual fun clearLoop(): Unit{
actual fun clearLoop() {
isLoopingAB = false
pointA = -1L
pointB = -1L
abJob?.cancel()
}
private fun startABMonitor() {
abJob?.cancel()
abJob = playerScope.launch {
while (isLoopingAB) {
val currentPos = mediaPlayer?.currentPosition?.toLong() ?: 0L
if (currentPos >= pointB) {
mediaPlayer?.seekTo(pointA.toInt())
}
private fun startABMonitor(){
GlobalScope.launch {
while(isLoopingAB){
// if ((player?.currentPosition ?: 0) >= pointB){
// player?.seekTo(pointA?.toInt())
// }
delay(50)
}
}
}
actual fun setTempo(factor: Float){
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
actual fun toggleVoice(index: Int) {
voiceStates[index] = !voiceStates[index]
println("Toggle voice $index (Limitation: Nécessite SoundFont/Fluidsynth sur Android)")
}
actual fun getVoiceStates(): List<Boolean> = voiceStates
actual fun changeInstru(noInstru: Int) {
}
actual fun setTempo(factor: Float) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
mediaPlayer?.let {
val params = it.playbackParams
params.speed = factor
it.playbackParams = params
}
}
}
actual fun getCurrentBPM(): Float {
return 120f
}
}
/*
actual fun MidiPlayer(filename: String, onFinished: () -> Unit) {
StopMidi()
val file = File(android.app.Instrumentation().context.filesDir, filename)
if(file.exists()){
androidMediaPlayer?.setDataSource(file.path)
androidMediaPlayer?.prepare()
androidMediaPlayer?.setOnCompletionListener {
onFinished()
}
androidMediaPlayer?.start()
}
}
actual fun StopMidi() {
androidMediaPlayer?.let {
if (it.isPlaying) {
it.stop()
it.release()
fun release() {
mediaPlayer?.release()
mediaPlayer = null
playerScope.coroutineContext.cancel()
}
}
androidMediaPlayer = null
}*/
}