From cfa381d3c0372ea6a2b501bbb9fd7cebb252f76a Mon Sep 17 00:00:00 2001 From: "hasinarak3@gmail.com" Date: Tue, 10 Mar 2026 16:09:54 +0300 Subject: [PATCH] Sync grid on tick position sequence & implement "$ DS" & resync when setting tempo --- .../kotlin/mg/dot/feufaro/midi/MidiPlayer.kt | 1 + .../mg/dot/feufaro/solfa/TimeUnitObject.kt | 23 +++---------- .../feufaro/viewmodel/SharedScreenModel.kt | 9 +++++ .../kotlin/mg/dot/feufaro/midi/MidiPlayer.kt | 33 ++++++++++--------- 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt index 41872c5..8d347e5 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt @@ -15,6 +15,7 @@ expect class FMediaPlayer(filename: String, onFinished: () -> Unit) { fun changeInstru(noInstru: Int) fun getCurrentPosition(): Long fun seekTo(position: Long) + fun seekToGrid(gridIndex: Int) fun setVolume(level: Float) fun setPointA() fun setPointB() diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt index d342c63..7e7019b 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt @@ -576,22 +576,9 @@ fun LazyVerticalGridTUO( val currentStanza = viewModel.stanza - val currentPos by sharedScreenModel.currentPos.collectAsState() - val duration by sharedScreenModel.duration.collectAsState() - val isPlay by sharedScreenModel.isPlay.collectAsState() val tuoTimestamps by sharedScreenModel.tuoTimestamps.collectAsState() - val displayedList = tuoList.drop(1) - val nbTotalDesRow = (displayedList.size-1) - val activeRowIndex = remember(currentPos, tuoTimestamps) { - val currentPosMicros = (currentPos * 1000).toLong() - val index = tuoTimestamps.indexOfLast { it <= currentPosMicros } - index.coerceIn(-1, nbTotalDesRow) - } - /*val activeRowIndex = if (duration > 0f) { - ((currentPos / duration) * nbTotalDesRow).toInt().coerceIn(0, nbTotalDesRow - 1) - } else { - -1 - }*/ + val activeRowIndex by sharedScreenModel.activeIndex.collectAsState() + val measures = tuoList.drop(1).chunked(gridColumnCount) // Avant column affichage: val metadataList = remember(tuoList) { @@ -729,10 +716,8 @@ fun LazyVerticalGridTUO( Box(modifier = Modifier.weight(1f) .combinedClickable( onClick = { - val targetMicros = tuoTimestamps.getOrNull(globalIndex) ?: 0L - sharedScreenModel.seekToTimestamp(targetMicros) -// sharedScreenModel.updatePositionFromPartition(globalIndex, nbTotalDesRow) - // println("tempNum ${oneTUO.numBlock} mesasindex ${measureIndex} & indexinM $indexInMeasure gridCount $gridColumnCount") +// println("je suis sur grille no: $globalIndex") + sharedScreenModel.seekToGrid(globalIndex) } , onDoubleClick = { val m = sharedScreenModel.getFullMarkers() diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt index b32de9d..4defeb0 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt @@ -152,6 +152,15 @@ class SharedScreenModel(private val fileRepository: FileRepository) : ScreenMode _activeIndex.value = index.coerceAtLeast(0) } } + fun updateActiveIndexByIndex(index: Int) { + val clamped = index.coerceAtLeast(0) + if (_activeIndex.value != clamped) { + _activeIndex.value = clamped + } + } + fun seekToGrid(gridIndex: Int) { + _mediaPlayer?.seekToGrid(gridIndex) + } fun getFullMarkers(): List { return _midiMarkersList.value 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 226ac9c..966baa7 100644 --- a/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt +++ b/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/midi/MidiPlayer.kt @@ -150,11 +150,11 @@ actual class FMediaPlayer actual constructor( ) println("Point d'orgue (\uD834\uDD10) mémorisée au grille n° $gridIndex") } - /*// DS + // DS dsGPattern.matches(marker.trim())-> { val target = if (lastSegno > 0) lastSegno else 0 var indx = if((last_grid - currentIndex) <= 0) { - currentIndex -1 + currentIndex - 1 } else currentIndex navigationSteps.add( NavigationStep( @@ -175,7 +175,7 @@ actual class FMediaPlayer actual constructor( targetGrid = target )) println("Lien DS créé : Saut immédiat à $gridIndex vers Segno $target") - }*/ + } // DC dcGPattern.matches(marker.trim()) -> { @@ -217,8 +217,8 @@ actual class FMediaPlayer actual constructor( sharedScreenModel.activeIndex.collect { currentIndex -> val availableIndices = navigationSteps.map { it.gridIndex } - println("bpm:$targetBpm _ ${sequencer?.tempoInBPM}") - println("MONITOR : Reçu Index $currentIndex | Index en mémoire : $availableIndices ") +// println("bpm:$targetBpm _ ${sequencer?.tempoInBPM}") +// println("MONITOR : Reçu Index $currentIndex | Index en mémoire : $availableIndices ") if (sequencer?.isRunning == true) { if (Math.abs(sequencer!!.tempoInBPM - targetBpm) > 0.1) { @@ -282,22 +282,20 @@ actual class FMediaPlayer actual constructor( syncJob = playerScope.launch(Dispatchers.Default) { while (isActive) { if (sequencer?.isRunning == true) { - val posMs = (sequencer?.microsecondPosition ?: 0L) / 1000 - sharedScreenModel.updateActiveIndex(posMs) + val resolution = sequencer?.sequence?.resolution?.toLong() ?: 480L + val gridIndex = (sequencer!!.tickPosition / resolution).toInt() + sharedScreenModel.updateActiveIndexByIndex(gridIndex) } delay(20) } } } - private fun seekToGrid(gridIndex: Int) { + actual fun seekToGrid(gridIndex: Int) { val resolution = sequencer?.sequence?.resolution?.toDouble() ?: 480.0 - val tick = gridIndex.toDouble() * resolution + val tick = (gridIndex.toDouble() * resolution).toLong() + sequencer?.tickPosition = tick - val bpm = sequencer?.tempoInBPM ?: targetBpm - val usPerTick = (60_000_000.0 / bpm) / resolution - val targetMicros = (tick * usPerTick).toLong() - - sequencer?.microsecondPosition = targetMicros + applyBpm() } actual fun play(){ @@ -337,7 +335,7 @@ actual class FMediaPlayer actual constructor( for (tick in 0..totalTicks step step) { val microsecond = (tick * usPerTick).toLong() timestamps.add(microsecond) -// println("Note detectée au Tick: ${tick} -> Temps: ${microsecond / 1000} ms") +// println("Note detectée au grille: ${tick/60} -> Temps: ${microsecond / 1000} ms") } // Détection de tous les note y compris les /2 /4 temps @@ -359,6 +357,7 @@ actual class FMediaPlayer actual constructor( }*/ val sortedList = timestamps.sorted() sharedScreenModel.updateTimestamps(sortedList) +// println("SUR tempo $targetBpm Synchronization terminer et mis à jour") } actual fun stop(){ @@ -497,6 +496,10 @@ actual class FMediaPlayer actual constructor( this.targetBpm = bpm sequencer?.tempoInBPM = bpm boundModel?.let { modele -> + val seq = sequencer?.sequence + if (seq != null) { + syncTuoWithMidi(seq, modele) + } prepareNavigation(modele) } println("Tempo réglé à : $bpm BPM")