From c00a8507cad904019ad9e75f5cb5b0ad9b815fca Mon Sep 17 00:00:00 2001 From: hasina Date: Mon, 19 Jan 2026 14:53:39 +0300 Subject: [PATCH] Remember voice states SATB --- .../kotlin/mg/dot/feufaro/ui/DrawerUI.kt | 146 +----------------- .../kotlin/mg/dot/feufaro/midi/MidiPlayer.kt | 45 +++--- 2 files changed, 27 insertions(+), 164 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/DrawerUI.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/DrawerUI.kt index 1889a37..7ead67d 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/DrawerUI.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/DrawerUI.kt @@ -38,8 +38,6 @@ import mg.dot.feufaro.data.DrawerItem import mg.dot.feufaro.data.getDrawerItems import mg.dot.feufaro.getPlatform import mg.dot.feufaro.midi.MediaPlayer -//import mg.dot.feufaro.midi.MidiPlayer -//import mg.dot.feufaro.midi.StopMidi import mg.dot.feufaro.solfa.Solfa import mg.dot.feufaro.viewmodel.SolfaScreenModel import java.io.File @@ -74,11 +72,7 @@ fun MainScreenWithDrawer( -//var isDragging by remember { mutableStateOf(false) } -//var isPlay by remember { mutableStateOf(false) } -//var isPos by remember { mutableStateOf(true) } var isPlayMid by remember { mutableStateOf(false) } -//var currentPos by remember { mutableStateOf(0f) } val isPlay by sharedScreenModel.isPlay.collectAsState() val isPos by sharedScreenModel.isPos.collectAsState() var isDragging = sharedScreenModel.isDragging @@ -90,19 +84,9 @@ var refreshTrigeer by remember { mutableStateOf(0)} val volumelevel by sharedScreenModel.volumeLevel.collectAsState() val player = sharedScreenModel.mediaPlayer -/*val mediaPlayer = remember(refreshTrigeer) { - MediaPlayer(filename = midiFile, onFinished = { - isPos = true - isPlay = false - currentPos = 0f -// isPlayMid = true - println("fin de lecture du whawyd3.mid") - }).apply { setVolume(volumelevel) } -}*/ LaunchedEffect(isPlay, isPos) { if (isPlay && !isPos) { -// while (isPlay && !isPos) { while (true) { sharedScreenModel.updateProgress() delay(100) @@ -110,20 +94,6 @@ LaunchedEffect(isPlay, isPos) { } } -/*LaunchedEffect(isPlay, isPos, mediaPlayer) { - if (isPlay && !isPos) { - val d = mediaPlayer.getDuration().toFloat() - if (d > 0) duration = d - while (isPlay && !isPos) { - if(!isDragging) { - val p = mediaPlayer.getCurrentPosition().toFloat() - if (p >= 0) currentPos = p - } - delay(100) - } - } -}*/ - LaunchedEffect(isSearchActive) { if (isSearchActive) { focusRequester.requestFocus() @@ -145,14 +115,9 @@ LaunchedEffect(isPlay, isPos) { onScannerButtonClick() }, onSongSelected = { newSong -> -// mediaPlayer?.stop() -// isPos = true -// isPlay = false -// currentPos = 0f sharedScreenModel.loadNewSong("whawyd3.mid") -// refreshTrigeer++ } - ) + ) }, content = { Scaffold(contentWindowInsets = WindowInsets(0, 0, 0, 0), topBar = { TopAppBar( @@ -174,15 +139,7 @@ LaunchedEffect(isPlay, isPos) { }) { Icon(Icons.Filled.Menu, contentDescription = "Ouvrir Menu") } - }, actions = {/* Text( - text = measure, - modifier = Modifier.weight(1f, fill = false), - fontSize = 20.sp, - maxLines = 2, - softWrap = false, - overflow = TextOverflow.Ellipsis - ) - Spacer(Modifier.width(8.dp))*/ + }, actions = { Text( text = songKey, fontSize = 25.sp, @@ -250,11 +207,6 @@ LaunchedEffect(isPlay, isPos) { FloatingActionButton( onClick = { isPlayMid = !isPlayMid -// if(isPlayMid) sharedScreenModel.stopMidi() -// if(mediaPlayer.getCurrentPosition() != 0L) { -// mediaPlayer?.seekTo(0) -// mediaPlayer?.stop() -// } }, modifier = Modifier.alpha(0.45f) ) { Icon( @@ -294,45 +246,8 @@ LaunchedEffect(isPlay, isPos) { volume = volumelevel, duration = duration, onPlayPauseClick = { - sharedScreenModel.togglePlayPause()/*if(isPlay){ - mediaPlayer?.pause() - isPlay = false - isPos = true - } else { - if(currentPos == 0f) { - mediaPlayer?.seekTo(0) - } - mediaPlayer?.play() - mediaPlayer?.setVolume(volumelevel) - isPlay = true - isPos = false*/ - }, - /* if(!isPlay) { - if (currentPos == 0f) mediaPlayer.seekTo(0) - mediaPlayer?.play() - isPlay = true - isPos = false - } else { - mediaPlayer?.stop() - isPlay = false - isPos = true - }*/ - - // println("je clique pause = ${sharedScreenModel.isPlay} play = ${sharedScreenModel.isPos}") - // if(isPos) { - // mediaPlayer.play() - // isPos = false - // } else { - // mediaPlayer.pause() - // isPos = true - // } - /*if (isPlayMid) { -// mediaPlayer.seekTo(0f.toLong()) - mediaPlayer.play() - isPlayMid = false - } - }*/ - onSeek = { newPos -> // currentPos = newPos + sharedScreenModel.togglePlayPause() + onSeek = { newPos -> sharedScreenModel.setDragging(true) sharedScreenModel.seekTo(newPos) scope.launch { @@ -342,7 +257,7 @@ LaunchedEffect(isPlay, isPos) { println("DrawerUI:335: mihetsika $newPos") }, mediaPlayer = player, - onVolumeChange = { newVolume -> // volumelevel = newVolume + onVolumeChange = { newVolume -> sharedScreenModel.setVolume(newVolume) println("Changement volume $newVolume -l $volumelevel") }, @@ -350,29 +265,6 @@ LaunchedEffect(isPlay, isPos) { } else { Text("Sélectionner un morceau") } - /*Row( - modifier = Modifier.align(Alignment.Center).padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Slider( - value = currentPos, - onValueChange = { newPos -> - currentPos = newPos - mediaPlayer?.seekTo(newPos.toLong()) - }, - valueRange = 0f..duration - ) - } - Button( - onClick = { - isPos = !isPos - if(isPlay) mediaPlayer?.pause() else mediaPlayer?.play() - if(isPos) mediaPlayer?.pause() else mediaPlayer?.play() - } - ) { - Text(if (isPos) "Pause" else "play Midi") - }*/ } } } @@ -444,13 +336,6 @@ LaunchedEffect(isPlay, isPos) { placeholder = { Text("... ...") }, - /*leadingIcon = { - Icon( - imageVector = Icons.Default.Search, - contentDescription = "Icône de recherche", - tint = MaterialTheme.colorScheme.primary - ) - },*/ textStyle = MaterialTheme.typography.titleLarge.copy( fontSize = 17.sp, fontWeight = FontWeight.Bold, @@ -495,23 +380,4 @@ LaunchedEffect(isPlay, isPos) { } } }) -} -/* - -var isPlay by mutableStateOf(false) - private set - -fun playMidi() { - if(!isPlay) { - isPlay = true - MidiPlayer("whawyd3.mid") { - isPlay = false - } - } -} -fun stopMidi() { - if(isPlay) { - StopMidi() - isPlay = false - } -}*/ +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt b/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt index e3de7f2..b6625fe 100644 --- a/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt +++ b/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt @@ -6,15 +6,14 @@ import kotlinx.coroutines.launch import mg.dot.feufaro.FileRepository import java.io.ByteArrayInputStream import java.io.File +import java.util.prefs.Preferences import javax.sound.midi.MidiSystem import javax.sound.midi.Sequencer -import javax.sound.midi.Synthesizer //import javax.sound.midi.ShortMessage -//import javax.sound.midi.Synthesizer +import javax.sound.midi.Synthesizer import javax.sound.sampled.AudioFormat import javax.sound.sampled.AudioSystem import javax.sound.sampled.FloatControl -//private var sequencer: javax.sound.midi.Sequencer?= null actual class MediaPlayer actual constructor( private val filename: String, private val onFinished: () -> Unit @@ -27,6 +26,7 @@ actual class MediaPlayer actual constructor( null } + private val prefs = Preferences.userRoot().node("mg.dot.feufaro") private var synthetizer = MidiSystem.getSynthesizer() as Synthesizer? private var pointA: Long = -1L @@ -53,6 +53,7 @@ actual class MediaPlayer actual constructor( val file = File(filename) if (file.exists()){ sequencer?.sequence = MidiSystem.getSequence(file) + loadVoiceStates() applyVoiceStates() sequencer?.addMetaEventListener { meta -> if(meta.type == 47){ @@ -103,16 +104,6 @@ actual class MediaPlayer actual constructor( channel?.controlChange(7, volumeInt) } } - /*val logVolume = if (level > 0 ){ - (Math.log10(level.toDouble() * 9 + 1) / Math.log10(10.0)).toFloat() - } else { - 0f - } - val volumeInt = (logVolume * 127).toInt().coerceIn(0, 127) - - synthetizer?.channels?.forEach { it?.controlChange(7, volumeInt) } - synthetizer?.channels?.forEach { it?.controlChange(11, volumeInt) } -*/ val mixer = AudioSystem.getMixer(null) val lines = mixer.sourceLines for (line in lines) { @@ -124,14 +115,6 @@ actual class MediaPlayer actual constructor( } } -// val msg = ShortMessage() -// val receiver = sequencer?.receiver -// for (i in 0 until 16) { -// val msg = ShortMessage() -// msg.setMessage(ShortMessage.CONTROL_CHANGE, i, 7, volumeInt) -// receiver?.send(msg, -1) -// } - } catch (e: Exception){ e.printStackTrace() } @@ -170,6 +153,7 @@ actual class MediaPlayer actual constructor( actual fun toggleVoice(index: Int) { voiceStates[index] = !voiceStates[index] + saveVoiceStates() applyVoiceStates() } @@ -204,11 +188,8 @@ actual class MediaPlayer actual constructor( } } actual fun getCurrentBPM(): Float { -// return sequencer?.tempoInBPM?.toInt() ?: 0 val currentFactor = sequencer?.tempoFactor ?: 1.0f -// val currentBPM = sequencer?.tempoInBPM ?: 120.0f val currentBPM = (120f * currentFactor) -// println("202: ${sequencer?.tempoInBPM} ${sequencer?.tempoFactor} ${sequencer?.tempoInMPQ}") return currentBPM } @@ -231,4 +212,20 @@ actual class MediaPlayer actual constructor( e.printStackTrace() } } + + private fun saveVoiceStates() { + val data = voiceStates.joinToString(",") + prefs.put("voice_states", data) + } + + private fun loadVoiceStates() { + val defaultValue = "true,true,true,true" + val savedData = prefs.get("voice_states", defaultValue) + + val states = savedData.split(",").map { it.toBoolean() } + for (i in 0 until 4) { + if (i < states.size) voiceStates[i] = states[i] + } + } + } \ No newline at end of file