Hasinjato : FilePicker
This commit is contained in:
parent
dfbdb2da2c
commit
bba28fd7c1
6 changed files with 272 additions and 103 deletions
|
|
@ -0,0 +1,8 @@
|
|||
package mg.dot.feufaro
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
expect fun launchFilePicker(
|
||||
mimeTypes: Array<String>,
|
||||
onFileSelected: (path: String?) -> Unit
|
||||
): Unit
|
||||
|
|
@ -61,7 +61,9 @@ object ScreenSolfa : Screen {
|
|||
val gridTUOData = GridTUOData(measure, tuoList, stanza)
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val scrollState = rememberScrollState()
|
||||
Box(Modifier.fillMaxSize()
|
||||
|
||||
Box(
|
||||
Modifier.fillMaxSize()
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
|
|
@ -122,6 +124,10 @@ object ScreenSolfa : Screen {
|
|||
gridWidthPx = gridWidthPx,
|
||||
onGridWidthMeasured = { width -> gridWidthPx = width }
|
||||
)
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
MGButton(onClick = {
|
||||
//showContent = !showContent
|
||||
|
||||
|
|
@ -130,6 +136,24 @@ object ScreenSolfa : Screen {
|
|||
val nextLabel: String by sharedScreenModel.nextLabel.collectAsState()
|
||||
Text(nextLabel)
|
||||
}
|
||||
MGButton(onClick = {
|
||||
/*println("Load btn clicked")
|
||||
launchFilePicker(
|
||||
mimeTypes = arrayOf("text/plain"),
|
||||
onFileSelected = { path ->
|
||||
if (path != null) {
|
||||
println("fichier $path");
|
||||
} else {
|
||||
println("Pas de dichier")
|
||||
}
|
||||
}
|
||||
)*/
|
||||
solfaScreenModel.loadCustomFile()
|
||||
}) {
|
||||
val loadFile: String by sharedScreenModel.loadFile.collectAsState()
|
||||
Text(loadFile)
|
||||
}
|
||||
}
|
||||
FlowRow(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
.windowInsetsPadding(WindowInsets.safeDrawing)
|
||||
|
|
@ -168,6 +192,7 @@ object ScreenSolfa : Screen {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(ObjectStreamException::class) // C'est une méthode de sérialisation Java, donc l'exception est nécessaire
|
||||
private fun readResolve(): Any {
|
||||
return this // Toujours retourner l'instance unique de ce singleton
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import mg.dot.feufaro.FileRepository
|
||||
import mg.dot.feufaro.launchFilePicker
|
||||
import mg.dot.feufaro.midi.MidiPitch
|
||||
import mg.dot.feufaro.midi.MidiWriterKotlin
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
private var refrainBeginsAt = -1
|
||||
private var smartLyricsType = "L"
|
||||
private val pitches = mutableListOf<MidiPitch>()
|
||||
|
||||
companion object {
|
||||
var currentFile = ""
|
||||
val REGEX_SHIFT_PAREN_UPWARD = Regex("([^a-yA-Y\\(\\[]+)([\\)\\]])")
|
||||
|
|
@ -36,7 +38,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
val REGEX_PARSE_META = Regex("\\|(?=[a-z]:)")
|
||||
val REGEX_LYRICS_COMMENT = Regex("\\$\\{([^\\}][^:]*:([^\\}]*))\\}|\\$\\{R!\\}")
|
||||
val REGEX_LYRICS_REPETITION = Regex("_(\\d+)")
|
||||
val REGEX_VOWELS_STAGE1 = Regex("[aeiouyòàéìỳ](?![,;\\.\\-:!\\?\\}»_\"]*([ aeiouyòàéìỳ/]|_[1-9]))", RegexOption.IGNORE_CASE)
|
||||
val REGEX_VOWELS_STAGE1 =
|
||||
Regex("[aeiouyòàéìỳ](?![,;\\.\\-:!\\?\\}»_\"]*([ aeiouyòàéìỳ/]|_[1-9]))", RegexOption.IGNORE_CASE)
|
||||
val REGEX_VOWELS_STAGE2 = Regex("(?<=[aeiouyòàéìỳ])_([,;\\.\\-:!\\?\\}»_\"]+)", RegexOption.IGNORE_CASE)
|
||||
val REGEX_VOWELS_STAGE3 = Regex("_([\\?\\!:,;\\.»\\)]+|(\\$\\{[^\\}]*\\})+)")
|
||||
val REGEX_MALAGASY_MN = Regex("([aeio])_([nm])([tdjkbp])")
|
||||
|
|
@ -45,6 +48,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
val REGEX_COMMENT = Regex("\\$\\{[^\\}]*\\}")
|
||||
val REGEX_STRIP_DC = Regex("\\$\\{D[^:]*:[^\\}]*\\}")
|
||||
}
|
||||
|
||||
var nextTIndex: Int = -1
|
||||
var nextNIndex: Int = -1
|
||||
var nextLIndex: Int = -1
|
||||
|
|
@ -75,7 +79,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
templateCharArray.forEach { // D.-R
|
||||
when (it) {
|
||||
'D', 'R', 'M', 'F', 'S', 'L', 'T',
|
||||
'd', 'r', 'm', 'f', 's', 'l', 't', -> {
|
||||
'd', 'r', 'm', 'f', 's', 'l', 't',
|
||||
-> {
|
||||
nextNIndex++
|
||||
if (!inGroup) {
|
||||
nextLIndex++
|
||||
|
|
@ -83,18 +88,22 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
unitObject.addLyrics(L[nextLIndex])
|
||||
}
|
||||
}
|
||||
N.forEachIndexed { voiceNumber, pOneVoiceNote -> run {
|
||||
N.forEachIndexed { voiceNumber, pOneVoiceNote ->
|
||||
run {
|
||||
unitObject.addNote(voiceNumber, pOneVoiceNote.oneVoiceNote, nextNIndex, nextMarker)
|
||||
}
|
||||
}
|
||||
nextMarker = '0'
|
||||
}
|
||||
'.', ',', ->
|
||||
|
||||
'.', ',' ->
|
||||
unitObject.addMarker(it)
|
||||
|
||||
'-', 'Z', 'z', 'w' ->
|
||||
N.indices.forEach { voiceNumber ->
|
||||
unitObject.addBlank(voiceNumber, it)
|
||||
}
|
||||
|
||||
'(', '[' -> {
|
||||
nextLIndex++
|
||||
if (L.size > nextLIndex) {
|
||||
|
|
@ -102,6 +111,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
inGroup = true
|
||||
}
|
||||
|
||||
')', ']' -> {
|
||||
inGroup = false
|
||||
}
|
||||
|
|
@ -112,11 +122,13 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
nextTimeUnitObject()
|
||||
}
|
||||
|
||||
fun loadSolfa() {
|
||||
val sourceFileName: String = sharedScreenModel.currentPlayed()
|
||||
sharedScreenModel.reset()
|
||||
parse(sourceFileName)
|
||||
}
|
||||
|
||||
fun loadNextInPlaylist() {
|
||||
val playlist = sharedScreenModel.playlist.value
|
||||
if (playlist.isNotEmpty()) {
|
||||
|
|
@ -124,6 +136,24 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
loadSolfa()
|
||||
}
|
||||
}
|
||||
|
||||
fun loadFile() {
|
||||
println("Load btn clicked")
|
||||
launchFilePicker(
|
||||
mimeTypes = arrayOf("text/plain"),
|
||||
onFileSelected = { path ->
|
||||
if (path != null) {
|
||||
println("fichier $path");
|
||||
sharedScreenModel.reset()
|
||||
parse(path)
|
||||
//loadSolfa()
|
||||
} else {
|
||||
println("Pas de dichier")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun parse(sourceFile: String) {
|
||||
currentFile = sourceFile
|
||||
val parseScope = CoroutineScope(Dispatchers.Default)
|
||||
|
|
@ -173,6 +203,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
private fun rearrangeNote(noteString: String, infiniteIter: Int = 0): String {
|
||||
var result: String = noteString
|
||||
result = result.replace(REGEX_PAREN_RECURSIVE, "$1$2")
|
||||
|
|
@ -192,11 +223,11 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun preloadN(noteLine: String) {
|
||||
val voiceNumber = noteLine.substring(0, 1).toInt()
|
||||
val templateComments = mutableListOf<String>()
|
||||
val templateStripped = REGEX_TEMPLATE_COMMENT.replace(templateString) {
|
||||
matchResult ->
|
||||
val templateStripped = REGEX_TEMPLATE_COMMENT.replace(templateString) { matchResult ->
|
||||
templateComments.add(matchResult.value)
|
||||
"&"
|
||||
}
|
||||
|
|
@ -257,7 +288,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
templateCharArray.forEach {
|
||||
when (it) {
|
||||
'D', 'R', 'M', 'F', 'S', 'L', 'T',
|
||||
'd', 'r', 'm', 'f', 's', 'l', 't', -> {
|
||||
'd', 'r', 'm', 'f', 's', 'l', 't',
|
||||
-> {
|
||||
if (firstInLoop) {
|
||||
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||
firstInLoop = false
|
||||
|
|
@ -269,12 +301,16 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
for (repetition in 0 until 6) {
|
||||
result += replacement
|
||||
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||
if (replacement in setOf('d', 'r', 'm', 'f', 's', 'l', 't' , 'z', '(',
|
||||
'D', 'R', 'M', 'F', 'S', 'L', 'T', '-', 'w', 'Z')) {
|
||||
if (replacement in setOf(
|
||||
'd', 'r', 'm', 'f', 's', 'l', 't', 'z', '(',
|
||||
'D', 'R', 'M', 'F', 'S', 'L', 'T', '-', 'w', 'Z'
|
||||
)
|
||||
) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
'w', '-' -> result += "~"
|
||||
'z', 'Z' -> result += "@"
|
||||
',' -> result += ";"
|
||||
|
|
@ -285,6 +321,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
result = rearrangeNote(result)
|
||||
loadN(voiceNumber, result, templateComments)
|
||||
}
|
||||
|
||||
private suspend fun parseOneLine(line: String) {
|
||||
val index: Int
|
||||
val value: String
|
||||
|
|
@ -305,27 +342,36 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
"T" -> if (index == 0) {
|
||||
loadT(value)
|
||||
}
|
||||
|
||||
"N" ->
|
||||
// Les lignes de type N seront parsées à la fin. preloadN() se chargera d'abord de réarranger la ligne
|
||||
// pour bien gérer les parenthèses.
|
||||
unparsedNote.add(index.toString() + value)
|
||||
|
||||
"M" ->
|
||||
loadM(value)
|
||||
|
||||
"L" ->
|
||||
loadL(index, value)
|
||||
|
||||
"Y" ->
|
||||
loadY(index, value)
|
||||
|
||||
"E" ->
|
||||
loadE(index, value)
|
||||
|
||||
"U" ->
|
||||
loadU(value)
|
||||
|
||||
"O" ->
|
||||
loadO(index, value)
|
||||
|
||||
"I" ->
|
||||
loadI(value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
suspend fun loadI(line: String) {
|
||||
val lineSplit = line.split(":")
|
||||
val lastSlashInFilename = currentFile.lastIndexOf('/')
|
||||
|
|
@ -353,6 +399,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadM(value: String) {
|
||||
val metaChunks: List<String> = value.split(REGEX_PARSE_META)
|
||||
metaChunks.forEach { parseMeta(it) }
|
||||
|
|
@ -363,6 +410,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
sharedScreenModel.setSongComposer(meta["h"] ?: "")
|
||||
sharedScreenModel.setSongRhythm(meta["r"] ?: "")
|
||||
}
|
||||
|
||||
private fun loadN(voiceNumber: Int, line: String, templateComments: MutableList<String>) {
|
||||
var midiDuration = 0
|
||||
var nextDuration = 0
|
||||
|
|
@ -421,11 +469,13 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
lineChar.forEach {
|
||||
when (it) {
|
||||
'|', ':', '!', '/' -> {
|
||||
if (lastIt == '|' || lastIt == ':' || lastIt == '!' || lastIt == '/') {} else {
|
||||
if (lastIt == '|' || lastIt == ':' || lastIt == '!' || lastIt == '/') {
|
||||
} else {
|
||||
midiDuration += nextDuration
|
||||
nextDuration = 60
|
||||
}
|
||||
}
|
||||
|
||||
'.' -> {
|
||||
if (lastIt == ';') {
|
||||
pushMidi()
|
||||
|
|
@ -436,6 +486,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
midiDuration += nextDuration - 30
|
||||
nextDuration = 30
|
||||
}
|
||||
|
||||
';' -> {
|
||||
if (lastIt == '.') {
|
||||
pushMidi()
|
||||
|
|
@ -451,10 +502,12 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
nextDuration = 15
|
||||
}
|
||||
}
|
||||
|
||||
'\'', ',' -> {
|
||||
newN.appendLastNote(it)
|
||||
lastNoteString += it
|
||||
}
|
||||
|
||||
'(', '[' -> newN.addNextMarker(it)
|
||||
')', ']' -> newN.appendLastMarker(it)
|
||||
'd', 'r', 'm', 'f', 's', 'l', 't',
|
||||
|
|
@ -474,6 +527,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
midiDuration += nextDuration
|
||||
nextDuration = 0
|
||||
}
|
||||
|
||||
"z", "@" -> {
|
||||
if (lastNoteString == "z") {
|
||||
midiDuration += nextDuration
|
||||
|
|
@ -484,6 +538,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
lastNoteString = "z"
|
||||
}
|
||||
|
||||
"'", "(", ")", "[", "]", "," -> {}
|
||||
else -> {
|
||||
pushMidi()
|
||||
|
|
@ -491,6 +546,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
'@' -> {
|
||||
if (lastNoteString == "z") {
|
||||
midiDuration += nextDuration
|
||||
|
|
@ -499,8 +555,10 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
lastNoteString = "z"
|
||||
}
|
||||
|
||||
'i', 'a' ->
|
||||
lastNoteString += it
|
||||
|
||||
'&' -> {
|
||||
commentNumber++
|
||||
nextComment.add(templateComments[commentNumber])
|
||||
|
|
@ -516,6 +574,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
midiPitch.setNote("z", 0)
|
||||
pitches.add(midiPitch.copy())
|
||||
}
|
||||
|
||||
private fun loadT(line: String) {
|
||||
templateString = line
|
||||
var nextTemplate = ""
|
||||
|
|
@ -528,7 +587,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
if (tMarker != "") {
|
||||
tMarker += it
|
||||
if ((it == '}')
|
||||
|| (tMarker.length == 2 && it != '{')) {
|
||||
|| (tMarker.length == 2 && it != '{')
|
||||
) {
|
||||
TimeUnitObject.hasMarker(true)
|
||||
nextMarker.add(PMarkers(tMarker, offset - templateOffset))
|
||||
tMarker = ""
|
||||
|
|
@ -562,9 +622,11 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
val parsedULine = uObject.parsed()
|
||||
loadT(parsedULine)
|
||||
}
|
||||
|
||||
fun loadO(index: Int, line: String) {
|
||||
O.getOrPut(index) { mutableListOf() }.add(line)
|
||||
}
|
||||
|
||||
fun parseMeta(line: String) {
|
||||
/* $_a_keyAbbrev = array(
|
||||
'a' => 'author',
|
||||
|
|
@ -610,6 +672,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
.replace("--_", "-_")
|
||||
.replace(Regex("_$"), "")
|
||||
}
|
||||
|
||||
private fun unpackLyrics(lyrics: String): String {
|
||||
val comments = REGEX_COMMENT.findAll(lyrics)
|
||||
val commentsIterator = comments.iterator()
|
||||
|
|
@ -624,16 +687,19 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
return lyricsFinal
|
||||
}
|
||||
|
||||
private fun loadL(stanzaNumber: Int, lyrics: String) {
|
||||
val unpackedLyrics = unpackLyrics(lyrics)
|
||||
loadLyrics(stanzaNumber, unpackedLyrics)
|
||||
}
|
||||
|
||||
fun setOverrideLyrics(stanzaNumber: Int, i: Int, voice: Int, text: String) {
|
||||
while (L.size <= i) {
|
||||
L.add(POneStanzaLyrics())
|
||||
}
|
||||
L[i].setAlternativeLyrics(stanzaNumber, voice, text)
|
||||
}
|
||||
|
||||
private fun loadLyrics(stanzaNumber: Int, lyrics: String) {
|
||||
val overrideIterator: MutableMap<Int, Iterator<String>> = mutableMapOf()
|
||||
try {
|
||||
|
|
@ -708,6 +774,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
lyricsComment.clear()
|
||||
}
|
||||
|
||||
fun smartYLyrics(lyrics: String): String {
|
||||
// Les ${O:1} risquent de changer en ${O:_1}. Sauvegardons-les dans comments.
|
||||
val comments = REGEX_COMMENT.findAll(lyrics)
|
||||
|
|
@ -729,12 +796,14 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
return unpackLyrics(lyricsFinal)
|
||||
}
|
||||
|
||||
// loadY is a smart lyrics parser for Malagasy language
|
||||
private fun loadY(intKey: Int, lyrics: String) {
|
||||
smartLyricsType = "Y"
|
||||
val smartLyrics = smartYLyrics(lyrics)
|
||||
loadL(intKey, smartLyrics)
|
||||
}
|
||||
|
||||
fun smartELyrics(lyrics: String): String {
|
||||
val loadedLyrics = lyrics
|
||||
.replace(" ", " _")
|
||||
|
|
@ -745,12 +814,14 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
//getLyricsComments(loadedLyrics)
|
||||
return unpackLyrics(loadedLyrics)
|
||||
}
|
||||
|
||||
// loadE is a smart Lyrics parser for English language
|
||||
private fun loadE(intKey: Int, lyrics: String) {
|
||||
smartLyricsType = "E"
|
||||
val smartLyrics = smartELyrics(lyrics)
|
||||
loadL(intKey, smartLyrics)
|
||||
}
|
||||
|
||||
private fun getLyricsComments(lyrics: String): String {
|
||||
val matchResult = REGEX_LYRICS_COMMENT.findAll(lyrics)
|
||||
.map { it.value }.toList()
|
||||
|
|
@ -759,15 +830,18 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
return REGEX_STRIP_DC.replace(lyrics, "")
|
||||
}
|
||||
|
||||
private fun defineRefrainFrom(tuoNumber: Int) {
|
||||
refrainBeginsAt = tuoNumber
|
||||
}
|
||||
|
||||
private fun copyRefrainToStanza(stanzaNumber: Int) {
|
||||
for (i in refrainBeginsAt..L.size - 1) {
|
||||
L[i].setLyrics(stanzaNumber, L[i].getLyrics(1))
|
||||
L[i].copyAlternativeLyrics(1, stanzaNumber)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addLyricsItem(stanzaNumber: Int, i: Int, lyricsItem: String) {
|
||||
while (L.size <= i) {
|
||||
L.add(POneStanzaLyrics())
|
||||
|
|
@ -783,11 +857,13 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
L[i].setLyrics(stanzaNumber, strippedLyrics)
|
||||
}
|
||||
|
||||
private fun appendLyricsItem(stanzaNumber: Int, i: Int, lyricsItem: String) {
|
||||
if (L.size > i) {
|
||||
L[i].appendDSLyrics(stanzaNumber, lyricsItem)
|
||||
}
|
||||
}
|
||||
|
||||
fun MutableList<POneVoiceNote>.addWithPadding(index: Int, element: POneVoiceNote) {
|
||||
if (index < this.size) {
|
||||
// L'index existe déjà, on remplace l'élément.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ import mg.dot.feufaro.solfa.TimeUnitObject
|
|||
class SharedScreenModel() : ScreenModel {
|
||||
private val _nextLabel = MutableStateFlow<String>("Next ...")
|
||||
val nextLabel: StateFlow<String> = _nextLabel.asStateFlow()
|
||||
|
||||
private val _loadFile = MutableStateFlow<String>("Load ...")
|
||||
|
||||
val loadFile: StateFlow<String> = _loadFile.asStateFlow()
|
||||
private val _measure = MutableStateFlow<String>("")
|
||||
val measure: StateFlow<String> = _measure.asStateFlow()
|
||||
private val _songTitle = MutableStateFlow<String>("")
|
||||
|
|
@ -43,24 +47,31 @@ class SharedScreenModel() : ScreenModel {
|
|||
fun appendData(otherData: String) {
|
||||
_nextLabel.value += otherData
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
tempTimeUnitObjectList.clear()
|
||||
}
|
||||
|
||||
fun lastTUO(): TimeUnitObject? {
|
||||
return tempTimeUnitObjectList.lastOrNull()
|
||||
}
|
||||
|
||||
fun addTUO(newTUO: TimeUnitObject) {
|
||||
tempTimeUnitObjectList.add(newTUO)
|
||||
}
|
||||
|
||||
fun doneTUOList() {
|
||||
_tuoList.value = tempTimeUnitObjectList.toList()
|
||||
}
|
||||
|
||||
fun setMeasure(theMeasure: String) {
|
||||
_measure.value = theMeasure
|
||||
}
|
||||
|
||||
fun setSongTitle(theTitle: String) {
|
||||
_songTitle.value = theTitle
|
||||
}
|
||||
|
||||
fun setStanza(theStanza: Int) {
|
||||
try {
|
||||
_stanza.value = theStanza
|
||||
|
|
@ -68,39 +79,50 @@ class SharedScreenModel() : ScreenModel {
|
|||
_stanza.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
fun setSongKey(theSongKey: String) {
|
||||
_songKey.value = theSongKey
|
||||
}
|
||||
|
||||
fun setTransposeTo(key: String) {
|
||||
_transposeTo.value = key
|
||||
}
|
||||
|
||||
fun setTransposeAsIf(key: String) {
|
||||
_transposeAsIf.value = key
|
||||
}
|
||||
|
||||
fun setSongAuthor(theSongAuthor: String) {
|
||||
_songAuthor.value = theSongAuthor
|
||||
}
|
||||
|
||||
fun setSongComposer(theSongComposer: String) {
|
||||
_songComposer.value = theSongComposer
|
||||
}
|
||||
|
||||
fun setSongRhythm(theSongRhythm: String) {
|
||||
_songRhythm.value = theSongRhythm
|
||||
}
|
||||
|
||||
fun setNbStanzas(nbStanzas: Int) {
|
||||
_nbStanzas.value = nbStanzas
|
||||
}
|
||||
|
||||
fun setPlaylist(thePlaylist: List<String>) {
|
||||
_playlist.value = thePlaylist
|
||||
}
|
||||
|
||||
fun setHasMarker(theHasMarker: Boolean) {
|
||||
_hasMarker.value = theHasMarker
|
||||
|
||||
}
|
||||
|
||||
fun playNext() {
|
||||
val nextIndex = (_nextPlayed.value + 1) % _playlist.value.size
|
||||
_nextPlayed.value = nextIndex
|
||||
setStanza(1)
|
||||
}
|
||||
|
||||
fun currentPlayed(): String {
|
||||
val playlistIndex = _nextPlayed.value
|
||||
return _playlist.value[playlistIndex]
|
||||
|
|
|
|||
|
|
@ -7,10 +7,16 @@ class SolfaScreenModel (
|
|||
private val solfa: Solfa
|
||||
) : ScreenModel {
|
||||
init {}
|
||||
|
||||
fun loadNextInPlaylist() {
|
||||
solfa.loadNextInPlaylist()
|
||||
}
|
||||
|
||||
fun reload() {
|
||||
solfa.loadSolfa()
|
||||
}
|
||||
|
||||
fun loadCustomFile() {
|
||||
solfa.loadFile()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package mg.dot.feufaro
|
||||
|
||||
import javax.swing.JFileChooser
|
||||
import javax.swing.filechooser.FileNameExtensionFilter
|
||||
import java.awt.EventQueue
|
||||
|
||||
actual fun launchFilePicker(
|
||||
mimeTypes: Array<String>,
|
||||
onFileSelected: (path: String?) -> Unit
|
||||
) {
|
||||
EventQueue.invokeLater {
|
||||
val fileChooser = JFileChooser()
|
||||
|
||||
if (mimeTypes.isNotEmpty()) {
|
||||
val filter = FileNameExtensionFilter(
|
||||
"Fichiers texte",
|
||||
"txt"
|
||||
)
|
||||
fileChooser.fileFilter = filter
|
||||
}
|
||||
|
||||
fileChooser.dialogTitle = "Sélectionnez votre fichier personnalisé"
|
||||
|
||||
val result = fileChooser.showOpenDialog(null)
|
||||
|
||||
if (result == JFileChooser.APPROVE_OPTION) {
|
||||
onFileSelected(fileChooser.selectedFile.absolutePath)
|
||||
} else {
|
||||
onFileSelected(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue