implement realtime solfa highlighting with sync
This commit is contained in:
parent
c9fd0fe81b
commit
4e8866a4e7
5 changed files with 260 additions and 113 deletions
|
|
@ -149,6 +149,7 @@ object ScreenSolfa : Screen {
|
||||||
LazyVerticalGridTUO(
|
LazyVerticalGridTUO(
|
||||||
gridTUOData,
|
gridTUOData,
|
||||||
gridWidthPx = gridWidthPx,
|
gridWidthPx = gridWidthPx,
|
||||||
|
sharedScreenModel = sharedScreenModel,
|
||||||
onGridWidthMeasured = { width -> gridWidthPx = width }
|
onGridWidthMeasured = { width -> gridWidthPx = width }
|
||||||
)
|
)
|
||||||
FlowRow(
|
FlowRow(
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.style.BaselineShift
|
import androidx.compose.ui.text.style.BaselineShift
|
||||||
import androidx.compose.ui.text.withStyle
|
import androidx.compose.ui.text.withStyle
|
||||||
|
import SharedScreenModel
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
val FEUFAROO_TRIOLET_COLOR = Color.DarkGray
|
val FEUFAROO_TRIOLET_COLOR = Color.DarkGray
|
||||||
val FEUFAROO_KEY_CHANGE_COLOR = Color.Blue
|
val FEUFAROO_KEY_CHANGE_COLOR = Color.Blue
|
||||||
|
|
@ -228,13 +231,14 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?, co
|
||||||
fun TimeUnitComposable(
|
fun TimeUnitComposable(
|
||||||
tuo: TimeUnitObject,
|
tuo: TimeUnitObject,
|
||||||
stanzaNumber: Int,
|
stanzaNumber: Int,
|
||||||
gridColumnCount: Int
|
gridColumnCount: Int,
|
||||||
|
gridActive: Boolean
|
||||||
) {
|
) {
|
||||||
val col = if (tuo.getNum() % 2 == 0) Color(0xff, 0xfa, 0xf7) else Color(0xfb, 0xf3, 0xff)
|
val col = if (tuo.getNum() % 2 == 0) Color(0xff, 0xfa, 0xf7) else Color(0xfb, 0xf3, 0xff)
|
||||||
val currentDensity = LocalDensity.current
|
val currentDensity = LocalDensity.current
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(col)
|
.background(if(gridActive) Color.Cyan.copy(alpha = 0.5f) else col)
|
||||||
) {
|
) {
|
||||||
if (TimeUnitObject._hasMarker) {
|
if (TimeUnitObject._hasMarker) {
|
||||||
val lineHeight = 20.sp
|
val lineHeight = 20.sp
|
||||||
|
|
@ -511,6 +515,7 @@ fun AutoResizingText(
|
||||||
fun LazyVerticalGridTUO(
|
fun LazyVerticalGridTUO(
|
||||||
viewModel: GridTUOData,
|
viewModel: GridTUOData,
|
||||||
gridWidthPx: Int,
|
gridWidthPx: Int,
|
||||||
|
sharedScreenModel: SharedScreenModel,
|
||||||
onGridWidthMeasured: (Int) -> Unit,
|
onGridWidthMeasured: (Int) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
|
|
@ -547,6 +552,16 @@ fun LazyVerticalGridTUO(
|
||||||
|
|
||||||
val currentStanza = viewModel.stanza
|
val currentStanza = viewModel.stanza
|
||||||
|
|
||||||
|
val currentPos by sharedScreenModel.currentPos.collectAsState()
|
||||||
|
val duration by sharedScreenModel.duration.collectAsState()
|
||||||
|
val isPlay by sharedScreenModel.isPlay.collectAsState()
|
||||||
|
val displayedList = tuoList.drop(1)
|
||||||
|
val nbTotalDesRow = displayedList.size
|
||||||
|
val activeRowIndex = if (duration > 0f) {
|
||||||
|
((currentPos / duration) * nbTotalDesRow).toInt().coerceIn(0, nbTotalDesRow - 1)
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
}
|
||||||
FlowRow(
|
FlowRow(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|
||||||
|
|
@ -556,12 +571,16 @@ fun LazyVerticalGridTUO(
|
||||||
// state = lazyGridState
|
// state = lazyGridState
|
||||||
) {
|
) {
|
||||||
tuoList.drop(n=1).forEachIndexed { relativeIndex, oneTUO ->
|
tuoList.drop(n=1).forEachIndexed { relativeIndex, oneTUO ->
|
||||||
|
val isActive = (relativeIndex == activeRowIndex)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth(flowRowSize)
|
.fillMaxWidth(flowRowSize)
|
||||||
|
.background(Color.Transparent)
|
||||||
.combinedClickable(
|
.combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
println("Clicked: ${oneTUO.numBlock} / relative index: $relativeIndex FL $flowRowSize GC $gridColumnCount")
|
sharedScreenModel.updatePositionFromPartition(relativeIndex, nbTotalDesRow)
|
||||||
|
println("590: relative $relativeIndex active? $isActive")
|
||||||
|
println("TimeUnitObj:566 Clicked: ${oneTUO.numBlock} / relative index: $relativeIndex FL $flowRowSize totaRow $nbTotalDesRow")
|
||||||
} ,
|
} ,
|
||||||
onDoubleClick = {
|
onDoubleClick = {
|
||||||
println("Double-Clicked: ${oneTUO.numBlock} / relative index: $relativeIndex")
|
println("Double-Clicked: ${oneTUO.numBlock} / relative index: $relativeIndex")
|
||||||
|
|
@ -571,7 +590,8 @@ fun LazyVerticalGridTUO(
|
||||||
TimeUnitComposable(
|
TimeUnitComposable(
|
||||||
tuo = oneTUO,
|
tuo = oneTUO,
|
||||||
currentStanza,
|
currentStanza,
|
||||||
gridColumnCount
|
gridColumnCount,
|
||||||
|
gridActive = isActive
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,18 +74,23 @@ fun MainScreenWithDrawer(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var isDragging by remember { mutableStateOf(false) }
|
//var isDragging by remember { mutableStateOf(false) }
|
||||||
var isPlay by remember { mutableStateOf(false) }
|
//var isPlay by remember { mutableStateOf(false) }
|
||||||
var isPos by remember { mutableStateOf(true) }
|
//var isPos by remember { mutableStateOf(true) }
|
||||||
var isPlayMid by remember { mutableStateOf(false) }
|
var isPlayMid by remember { mutableStateOf(false) }
|
||||||
var currentPos by remember { mutableStateOf(0f) }
|
//var currentPos by remember { mutableStateOf(0f) }
|
||||||
var duration by remember { mutableStateOf(0f) }
|
val isPlay by sharedScreenModel.isPlay.collectAsState()
|
||||||
|
val isPos by sharedScreenModel.isPos.collectAsState()
|
||||||
|
var isDragging = sharedScreenModel.isDragging
|
||||||
|
val currentPos by sharedScreenModel.currentPos.collectAsState()
|
||||||
|
val duration by sharedScreenModel.duration.collectAsState()
|
||||||
var midiFile = "whawyd3.mid"
|
var midiFile = "whawyd3.mid"
|
||||||
var refreshTrigeer by remember { mutableStateOf(0)}
|
var refreshTrigeer by remember { mutableStateOf(0)}
|
||||||
|
|
||||||
var volumelevel by remember { mutableStateOf(0.8f) }
|
val volumelevel by sharedScreenModel.volumeLevel.collectAsState()
|
||||||
|
|
||||||
val mediaPlayer = remember(refreshTrigeer) {
|
val player = sharedScreenModel.mediaPlayer
|
||||||
|
/*val mediaPlayer = remember(refreshTrigeer) {
|
||||||
MediaPlayer(filename = midiFile, onFinished = {
|
MediaPlayer(filename = midiFile, onFinished = {
|
||||||
isPos = true
|
isPos = true
|
||||||
isPlay = false
|
isPlay = false
|
||||||
|
|
@ -94,9 +99,18 @@ val mediaPlayer = remember(refreshTrigeer) {
|
||||||
println("fin de lecture du whawyd3.mid")
|
println("fin de lecture du whawyd3.mid")
|
||||||
|
|
||||||
}).apply { setVolume(volumelevel) }
|
}).apply { setVolume(volumelevel) }
|
||||||
|
}*/
|
||||||
|
LaunchedEffect(isPlay, isPos) {
|
||||||
|
if (isPlay && !isPos) {
|
||||||
|
// while (isPlay && !isPos) {
|
||||||
|
while (true) {
|
||||||
|
sharedScreenModel.updateProgress()
|
||||||
|
delay(100)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
/*LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
||||||
if (isPlay && !isPos) {
|
if (isPlay && !isPos) {
|
||||||
val d = mediaPlayer.getDuration().toFloat()
|
val d = mediaPlayer.getDuration().toFloat()
|
||||||
if (d > 0) duration = d
|
if (d > 0) duration = d
|
||||||
|
|
@ -108,13 +122,16 @@ LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
||||||
delay(100)
|
delay(100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
LaunchedEffect(isSearchActive) {
|
LaunchedEffect(isSearchActive) {
|
||||||
if (isSearchActive) {
|
if (isSearchActive) {
|
||||||
focusRequester.requestFocus()
|
focusRequester.requestFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
sharedScreenModel.loadNewSong("whawyd3.mid")
|
||||||
|
}
|
||||||
ModalNavigationDrawer(drawerState = drawerState, drawerContent = {
|
ModalNavigationDrawer(drawerState = drawerState, drawerContent = {
|
||||||
SimpleDrawerContent(
|
SimpleDrawerContent(
|
||||||
items,
|
items,
|
||||||
|
|
@ -128,11 +145,12 @@ LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
||||||
onScannerButtonClick()
|
onScannerButtonClick()
|
||||||
},
|
},
|
||||||
onSongSelected = { newSong ->
|
onSongSelected = { newSong ->
|
||||||
mediaPlayer?.stop()
|
// mediaPlayer?.stop()
|
||||||
isPos = true
|
// isPos = true
|
||||||
isPlay = false
|
// isPlay = false
|
||||||
currentPos = 0f
|
// currentPos = 0f
|
||||||
refreshTrigeer++
|
sharedScreenModel.loadNewSong("whawyd3.mid")
|
||||||
|
// refreshTrigeer++
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}, content = {
|
}, content = {
|
||||||
|
|
@ -232,10 +250,11 @@ LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
isPlayMid = !isPlayMid
|
isPlayMid = !isPlayMid
|
||||||
if(mediaPlayer.getCurrentPosition() != 0L) {
|
// if(isPlayMid) sharedScreenModel.stopMidi()
|
||||||
mediaPlayer?.seekTo(0)
|
// if(mediaPlayer.getCurrentPosition() != 0L) {
|
||||||
mediaPlayer?.stop()
|
// mediaPlayer?.seekTo(0)
|
||||||
}
|
// mediaPlayer?.stop()
|
||||||
|
// }
|
||||||
}, modifier = Modifier.alpha(0.45f)
|
}, modifier = Modifier.alpha(0.45f)
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
|
|
@ -250,6 +269,7 @@ LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
||||||
onClick = {
|
onClick = {
|
||||||
isExpanded = !isExpanded
|
isExpanded = !isExpanded
|
||||||
refreshTrigeer++
|
refreshTrigeer++
|
||||||
|
sharedScreenModel.loadNewSong("whawyd3.mid")
|
||||||
}, modifier = Modifier.alpha(0.45f)
|
}, modifier = Modifier.alpha(0.45f)
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
|
|
@ -267,13 +287,14 @@ LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxWidth(0.9f)
|
modifier = Modifier.fillMaxWidth(0.9f)
|
||||||
) {
|
) {
|
||||||
|
if(player != null) {
|
||||||
MidiControlPanel(
|
MidiControlPanel(
|
||||||
isPause = isPos,
|
isPause = isPos,
|
||||||
currentPos = currentPos,
|
currentPos = currentPos,
|
||||||
volume = volumelevel,
|
volume = volumelevel,
|
||||||
duration = duration,
|
duration = duration,
|
||||||
onPlayPauseClick = {
|
onPlayPauseClick = {
|
||||||
if(isPlay){
|
sharedScreenModel.togglePlayPause()/*if(isPlay){
|
||||||
mediaPlayer?.pause()
|
mediaPlayer?.pause()
|
||||||
isPlay = false
|
isPlay = false
|
||||||
isPos = true
|
isPos = true
|
||||||
|
|
@ -284,8 +305,8 @@ LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
||||||
mediaPlayer?.play()
|
mediaPlayer?.play()
|
||||||
mediaPlayer?.setVolume(volumelevel)
|
mediaPlayer?.setVolume(volumelevel)
|
||||||
isPlay = true
|
isPlay = true
|
||||||
isPos = false
|
isPos = false*/
|
||||||
}
|
},
|
||||||
/* if(!isPlay) {
|
/* if(!isPlay) {
|
||||||
if (currentPos == 0f) mediaPlayer.seekTo(0)
|
if (currentPos == 0f) mediaPlayer.seekTo(0)
|
||||||
mediaPlayer?.play()
|
mediaPlayer?.play()
|
||||||
|
|
@ -297,36 +318,38 @@ LaunchedEffect(isPlay, isPos, mediaPlayer) {
|
||||||
isPos = true
|
isPos = true
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
println("je clique pause = $isPos play = $isPlay")
|
// println("je clique pause = ${sharedScreenModel.isPlay} play = ${sharedScreenModel.isPos}")
|
||||||
// if(isPos) {
|
// if(isPos) {
|
||||||
// mediaPlayer.play()
|
// mediaPlayer.play()
|
||||||
// isPos = false
|
// isPos = false
|
||||||
// } else {
|
// } else {
|
||||||
// mediaPlayer.pause()
|
// mediaPlayer.pause()
|
||||||
// isPos = true
|
// isPos = true
|
||||||
// }
|
// }
|
||||||
/*if (isPlayMid) {
|
/*if (isPlayMid) {
|
||||||
// mediaPlayer.seekTo(0f.toLong())
|
// mediaPlayer.seekTo(0f.toLong())
|
||||||
mediaPlayer.play()
|
mediaPlayer.play()
|
||||||
isPlayMid = false
|
isPlayMid = false
|
||||||
|
}
|
||||||
}*/
|
}*/
|
||||||
},
|
onSeek = { newPos -> // currentPos = newPos
|
||||||
onSeek = { newPos ->
|
sharedScreenModel.setDragging(true)
|
||||||
currentPos = newPos
|
sharedScreenModel.seekTo(newPos)
|
||||||
isDragging = true
|
|
||||||
mediaPlayer.seekTo(newPos.toLong())
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
delay(100)
|
delay(100)
|
||||||
isDragging = false
|
sharedScreenModel.setDragging(false)
|
||||||
}
|
}
|
||||||
|
println("DrawerUI:335: mihetsika $newPos")
|
||||||
},
|
},
|
||||||
mediaPlayer = mediaPlayer,
|
mediaPlayer = player,
|
||||||
onVolumeChange = { newVolume ->
|
onVolumeChange = { newVolume -> // volumelevel = newVolume
|
||||||
volumelevel = newVolume
|
sharedScreenModel.setVolume(newVolume)
|
||||||
mediaPlayer?.setVolume(newVolume)
|
|
||||||
println("Changement volume $newVolume -l $volumelevel")
|
println("Changement volume $newVolume -l $volumelevel")
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
Text("Sélectionner un morceau")
|
||||||
|
}
|
||||||
/*Row(
|
/*Row(
|
||||||
modifier = Modifier.align(Alignment.Center).padding(16.dp),
|
modifier = Modifier.align(Alignment.Center).padding(16.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt
|
// commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import cafe.adriel.voyager.core.model.ScreenModel
|
import cafe.adriel.voyager.core.model.ScreenModel
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -11,8 +13,9 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import mg.dot.feufaro.data.DrawerItem
|
import mg.dot.feufaro.data.DrawerItem
|
||||||
import mg.dot.feufaro.solfa.TimeUnitObject
|
|
||||||
import mg.dot.feufaro.data.getDrawerItems
|
import mg.dot.feufaro.data.getDrawerItems
|
||||||
|
import mg.dot.feufaro.solfa.TimeUnitObject
|
||||||
|
import mg.dot.feufaro.midi.MediaPlayer
|
||||||
|
|
||||||
class SharedScreenModel() : ScreenModel {
|
class SharedScreenModel() : ScreenModel {
|
||||||
private val _nextLabel = MutableStateFlow<String>("Next ...")
|
private val _nextLabel = MutableStateFlow<String>("Next ...")
|
||||||
|
|
@ -90,7 +93,113 @@ class SharedScreenModel() : ScreenModel {
|
||||||
}
|
}
|
||||||
fun updateSearchTxt(searchValue: String) {
|
fun updateSearchTxt(searchValue: String) {
|
||||||
_searchTitle.value = searchValue
|
_searchTitle.value = searchValue
|
||||||
} fun appendData(otherData: String) {
|
}
|
||||||
|
|
||||||
|
private var _mediaPlayer by mutableStateOf<MediaPlayer?>(null)
|
||||||
|
val mediaPlayer: MediaPlayer? get() = _mediaPlayer
|
||||||
|
|
||||||
|
private val _isPlay = MutableStateFlow(false)
|
||||||
|
val isPlay = _isPlay.asStateFlow()
|
||||||
|
|
||||||
|
private val _isPos = MutableStateFlow(true)
|
||||||
|
val isPos = _isPos.asStateFlow()
|
||||||
|
|
||||||
|
private val _isDragging = MutableStateFlow(true)
|
||||||
|
val isDragging = _isDragging.asStateFlow()
|
||||||
|
|
||||||
|
private val _currentPos = MutableStateFlow(0f)
|
||||||
|
val currentPos = _currentPos.asStateFlow()
|
||||||
|
private val _duration = MutableStateFlow(0f)
|
||||||
|
val duration = _duration.asStateFlow()
|
||||||
|
|
||||||
|
private val _volumeLevel = MutableStateFlow(0.8f)
|
||||||
|
val volumeLevel = _volumeLevel.asStateFlow()
|
||||||
|
|
||||||
|
private val _isPlayMid = MutableStateFlow(false)
|
||||||
|
val isPlayMid = _isPlayMid.asStateFlow()
|
||||||
|
|
||||||
|
private var midiFile = "whawyd3.mid"
|
||||||
|
|
||||||
|
fun loadNewSong(newMidiFile: String) {
|
||||||
|
_mediaPlayer?.stop()
|
||||||
|
_isPos.value = true
|
||||||
|
_isPlay.value = false
|
||||||
|
_currentPos.value = 0f
|
||||||
|
_mediaPlayer = MediaPlayer(filename = newMidiFile, onFinished = {
|
||||||
|
_isPos.value = true
|
||||||
|
_isPlay.value = false
|
||||||
|
_currentPos.value = 0f
|
||||||
|
println("fin de lecture du Midi $newMidiFile")
|
||||||
|
})
|
||||||
|
println("New media Player crée $newMidiFile")
|
||||||
|
}
|
||||||
|
// val mediaPlayer =
|
||||||
|
|
||||||
|
fun togglePlayPause() {
|
||||||
|
_mediaPlayer?.let { player ->
|
||||||
|
if (_isPlay.value) {
|
||||||
|
_isPlay.value = false
|
||||||
|
_isPos.value = true
|
||||||
|
player.pause()
|
||||||
|
} else {
|
||||||
|
_isPlay.value = true
|
||||||
|
_isPos.value = false
|
||||||
|
player.play()
|
||||||
|
player.setVolume(_volumeLevel.value)
|
||||||
|
if(currentPos.value == 0f) {
|
||||||
|
player.seekTo(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println("128: Status de isPlay ${_isPlay.value} \nisPos ${_isPos.value} \ncurrentPos ${_currentPos.value} \n volume ${_volumeLevel.value}")
|
||||||
|
// _isPlay.value = !_isPlay.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun stopMidi() {
|
||||||
|
_mediaPlayer?.let { player ->
|
||||||
|
_isPlay.value = false
|
||||||
|
_isPos.value = true
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun seekTo(pos: Float) {
|
||||||
|
_currentPos.value = pos
|
||||||
|
_mediaPlayer?.let { player ->
|
||||||
|
player.seekTo(pos.toLong())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setDragging(dragState: Boolean) {
|
||||||
|
_isDragging.value = dragState
|
||||||
|
}
|
||||||
|
fun setVolume(level: Float) {
|
||||||
|
_volumeLevel.value = level
|
||||||
|
_mediaPlayer?.let { player ->
|
||||||
|
player.setVolume(level) }
|
||||||
|
}
|
||||||
|
fun updateProgress(){
|
||||||
|
_mediaPlayer?.let { player->
|
||||||
|
if (_isPlay.value) {
|
||||||
|
val p = player.getCurrentPosition().toFloat()
|
||||||
|
val d = player.getDuration().toFloat()
|
||||||
|
|
||||||
|
if (p >= 0) _currentPos.value = p
|
||||||
|
if ((d > 0) && _duration.value != d) _duration.value = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var currentNoteIndex by mutableStateOf(0f)
|
||||||
|
|
||||||
|
fun updatePositionFromPartition(index: Int, totalRow: Int) {
|
||||||
|
val duration = _duration.value
|
||||||
|
if(totalRow > 0) {
|
||||||
|
currentNoteIndex = index.toFloat()
|
||||||
|
val newPos = (currentNoteIndex / totalRow.toFloat()) * duration
|
||||||
|
seekTo(newPos)
|
||||||
|
println("Shared:196 currentNoteIndex $currentNoteIndex, Index $index et curret = ${_currentPos.value}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun appendData(otherData: String) {
|
||||||
_nextLabel.value += otherData
|
_nextLabel.value += otherData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@ import java.io.ByteArrayInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.sound.midi.MidiSystem
|
import javax.sound.midi.MidiSystem
|
||||||
import javax.sound.midi.Sequencer
|
import javax.sound.midi.Sequencer
|
||||||
import javax.sound.midi.ShortMessage
|
import javax.sound.midi.Synthesizer //import javax.sound.midi.ShortMessage
|
||||||
import javax.sound.midi.Synthesizer
|
//import javax.sound.midi.Synthesizer
|
||||||
import javax.sound.sampled.*
|
import javax.sound.sampled.AudioFormat
|
||||||
|
import javax.sound.sampled.AudioSystem
|
||||||
|
import javax.sound.sampled.FloatControl
|
||||||
|
|
||||||
//private var sequencer: javax.sound.midi.Sequencer?= null
|
//private var sequencer: javax.sound.midi.Sequencer?= null
|
||||||
actual class MediaPlayer actual constructor(
|
actual class MediaPlayer actual constructor(
|
||||||
|
|
@ -20,11 +22,12 @@ actual class MediaPlayer actual constructor(
|
||||||
private var sequencer: Sequencer? = try {
|
private var sequencer: Sequencer? = try {
|
||||||
MidiSystem.getSequencer(false)
|
MidiSystem.getSequencer(false)
|
||||||
} catch (e: Exception){
|
} catch (e: Exception){
|
||||||
|
|
||||||
println("Erreur impossible obtenir ${e.message}")
|
println("Erreur impossible obtenir ${e.message}")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
private var synthetizer: Synthesizer? = MidiSystem.getSynthesizer()
|
private var synthetizer = MidiSystem.getSynthesizer() as Synthesizer?
|
||||||
|
|
||||||
private var pointA: Long = -1L
|
private var pointA: Long = -1L
|
||||||
private var pointB: Long = -1L
|
private var pointB: Long = -1L
|
||||||
|
|
@ -37,12 +40,15 @@ actual class MediaPlayer actual constructor(
|
||||||
private var currentTempo: Float = 1.0f
|
private var currentTempo: Float = 1.0f
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
try {
|
||||||
sequencer?.open()
|
sequencer?.open()
|
||||||
synthetizer?.open()
|
synthetizer?.open()
|
||||||
|
|
||||||
val transmitter = sequencer?.transmitter
|
val transmitter = sequencer?.transmitter
|
||||||
val synthReceiver = synthetizer?.receiver
|
val synthReceiver = synthetizer?.receiver
|
||||||
transmitter?.receiver = synthReceiver
|
transmitter?.receiver = synthReceiver
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
val file = File(filename)
|
val file = File(filename)
|
||||||
if (file.exists()){
|
if (file.exists()){
|
||||||
|
|
@ -55,6 +61,7 @@ actual class MediaPlayer actual constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun play(){
|
actual fun play(){
|
||||||
if (sequencer!!.isOpen){
|
if (sequencer!!.isOpen){
|
||||||
sequencer?.start()
|
sequencer?.start()
|
||||||
|
|
@ -67,7 +74,8 @@ actual class MediaPlayer actual constructor(
|
||||||
actual fun stop(){
|
actual fun stop(){
|
||||||
sequencer?.stop()
|
sequencer?.stop()
|
||||||
sequencer?.microsecondPosition = 0
|
sequencer?.microsecondPosition = 0
|
||||||
// disableLoop()
|
clearLoop()
|
||||||
|
release()
|
||||||
}
|
}
|
||||||
actual fun getDuration(): Long {
|
actual fun getDuration(): Long {
|
||||||
return (sequencer?.microsecondLength ?: 0L) / 1000
|
return (sequencer?.microsecondLength ?: 0L) / 1000
|
||||||
|
|
@ -80,7 +88,7 @@ actual class MediaPlayer actual constructor(
|
||||||
}
|
}
|
||||||
fun release() {
|
fun release() {
|
||||||
sequencer?.close()
|
sequencer?.close()
|
||||||
// synthetizer?.close()
|
synthetizer?.close()
|
||||||
}
|
}
|
||||||
actual fun setVolume(level: Float) {
|
actual fun setVolume(level: Float) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -209,32 +217,18 @@ actual class MediaPlayer actual constructor(
|
||||||
sequencer?.tempoFactor = factor
|
sequencer?.tempoFactor = factor
|
||||||
}
|
}
|
||||||
fun getTempo(): Float = currentTempo
|
fun getTempo(): Float = currentTempo
|
||||||
}
|
private val MS8PER_NOTE = 500L
|
||||||
|
|
||||||
|
fun seekToNote(index: Int) {
|
||||||
/*
|
try {
|
||||||
|
sequencer?.let { sequencer ->
|
||||||
private var sequencer: javax.sound.midi.Sequencer?= null
|
if (sequencer.isOpen) {
|
||||||
actual fun MidiPlayer(filename: String, onFinished: () -> Unit) {
|
val targetPos = index * MS8PER_NOTE * 1000
|
||||||
val file = File(filename)
|
sequencer.microsecondPosition = targetPos
|
||||||
if (file.exists()){
|
|
||||||
StopMidi()
|
|
||||||
sequencer = MidiSystem.getSequencer().apply {
|
|
||||||
open()
|
|
||||||
sequence = MidiSystem.getSequence(file)
|
|
||||||
addMetaEventListener { meta ->
|
|
||||||
if(meta.type == 47){
|
|
||||||
onFinished()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
start()
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun StopMidi() {
|
|
||||||
if(sequencer?.isRunning == true){
|
|
||||||
sequencer?.stop()
|
|
||||||
sequencer?.close()
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue