implement MidiPlayer for android
This commit is contained in:
parent
2f0be71dd8
commit
d25753aee4
1 changed files with 94 additions and 81 deletions
|
|
@ -1,129 +1,142 @@
|
||||||
package mg.dot.feufaro.midi
|
package mg.dot.feufaro.midi
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import android.media.MediaPlayer
|
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.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
private var androidMediaPlayer: MediaPlayer?= null
|
private var androidMediaPlayer: MediaPlayer?= null
|
||||||
|
|
||||||
actual class MediaPlayer actual constructor(filename: String, onFinished: () -> Unit) {
|
actual class MediaPlayer actual constructor(filename: String, onFinished: () -> Unit) {
|
||||||
private val player = androidMediaPlayer?.apply {
|
private var mediaPlayer: MediaPlayer? = MediaPlayer()
|
||||||
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 val voiceStates = mutableListOf(true, true, true, true)
|
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 pointA: Long = -1L
|
||||||
private var pointB: Long = -1L
|
private var pointB: Long = -1L
|
||||||
|
|
||||||
|
private val playerScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||||
|
private var abJob: Job? = null
|
||||||
|
|
||||||
private var isLoopingAB: Boolean = false
|
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() {
|
actual fun play() {
|
||||||
// player?.start()
|
mediaPlayer?.start()
|
||||||
}
|
}
|
||||||
actual fun pause() {
|
actual fun pause() {
|
||||||
// player?.pause()
|
mediaPlayer?.pause()
|
||||||
}
|
}
|
||||||
actual fun stop() {
|
actual fun stop() {
|
||||||
// player?.stop()
|
mediaPlayer?.stop()
|
||||||
|
mediaPlayer?.prepare()
|
||||||
|
mediaPlayer?.seekTo(0)
|
||||||
|
clearLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getDuration(): Long {
|
actual fun getDuration(): Long {
|
||||||
// player!!.duration.toLong() ?: 0L
|
return mediaPlayer?.duration?.toLong() ?: 0L
|
||||||
return 4.toLong()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getCurrentPosition(): Long {
|
actual fun getCurrentPosition(): Long {
|
||||||
// player!!.currentPosition.toLong()
|
return mediaPlayer?.currentPosition?.toLong() ?: 0L
|
||||||
return 4.toLong()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun seekTo(position: Long) {
|
actual fun seekTo(position: Long) {
|
||||||
// player!!.seekTo(position.toInt())
|
mediaPlayer?.seekTo(position.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun setVolume(level: Float) {
|
actual fun setVolume(level: Float) {
|
||||||
// currentGlobalVolume =level
|
mediaPlayer?.setVolume(level, level)
|
||||||
// player?.setVolume(level, level)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
|
actual fun setPointA() {
|
||||||
|
pointA = mediaPlayer?.currentPosition?.toLong() ?: 0L
|
||||||
actual fun toggleVoice(index: Int): Unit{
|
|
||||||
voiceStates[index] = !voiceStates[index]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getVoiceStates(): List<Boolean> = voiceStates
|
actual fun setPointB() {
|
||||||
|
pointB = mediaPlayer?.currentPosition?.toLong() ?: 0L
|
||||||
actual fun changeInstru(noInstru: Int): Unit{
|
if (pointB > pointA && pointA != -1L) {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun setPointA(): Unit{
|
|
||||||
// pointA = getCurrentPosition()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun setPointB(): Unit{
|
|
||||||
pointB = getCurrentPosition()
|
|
||||||
if(pointB > pointA) {
|
|
||||||
isLoopingAB = true
|
isLoopingAB = true
|
||||||
startABMonitor()
|
startABMonitor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun clearLoop(): Unit{
|
actual fun clearLoop() {
|
||||||
isLoopingAB = false
|
isLoopingAB = false
|
||||||
|
pointA = -1L
|
||||||
|
pointB = -1L
|
||||||
|
abJob?.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startABMonitor() {
|
private fun startABMonitor() {
|
||||||
GlobalScope.launch {
|
abJob?.cancel()
|
||||||
|
abJob = playerScope.launch {
|
||||||
while (isLoopingAB) {
|
while (isLoopingAB) {
|
||||||
// if ((player?.currentPosition ?: 0) >= pointB){
|
val currentPos = mediaPlayer?.currentPosition?.toLong() ?: 0L
|
||||||
// player?.seekTo(pointA?.toInt())
|
if (currentPos >= pointB) {
|
||||||
// }
|
mediaPlayer?.seekTo(pointA.toInt())
|
||||||
|
}
|
||||||
delay(50)
|
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 {
|
actual fun getCurrentBPM(): Float {
|
||||||
return 120f
|
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() {
|
fun release() {
|
||||||
androidMediaPlayer?.let {
|
mediaPlayer?.release()
|
||||||
if (it.isPlaying) {
|
mediaPlayer = null
|
||||||
it.stop()
|
playerScope.coroutineContext.cancel()
|
||||||
it.release()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
androidMediaPlayer = null
|
|
||||||
}*/
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue