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
|
||||||
|
|
@ -51,8 +51,8 @@ object ScreenSolfa : Screen {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val solfaScreenModel = koinScreenModel<SolfaScreenModel>()
|
val solfaScreenModel = koinScreenModel<SolfaScreenModel>()
|
||||||
var menuPosition by remember { mutableStateOf(Offset.Zero)}
|
var menuPosition by remember { mutableStateOf(Offset.Zero) }
|
||||||
var showContextualMenu by remember { mutableStateOf(false)}
|
var showContextualMenu by remember { mutableStateOf(false) }
|
||||||
var gridWidthPx by rememberSaveable { mutableStateOf(0) }
|
var gridWidthPx by rememberSaveable { mutableStateOf(0) }
|
||||||
val sharedScreenModel = koinScreenModel<SharedScreenModel>()
|
val sharedScreenModel = koinScreenModel<SharedScreenModel>()
|
||||||
val tuoList by sharedScreenModel.tuoList.collectAsState()
|
val tuoList by sharedScreenModel.tuoList.collectAsState()
|
||||||
|
|
@ -61,7 +61,9 @@ object ScreenSolfa : Screen {
|
||||||
val gridTUOData = GridTUOData(measure, tuoList, stanza)
|
val gridTUOData = GridTUOData(measure, tuoList, stanza)
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
Box(Modifier.fillMaxSize()
|
|
||||||
|
Box(
|
||||||
|
Modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
|
|
@ -122,13 +124,35 @@ object ScreenSolfa : Screen {
|
||||||
gridWidthPx = gridWidthPx,
|
gridWidthPx = gridWidthPx,
|
||||||
onGridWidthMeasured = { width -> gridWidthPx = width }
|
onGridWidthMeasured = { width -> gridWidthPx = width }
|
||||||
)
|
)
|
||||||
MGButton(onClick = {
|
FlowRow(
|
||||||
//showContent = !showContent
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
|
) {
|
||||||
|
MGButton(onClick = {
|
||||||
|
//showContent = !showContent
|
||||||
|
|
||||||
solfaScreenModel.loadNextInPlaylist()
|
solfaScreenModel.loadNextInPlaylist()
|
||||||
}, modifier = Modifier.height(40.dp)) {
|
}, modifier = Modifier.height(40.dp)) {
|
||||||
val nextLabel: String by sharedScreenModel.nextLabel.collectAsState()
|
val nextLabel: String by sharedScreenModel.nextLabel.collectAsState()
|
||||||
Text(nextLabel)
|
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(
|
FlowRow(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
|
@ -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
|
@Throws(ObjectStreamException::class) // C'est une méthode de sérialisation Java, donc l'exception est nécessaire
|
||||||
private fun readResolve(): Any {
|
private fun readResolve(): Any {
|
||||||
return this // Toujours retourner l'instance unique de ce singleton
|
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.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import mg.dot.feufaro.FileRepository
|
import mg.dot.feufaro.FileRepository
|
||||||
|
import mg.dot.feufaro.launchFilePicker
|
||||||
import mg.dot.feufaro.midi.MidiPitch
|
import mg.dot.feufaro.midi.MidiPitch
|
||||||
import mg.dot.feufaro.midi.MidiWriterKotlin
|
import mg.dot.feufaro.midi.MidiWriterKotlin
|
||||||
|
|
||||||
|
|
@ -23,28 +24,31 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
private var refrainBeginsAt = -1
|
private var refrainBeginsAt = -1
|
||||||
private var smartLyricsType = "L"
|
private var smartLyricsType = "L"
|
||||||
private val pitches = mutableListOf<MidiPitch>()
|
private val pitches = mutableListOf<MidiPitch>()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var currentFile = ""
|
var currentFile = ""
|
||||||
val REGEX_SHIFT_PAREN_UPWARD = Regex("([^a-yA-Y\\(\\[]+)([\\)\\]])")
|
val REGEX_SHIFT_PAREN_UPWARD = Regex("([^a-yA-Y\\(\\[]+)([\\)\\]])")
|
||||||
val REGEX_SHIFT_PAREN_DOWNWARD = Regex("([\\(\\[])([^a-yA-y\\)\\]]+)")
|
val REGEX_SHIFT_PAREN_DOWNWARD = Regex("([\\(\\[])([^a-yA-y\\)\\]]+)")
|
||||||
val REGEX_COLLAPSE_PARENS_OPEN = Regex("([\\(\\[])[\\(\\[]+")
|
val REGEX_COLLAPSE_PARENS_OPEN = Regex("([\\(\\[])[\\(\\[]+")
|
||||||
val REGEX_COLLAPSE_PARENS_CLOSE = Regex("([\\)\\]])[\\)\\]]+")
|
val REGEX_COLLAPSE_PARENS_CLOSE = Regex("([\\)\\]])[\\)\\]]+")
|
||||||
val REGEX_SINGLETON_PAREN = Regex("[\\(\\[](.[¹²³₁₂₃]?)?[\\)\\]]") // @todo
|
val REGEX_SINGLETON_PAREN = Regex("[\\(\\[](.[¹²³₁₂₃]?)?[\\)\\]]") // @todo
|
||||||
val REGEX_SHIFT_COMMA_UPWARD = Regex("([^a-zA-Z]+)([',])")
|
val REGEX_SHIFT_COMMA_UPWARD = Regex("([^a-zA-Z]+)([',])")
|
||||||
val REGEX_TEMPLATE_COMMENT = Regex("(\\$[A-Z]|\\$\\{[^\\}]*\\})")
|
val REGEX_TEMPLATE_COMMENT = Regex("(\\$[A-Z]|\\$\\{[^\\}]*\\})")
|
||||||
val REGEX_REPETITION = Regex("([zwdrmfslt-](?>[',]*))([1-9][0-9]*)", RegexOption.IGNORE_CASE)
|
val REGEX_REPETITION = Regex("([zwdrmfslt-](?>[',]*))([1-9][0-9]*)", RegexOption.IGNORE_CASE)
|
||||||
val REGEX_PARSE_META = Regex("\\|(?=[a-z]:)")
|
val REGEX_PARSE_META = Regex("\\|(?=[a-z]:)")
|
||||||
val REGEX_LYRICS_COMMENT = Regex("\\$\\{([^\\}][^:]*:([^\\}]*))\\}|\\$\\{R!\\}")
|
val REGEX_LYRICS_COMMENT = Regex("\\$\\{([^\\}][^:]*:([^\\}]*))\\}|\\$\\{R!\\}")
|
||||||
val REGEX_LYRICS_REPETITION = Regex("_(\\d+)")
|
val REGEX_LYRICS_REPETITION = Regex("_(\\d+)")
|
||||||
val REGEX_VOWELS_STAGE1 = Regex("[aeiouyòàéìỳ](?![,;\\.\\-:!\\?\\}»_\"]*([ aeiouyòàéìỳ/]|_[1-9]))", RegexOption.IGNORE_CASE)
|
val REGEX_VOWELS_STAGE1 =
|
||||||
val REGEX_VOWELS_STAGE2 = Regex("(?<=[aeiouyòàéìỳ])_([,;\\.\\-:!\\?\\}»_\"]+)", RegexOption.IGNORE_CASE)
|
Regex("[aeiouyòàéìỳ](?![,;\\.\\-:!\\?\\}»_\"]*([ aeiouyòàéìỳ/]|_[1-9]))", RegexOption.IGNORE_CASE)
|
||||||
val REGEX_VOWELS_STAGE3 = Regex("_([\\?\\!:,;\\.»\\)]+|(\\$\\{[^\\}]*\\})+)")
|
val REGEX_VOWELS_STAGE2 = Regex("(?<=[aeiouyòàéìỳ])_([,;\\.\\-:!\\?\\}»_\"]+)", RegexOption.IGNORE_CASE)
|
||||||
val REGEX_MALAGASY_MN = Regex("([aeio])_([nm])([tdjkbp])")
|
val REGEX_VOWELS_STAGE3 = Regex("_([\\?\\!:,;\\.»\\)]+|(\\$\\{[^\\}]*\\})+)")
|
||||||
val REGEX_MALAGASY_MN_STAGE2 = Regex("_([mn])-")
|
val REGEX_MALAGASY_MN = Regex("([aeio])_([nm])([tdjkbp])")
|
||||||
val REGEX_PAREN_RECURSIVE = Regex("(\\([^\\(\\)]*)\\(([^\\)]*)\\)")
|
val REGEX_MALAGASY_MN_STAGE2 = Regex("_([mn])-")
|
||||||
val REGEX_COMMENT = Regex("\\$\\{[^\\}]*\\}")
|
val REGEX_PAREN_RECURSIVE = Regex("(\\([^\\(\\)]*)\\(([^\\)]*)\\)")
|
||||||
val REGEX_STRIP_DC = Regex("\\$\\{D[^:]*:[^\\}]*\\}")
|
val REGEX_COMMENT = Regex("\\$\\{[^\\}]*\\}")
|
||||||
|
val REGEX_STRIP_DC = Regex("\\$\\{D[^:]*:[^\\}]*\\}")
|
||||||
}
|
}
|
||||||
|
|
||||||
var nextTIndex: Int = -1
|
var nextTIndex: Int = -1
|
||||||
var nextNIndex: Int = -1
|
var nextNIndex: Int = -1
|
||||||
var nextLIndex: Int = -1
|
var nextLIndex: Int = -1
|
||||||
|
|
@ -75,26 +79,31 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
templateCharArray.forEach { // D.-R
|
templateCharArray.forEach { // D.-R
|
||||||
when (it) {
|
when (it) {
|
||||||
'D', 'R', 'M', 'F', 'S', 'L', 'T',
|
'D', 'R', 'M', 'F', 'S', 'L', 'T',
|
||||||
'd', 'r', 'm', 'f', 's', 'l', 't', -> {
|
'd', 'r', 'm', 'f', 's', 'l', 't',
|
||||||
|
-> {
|
||||||
nextNIndex++
|
nextNIndex++
|
||||||
if (!inGroup) {
|
if (!inGroup) {
|
||||||
nextLIndex ++
|
nextLIndex++
|
||||||
if (L.size > nextLIndex) {
|
if (L.size > nextLIndex) {
|
||||||
unitObject.addLyrics(L[nextLIndex])
|
unitObject.addLyrics(L[nextLIndex])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
N.forEachIndexed { voiceNumber, pOneVoiceNote -> run {
|
N.forEachIndexed { voiceNumber, pOneVoiceNote ->
|
||||||
unitObject.addNote(voiceNumber, pOneVoiceNote.oneVoiceNote, nextNIndex, nextMarker)
|
run {
|
||||||
|
unitObject.addNote(voiceNumber, pOneVoiceNote.oneVoiceNote, nextNIndex, nextMarker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nextMarker = '0'
|
nextMarker = '0'
|
||||||
}
|
}
|
||||||
'.', ',', ->
|
|
||||||
|
'.', ',' ->
|
||||||
unitObject.addMarker(it)
|
unitObject.addMarker(it)
|
||||||
|
|
||||||
'-', 'Z', 'z', 'w' ->
|
'-', 'Z', 'z', 'w' ->
|
||||||
N.indices.forEach { voiceNumber ->
|
N.indices.forEach { voiceNumber ->
|
||||||
unitObject.addBlank(voiceNumber, it)
|
unitObject.addBlank(voiceNumber, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
'(', '[' -> {
|
'(', '[' -> {
|
||||||
nextLIndex++
|
nextLIndex++
|
||||||
if (L.size > nextLIndex) {
|
if (L.size > nextLIndex) {
|
||||||
|
|
@ -102,6 +111,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
inGroup = true
|
inGroup = true
|
||||||
}
|
}
|
||||||
|
|
||||||
')', ']' -> {
|
')', ']' -> {
|
||||||
inGroup = false
|
inGroup = false
|
||||||
}
|
}
|
||||||
|
|
@ -112,11 +122,13 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
nextTimeUnitObject()
|
nextTimeUnitObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadSolfa() {
|
fun loadSolfa() {
|
||||||
val sourceFileName: String = sharedScreenModel.currentPlayed()
|
val sourceFileName: String = sharedScreenModel.currentPlayed()
|
||||||
sharedScreenModel.reset()
|
sharedScreenModel.reset()
|
||||||
parse(sourceFileName)
|
parse(sourceFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadNextInPlaylist() {
|
fun loadNextInPlaylist() {
|
||||||
val playlist = sharedScreenModel.playlist.value
|
val playlist = sharedScreenModel.playlist.value
|
||||||
if (playlist.isNotEmpty()) {
|
if (playlist.isNotEmpty()) {
|
||||||
|
|
@ -124,6 +136,24 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
loadSolfa()
|
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) {
|
fun parse(sourceFile: String) {
|
||||||
currentFile = sourceFile
|
currentFile = sourceFile
|
||||||
val parseScope = CoroutineScope(Dispatchers.Default)
|
val parseScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
|
@ -166,39 +196,40 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println("Erreur parseScope Solfa:150 : ${e.message} iter: ${TimeUnitObject.nbBlock}")
|
println("Erreur parseScope Solfa:150 : ${e.message} iter: ${TimeUnitObject.nbBlock}")
|
||||||
}
|
}
|
||||||
val pitches = pitches.sortedWith( compareBy({it.tick}, {it.voiceNumber}))
|
val pitches = pitches.sortedWith(compareBy({ it.tick }, { it.voiceNumber }))
|
||||||
val midiWriter = MidiWriterKotlin(fileRepository)
|
val midiWriter = MidiWriterKotlin(fileRepository)
|
||||||
midiWriter.process(pitches)
|
midiWriter.process(pitches)
|
||||||
midiWriter.save("whawyd3.mid")
|
midiWriter.save("whawyd3.mid")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun rearrangeNote(noteString: String, infiniteIter: Int = 0): String {
|
private fun rearrangeNote(noteString: String, infiniteIter: Int = 0): String {
|
||||||
var result: String = noteString
|
var result: String = noteString
|
||||||
result = result .replace(REGEX_PAREN_RECURSIVE, "$1$2")
|
result = result.replace(REGEX_PAREN_RECURSIVE, "$1$2")
|
||||||
result = result .replace(REGEX_PAREN_RECURSIVE, "$1$2")
|
result = result.replace(REGEX_PAREN_RECURSIVE, "$1$2")
|
||||||
result = result .replace(REGEX_PAREN_RECURSIVE, "$1$2")
|
result = result.replace(REGEX_PAREN_RECURSIVE, "$1$2")
|
||||||
result = result .replace(REGEX_SHIFT_PAREN_UPWARD, "$2$1")
|
result = result.replace(REGEX_SHIFT_PAREN_UPWARD, "$2$1")
|
||||||
result = result .replace(REGEX_SHIFT_PAREN_DOWNWARD, "$2$1")
|
result = result.replace(REGEX_SHIFT_PAREN_DOWNWARD, "$2$1")
|
||||||
result = result .replace(REGEX_COLLAPSE_PARENS_OPEN, "$1")
|
result = result.replace(REGEX_COLLAPSE_PARENS_OPEN, "$1")
|
||||||
result = result .replace(REGEX_COLLAPSE_PARENS_CLOSE, "$1")
|
result = result.replace(REGEX_COLLAPSE_PARENS_CLOSE, "$1")
|
||||||
result = result .replace(REGEX_SINGLETON_PAREN, "$1")
|
result = result.replace(REGEX_SINGLETON_PAREN, "$1")
|
||||||
result = result .replace(REGEX_SHIFT_COMMA_UPWARD, "$2$1")
|
result = result.replace(REGEX_SHIFT_COMMA_UPWARD, "$2$1")
|
||||||
if (result != noteString && infiniteIter < 75) {
|
if (result != noteString && infiniteIter < 75) {
|
||||||
result = rearrangeNote(result, infiniteIter+1)
|
result = rearrangeNote(result, infiniteIter + 1)
|
||||||
}
|
}
|
||||||
if (infiniteIter >= 70) {
|
if (infiniteIter >= 70) {
|
||||||
println("$infiniteIter\n$noteString\n$result")
|
println("$infiniteIter\n$noteString\n$result")
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun preloadN(noteLine: String) {
|
private fun preloadN(noteLine: String) {
|
||||||
val voiceNumber = noteLine.substring(0, 1).toInt()
|
val voiceNumber = noteLine.substring(0, 1).toInt()
|
||||||
val templateComments = mutableListOf<String>()
|
val templateComments = mutableListOf<String>()
|
||||||
val templateStripped = REGEX_TEMPLATE_COMMENT.replace(templateString) {
|
val templateStripped = REGEX_TEMPLATE_COMMENT.replace(templateString) { matchResult ->
|
||||||
matchResult ->
|
templateComments.add(matchResult.value)
|
||||||
templateComments.add(matchResult.value)
|
"&"
|
||||||
"&"
|
|
||||||
}
|
}
|
||||||
val templateCharArray = templateStripped.toCharArray()
|
val templateCharArray = templateStripped.toCharArray()
|
||||||
val noteLine = noteLine.replace(REGEX_TEMPLATE_COMMENT, "")
|
val noteLine = noteLine.replace(REGEX_TEMPLATE_COMMENT, "")
|
||||||
|
|
@ -234,12 +265,12 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
if (it in listOf('d', 'r', 'm', 'f', 's', 'l', 't', 'D', 'R', 'M', 'F', 'S', 'L', 'T')) {
|
if (it in listOf('d', 'r', 'm', 'f', 's', 'l', 't', 'D', 'R', 'M', 'F', 'S', 'L', 'T')) {
|
||||||
noteChar2 += anchorSuffix
|
noteChar2 += anchorSuffix
|
||||||
if (
|
if (
|
||||||
(anchorNote == 'r' && it in listOf('d', 'D'))
|
(anchorNote == 'r' && it in listOf('d', 'D'))
|
||||||
|| (anchorNote == 'm' && it in listOf('d', 'D', 'r', 'R'))
|
|| (anchorNote == 'm' && it in listOf('d', 'D', 'r', 'R'))
|
||||||
|| (anchorNote == 'f' && it in listOf('d', 'D', 'r', 'R', 'm', 'M'))
|
|| (anchorNote == 'f' && it in listOf('d', 'D', 'r', 'R', 'm', 'M'))
|
||||||
|| (anchorNote == 's' && it !in listOf('s', 'S', 'l', 'L', 't', 'T'))
|
|| (anchorNote == 's' && it !in listOf('s', 'S', 'l', 'L', 't', 'T'))
|
||||||
|| (anchorNote == 'l' && it !in listOf( 'l', 'L', 't', 'T'))
|
|| (anchorNote == 'l' && it !in listOf('l', 'L', 't', 'T'))
|
||||||
|| (anchorNote == 't' && it !in listOf( 't', 'T'))
|
|| (anchorNote == 't' && it !in listOf('t', 'T'))
|
||||||
) {
|
) {
|
||||||
noteChar2 += '\''
|
noteChar2 += '\''
|
||||||
}
|
}
|
||||||
|
|
@ -253,28 +284,33 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
val noteCharIterator = noteChar2.replace("/", "").toCharArray().iterator()
|
val noteCharIterator = noteChar2.replace("/", "").toCharArray().iterator()
|
||||||
var result = ""
|
var result = ""
|
||||||
var firstInLoop = true
|
var firstInLoop = true
|
||||||
var replacement : Char = 'x'
|
var replacement: Char = 'x'
|
||||||
templateCharArray.forEach {
|
templateCharArray.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
'D', 'R', 'M', 'F', 'S', 'L', 'T',
|
'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'
|
if (firstInLoop) {
|
||||||
firstInLoop = false
|
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||||
}
|
firstInLoop = false
|
||||||
if (replacement == '(') {
|
}
|
||||||
result += replacement
|
if (replacement == '(') {
|
||||||
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
result += replacement
|
||||||
}
|
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||||
for (repetition in 0 until 6) {
|
}
|
||||||
result += replacement
|
for (repetition in 0 until 6) {
|
||||||
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
result += replacement
|
||||||
if (replacement in setOf('d', 'r', 'm', 'f', 's', 'l', 't' , 'z', '(',
|
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||||
'D', 'R', 'M', 'F', 'S', 'L', 'T', '-', 'w', 'Z')) {
|
if (replacement in setOf(
|
||||||
break
|
'd', 'r', 'm', 'f', 's', 'l', 't', 'z', '(',
|
||||||
}
|
'D', 'R', 'M', 'F', 'S', 'L', 'T', '-', 'w', 'Z'
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'w', '-' -> result += "~"
|
'w', '-' -> result += "~"
|
||||||
'z', 'Z' -> result += "@"
|
'z', 'Z' -> result += "@"
|
||||||
',' -> result += ";"
|
',' -> result += ";"
|
||||||
|
|
@ -285,6 +321,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
result = rearrangeNote(result)
|
result = rearrangeNote(result)
|
||||||
loadN(voiceNumber, result, templateComments)
|
loadN(voiceNumber, result, templateComments)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun parseOneLine(line: String) {
|
private suspend fun parseOneLine(line: String) {
|
||||||
val index: Int
|
val index: Int
|
||||||
val value: String
|
val value: String
|
||||||
|
|
@ -292,7 +329,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
if (lineLength <= 3) {
|
if (lineLength <= 3) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val key : String = line.trim().substring(0, 1)
|
val key: String = line.trim().substring(0, 1)
|
||||||
if (lineLength > 4 && line.trim().substring(3, 4) == ":") {
|
if (lineLength > 4 && line.trim().substring(3, 4) == ":") {
|
||||||
index = line.substring(1, 3).toIntOrNull() ?: 0
|
index = line.substring(1, 3).toIntOrNull() ?: 0
|
||||||
value = line.trim().substring(4)
|
value = line.trim().substring(4)
|
||||||
|
|
@ -305,27 +342,36 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
"T" -> if (index == 0) {
|
"T" -> if (index == 0) {
|
||||||
loadT(value)
|
loadT(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
"N" ->
|
"N" ->
|
||||||
// Les lignes de type N seront parsées à la fin. preloadN() se chargera d'abord de réarranger la ligne
|
// 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.
|
// pour bien gérer les parenthèses.
|
||||||
unparsedNote.add(index.toString()+value)
|
unparsedNote.add(index.toString() + value)
|
||||||
|
|
||||||
"M" ->
|
"M" ->
|
||||||
loadM(value)
|
loadM(value)
|
||||||
|
|
||||||
"L" ->
|
"L" ->
|
||||||
loadL(index, value)
|
loadL(index, value)
|
||||||
|
|
||||||
"Y" ->
|
"Y" ->
|
||||||
loadY(index, value)
|
loadY(index, value)
|
||||||
|
|
||||||
"E" ->
|
"E" ->
|
||||||
loadE(index, value)
|
loadE(index, value)
|
||||||
|
|
||||||
"U" ->
|
"U" ->
|
||||||
loadU(value)
|
loadU(value)
|
||||||
|
|
||||||
"O" ->
|
"O" ->
|
||||||
loadO(index, value)
|
loadO(index, value)
|
||||||
|
|
||||||
"I" ->
|
"I" ->
|
||||||
loadI(value)
|
loadI(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun loadI(line: String) {
|
suspend fun loadI(line: String) {
|
||||||
val lineSplit = line.split(":")
|
val lineSplit = line.split(":")
|
||||||
val lastSlashInFilename = currentFile.lastIndexOf('/')
|
val lastSlashInFilename = currentFile.lastIndexOf('/')
|
||||||
|
|
@ -349,10 +395,11 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
parseOneLine(it)
|
parseOneLine(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadM(value: String) {
|
private fun loadM(value: String) {
|
||||||
val metaChunks: List<String> = value.split(REGEX_PARSE_META)
|
val metaChunks: List<String> = value.split(REGEX_PARSE_META)
|
||||||
metaChunks.forEach { parseMeta(it) }
|
metaChunks.forEach { parseMeta(it) }
|
||||||
|
|
@ -363,6 +410,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
sharedScreenModel.setSongComposer(meta["h"] ?: "")
|
sharedScreenModel.setSongComposer(meta["h"] ?: "")
|
||||||
sharedScreenModel.setSongRhythm(meta["r"] ?: "")
|
sharedScreenModel.setSongRhythm(meta["r"] ?: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadN(voiceNumber: Int, line: String, templateComments: MutableList<String>) {
|
private fun loadN(voiceNumber: Int, line: String, templateComments: MutableList<String>) {
|
||||||
var midiDuration = 0
|
var midiDuration = 0
|
||||||
var nextDuration = 0
|
var nextDuration = 0
|
||||||
|
|
@ -421,11 +469,13 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
lineChar.forEach {
|
lineChar.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
'|', ':', '!', '/' -> {
|
'|', ':', '!', '/' -> {
|
||||||
if (lastIt == '|' || lastIt == ':' || lastIt == '!' || lastIt == '/') {} else {
|
if (lastIt == '|' || lastIt == ':' || lastIt == '!' || lastIt == '/') {
|
||||||
|
} else {
|
||||||
midiDuration += nextDuration
|
midiDuration += nextDuration
|
||||||
nextDuration = 60
|
nextDuration = 60
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'.' -> {
|
'.' -> {
|
||||||
if (lastIt == ';') {
|
if (lastIt == ';') {
|
||||||
pushMidi()
|
pushMidi()
|
||||||
|
|
@ -436,6 +486,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
midiDuration += nextDuration - 30
|
midiDuration += nextDuration - 30
|
||||||
nextDuration = 30
|
nextDuration = 30
|
||||||
}
|
}
|
||||||
|
|
||||||
';' -> {
|
';' -> {
|
||||||
if (lastIt == '.') {
|
if (lastIt == '.') {
|
||||||
pushMidi()
|
pushMidi()
|
||||||
|
|
@ -451,16 +502,18 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
nextDuration = 15
|
nextDuration = 15
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'\'', ',' -> {
|
'\'', ',' -> {
|
||||||
newN.appendLastNote(it)
|
newN.appendLastNote(it)
|
||||||
lastNoteString += it
|
lastNoteString += it
|
||||||
}
|
}
|
||||||
'(', '[' -> newN.addNextMarker(it)
|
|
||||||
|
'(', '[' -> newN.addNextMarker(it)
|
||||||
')', ']' -> newN.appendLastMarker(it)
|
')', ']' -> newN.appendLastMarker(it)
|
||||||
'd', 'r', 'm', 'f', 's', 'l', 't',
|
'd', 'r', 'm', 'f', 's', 'l', 't',
|
||||||
'D', 'R', 'F', 'S', 'T',
|
'D', 'R', 'F', 'S', 'T',
|
||||||
'-', 'Z', 'z'
|
'-', 'Z', 'z'
|
||||||
-> {
|
-> {
|
||||||
var noteString = it.toString().lowercase()
|
var noteString = it.toString().lowercase()
|
||||||
if (it == 'D' || it == 'R' || it == 'F' || it == 'S') {
|
if (it == 'D' || it == 'R' || it == 'F' || it == 'S') {
|
||||||
noteString += "i"
|
noteString += "i"
|
||||||
|
|
@ -474,6 +527,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
midiDuration += nextDuration
|
midiDuration += nextDuration
|
||||||
nextDuration = 0
|
nextDuration = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
"z", "@" -> {
|
"z", "@" -> {
|
||||||
if (lastNoteString == "z") {
|
if (lastNoteString == "z") {
|
||||||
midiDuration += nextDuration
|
midiDuration += nextDuration
|
||||||
|
|
@ -484,6 +538,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
lastNoteString = "z"
|
lastNoteString = "z"
|
||||||
}
|
}
|
||||||
|
|
||||||
"'", "(", ")", "[", "]", "," -> {}
|
"'", "(", ")", "[", "]", "," -> {}
|
||||||
else -> {
|
else -> {
|
||||||
pushMidi()
|
pushMidi()
|
||||||
|
|
@ -491,6 +546,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'@' -> {
|
'@' -> {
|
||||||
if (lastNoteString == "z") {
|
if (lastNoteString == "z") {
|
||||||
midiDuration += nextDuration
|
midiDuration += nextDuration
|
||||||
|
|
@ -499,10 +555,12 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
lastNoteString = "z"
|
lastNoteString = "z"
|
||||||
}
|
}
|
||||||
|
|
||||||
'i', 'a' ->
|
'i', 'a' ->
|
||||||
lastNoteString += it
|
lastNoteString += it
|
||||||
|
|
||||||
'&' -> {
|
'&' -> {
|
||||||
commentNumber ++
|
commentNumber++
|
||||||
nextComment.add(templateComments[commentNumber])
|
nextComment.add(templateComments[commentNumber])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -516,6 +574,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
midiPitch.setNote("z", 0)
|
midiPitch.setNote("z", 0)
|
||||||
pitches.add(midiPitch.copy())
|
pitches.add(midiPitch.copy())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadT(line: String) {
|
private fun loadT(line: String) {
|
||||||
templateString = line
|
templateString = line
|
||||||
var nextTemplate = ""
|
var nextTemplate = ""
|
||||||
|
|
@ -528,7 +587,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
if (tMarker != "") {
|
if (tMarker != "") {
|
||||||
tMarker += it
|
tMarker += it
|
||||||
if ((it == '}')
|
if ((it == '}')
|
||||||
|| (tMarker.length == 2 && it != '{')) {
|
|| (tMarker.length == 2 && it != '{')
|
||||||
|
) {
|
||||||
TimeUnitObject.hasMarker(true)
|
TimeUnitObject.hasMarker(true)
|
||||||
nextMarker.add(PMarkers(tMarker, offset - templateOffset))
|
nextMarker.add(PMarkers(tMarker, offset - templateOffset))
|
||||||
tMarker = ""
|
tMarker = ""
|
||||||
|
|
@ -539,7 +599,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
tMarker = "$"
|
tMarker = "$"
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
offset ++
|
offset++
|
||||||
if (it == ':' || it == '|' || it == '/' || it == '!') {
|
if (it == ':' || it == '|' || it == '/' || it == '!') {
|
||||||
val newTemplateItem =
|
val newTemplateItem =
|
||||||
PTemplate(nextTemplate, it.toString(), nextMarker.toMutableList())
|
PTemplate(nextTemplate, it.toString(), nextMarker.toMutableList())
|
||||||
|
|
@ -562,9 +622,11 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
val parsedULine = uObject.parsed()
|
val parsedULine = uObject.parsed()
|
||||||
loadT(parsedULine)
|
loadT(parsedULine)
|
||||||
}
|
}
|
||||||
fun loadO(index:Int, line:String) {
|
|
||||||
|
fun loadO(index: Int, line: String) {
|
||||||
O.getOrPut(index) { mutableListOf() }.add(line)
|
O.getOrPut(index) { mutableListOf() }.add(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseMeta(line: String) {
|
fun parseMeta(line: String) {
|
||||||
/* $_a_keyAbbrev = array(
|
/* $_a_keyAbbrev = array(
|
||||||
'a' => 'author',
|
'a' => 'author',
|
||||||
|
|
@ -585,7 +647,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (subKey != "" && "M" != subKey) {
|
if (subKey != "" && "M" != subKey) {
|
||||||
meta[subKey] = line.substring(2)
|
meta[subKey] = line.substring(2)
|
||||||
}
|
}
|
||||||
if ("c" == subKey) {
|
if ("c" == subKey) {
|
||||||
val tonality = line.uppercaseFirstMeta()
|
val tonality = line.uppercaseFirstMeta()
|
||||||
|
|
@ -610,7 +672,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
.replace("--_", "-_")
|
.replace("--_", "-_")
|
||||||
.replace(Regex("_$"), "")
|
.replace(Regex("_$"), "")
|
||||||
}
|
}
|
||||||
private fun unpackLyrics(lyrics: String) :String {
|
|
||||||
|
private fun unpackLyrics(lyrics: String): String {
|
||||||
val comments = REGEX_COMMENT.findAll(lyrics)
|
val comments = REGEX_COMMENT.findAll(lyrics)
|
||||||
val commentsIterator = comments.iterator()
|
val commentsIterator = comments.iterator()
|
||||||
val loadedLyrics = lyrics//.replace(REGEX_LYRICS_COMMENT, "")
|
val loadedLyrics = lyrics//.replace(REGEX_LYRICS_COMMENT, "")
|
||||||
|
|
@ -624,16 +687,19 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
return lyricsFinal
|
return lyricsFinal
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadL(stanzaNumber: Int, lyrics: String) {
|
private fun loadL(stanzaNumber: Int, lyrics: String) {
|
||||||
val unpackedLyrics = unpackLyrics(lyrics)
|
val unpackedLyrics = unpackLyrics(lyrics)
|
||||||
loadLyrics(stanzaNumber, unpackedLyrics)
|
loadLyrics(stanzaNumber, unpackedLyrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOverrideLyrics(stanzaNumber: Int, i: Int, voice: Int, text: String) {
|
fun setOverrideLyrics(stanzaNumber: Int, i: Int, voice: Int, text: String) {
|
||||||
while (L.size <= i) {
|
while (L.size <= i) {
|
||||||
L.add(POneStanzaLyrics())
|
L.add(POneStanzaLyrics())
|
||||||
}
|
}
|
||||||
L[i].setAlternativeLyrics(stanzaNumber, voice, text)
|
L[i].setAlternativeLyrics(stanzaNumber, voice, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadLyrics(stanzaNumber: Int, lyrics: String) {
|
private fun loadLyrics(stanzaNumber: Int, lyrics: String) {
|
||||||
val overrideIterator: MutableMap<Int, Iterator<String>> = mutableMapOf()
|
val overrideIterator: MutableMap<Int, Iterator<String>> = mutableMapOf()
|
||||||
try {
|
try {
|
||||||
|
|
@ -645,14 +711,14 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
if (REGEX_OVERRIDE.matches(lyricsItem)) {
|
if (REGEX_OVERRIDE.matches(lyricsItem)) {
|
||||||
val overrideNumber = lyricsItem.replace(REGEX_OVERRIDE, "$1").toInt()
|
val overrideNumber = lyricsItem.replace(REGEX_OVERRIDE, "$1").toInt()
|
||||||
val override = O.getOrElse(overrideNumber) { null }
|
val override = O.getOrElse(overrideNumber) { null }
|
||||||
override?.forEachIndexed { index, value ->
|
override?.forEachIndexed { index, value ->
|
||||||
val matchResult = Regex("v(\\d+):(.*)").find(value)
|
val matchResult = Regex("v(\\d+):(.*)").find(value)
|
||||||
val overrideString = when (smartLyricsType) {
|
val overrideString = when (smartLyricsType) {
|
||||||
"E" -> smartELyrics(matchResult?.groupValues[2] ?: value)
|
"E" -> smartELyrics(matchResult?.groupValues[2] ?: value)
|
||||||
"Y" -> smartYLyrics(matchResult?.groupValues[2] ?: value)
|
"Y" -> smartYLyrics(matchResult?.groupValues[2] ?: value)
|
||||||
else -> value
|
else -> value
|
||||||
}
|
}
|
||||||
for ( iN in (1..9) ) {
|
for (iN in (1..9)) {
|
||||||
if (matchResult?.groupValues[1]?.contains(iN.digitToChar()) ?: false) {
|
if (matchResult?.groupValues[1]?.contains(iN.digitToChar()) ?: false) {
|
||||||
val overrideSyllabus = overrideString.split(Regex("[_/]")).iterator()
|
val overrideSyllabus = overrideString.split(Regex("[_/]")).iterator()
|
||||||
overrideIterator[iN] = overrideSyllabus
|
overrideIterator[iN] = overrideSyllabus
|
||||||
|
|
@ -669,7 +735,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
addLyricsItem(stanzaNumber, i, originalLyrics)
|
addLyricsItem(stanzaNumber, i, originalLyrics)
|
||||||
}
|
}
|
||||||
if (refrainBeginsAt > 0 && stanzaNumber > 1 && !lyrics.contains($$"${R!}")) {
|
if (refrainBeginsAt > 0 && stanzaNumber > 1 && !lyrics.contains($$"${R!}")) {
|
||||||
copyRefrainToStanza(stanzaNumber)
|
copyRefrainToStanza(stanzaNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -690,12 +756,12 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
"Y" -> smartYLyrics(item)
|
"Y" -> smartYLyrics(item)
|
||||||
else -> item
|
else -> item
|
||||||
}
|
}
|
||||||
item
|
item
|
||||||
.addHyphens()
|
.addHyphens()
|
||||||
.split(Regex("[_/]"))
|
.split(Regex("[_/]"))
|
||||||
.forEachIndexed { i, xval ->
|
.forEachIndexed { i, xval ->
|
||||||
appendLyricsItem(stanzaNumber, i + positionDS, xval)
|
appendLyricsItem(stanzaNumber, i + positionDS, xval)
|
||||||
}
|
}
|
||||||
lyricsIterator.remove()
|
lyricsIterator.remove()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -708,6 +774,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
lyricsComment.clear()
|
lyricsComment.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun smartYLyrics(lyrics: String): String {
|
fun smartYLyrics(lyrics: String): String {
|
||||||
// Les ${O:1} risquent de changer en ${O:_1}. Sauvegardons-les dans comments.
|
// Les ${O:1} risquent de changer en ${O:_1}. Sauvegardons-les dans comments.
|
||||||
val comments = REGEX_COMMENT.findAll(lyrics)
|
val comments = REGEX_COMMENT.findAll(lyrics)
|
||||||
|
|
@ -728,13 +795,15 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
commentsIterator.next().value
|
commentsIterator.next().value
|
||||||
}
|
}
|
||||||
return unpackLyrics(lyricsFinal)
|
return unpackLyrics(lyricsFinal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadY is a smart lyrics parser for Malagasy language
|
// loadY is a smart lyrics parser for Malagasy language
|
||||||
private fun loadY(intKey: Int, lyrics: String) {
|
private fun loadY(intKey: Int, lyrics: String) {
|
||||||
smartLyricsType = "Y"
|
smartLyricsType = "Y"
|
||||||
val smartLyrics = smartYLyrics(lyrics)
|
val smartLyrics = smartYLyrics(lyrics)
|
||||||
loadL(intKey, smartLyrics)
|
loadL(intKey, smartLyrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun smartELyrics(lyrics: String): String {
|
fun smartELyrics(lyrics: String): String {
|
||||||
val loadedLyrics = lyrics
|
val loadedLyrics = lyrics
|
||||||
.replace(" ", " _")
|
.replace(" ", " _")
|
||||||
|
|
@ -745,12 +814,14 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
//getLyricsComments(loadedLyrics)
|
//getLyricsComments(loadedLyrics)
|
||||||
return unpackLyrics(loadedLyrics)
|
return unpackLyrics(loadedLyrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadE is a smart Lyrics parser for English language
|
// loadE is a smart Lyrics parser for English language
|
||||||
private fun loadE(intKey: Int, lyrics: String) {
|
private fun loadE(intKey: Int, lyrics: String) {
|
||||||
smartLyricsType = "E"
|
smartLyricsType = "E"
|
||||||
val smartLyrics = smartELyrics(lyrics)
|
val smartLyrics = smartELyrics(lyrics)
|
||||||
loadL(intKey, smartLyrics)
|
loadL(intKey, smartLyrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLyricsComments(lyrics: String): String {
|
private fun getLyricsComments(lyrics: String): String {
|
||||||
val matchResult = REGEX_LYRICS_COMMENT.findAll(lyrics)
|
val matchResult = REGEX_LYRICS_COMMENT.findAll(lyrics)
|
||||||
.map { it.value }.toList()
|
.map { it.value }.toList()
|
||||||
|
|
@ -759,35 +830,40 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
return REGEX_STRIP_DC.replace(lyrics, "")
|
return REGEX_STRIP_DC.replace(lyrics, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun defineRefrainFrom(tuoNumber: Int) {
|
private fun defineRefrainFrom(tuoNumber: Int) {
|
||||||
refrainBeginsAt = tuoNumber
|
refrainBeginsAt = tuoNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copyRefrainToStanza(stanzaNumber: Int) {
|
private fun copyRefrainToStanza(stanzaNumber: Int) {
|
||||||
for (i in refrainBeginsAt..L.size-1) {
|
for (i in refrainBeginsAt..L.size - 1) {
|
||||||
L[i].setLyrics(stanzaNumber, L[i].getLyrics(1))
|
L[i].setLyrics(stanzaNumber, L[i].getLyrics(1))
|
||||||
L[i].copyAlternativeLyrics(1, stanzaNumber)
|
L[i].copyAlternativeLyrics(1, stanzaNumber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addLyricsItem(stanzaNumber: Int, i: Int, lyricsItem: String) {
|
private fun addLyricsItem(stanzaNumber: Int, i: Int, lyricsItem: String) {
|
||||||
while (L.size <= i) {
|
while (L.size <= i) {
|
||||||
L.add(POneStanzaLyrics())
|
L.add(POneStanzaLyrics())
|
||||||
}
|
}
|
||||||
val strippedLyrics =
|
val strippedLyrics =
|
||||||
if (lyricsItem.contains($$"${R=}")) {
|
if (lyricsItem.contains($$"${R=}")) {
|
||||||
if (stanzaNumber == 1) {
|
if (stanzaNumber == 1) {
|
||||||
defineRefrainFrom(i)
|
defineRefrainFrom(i)
|
||||||
|
}
|
||||||
|
lyricsItem.replace($$"${R=}", "")
|
||||||
|
} else {
|
||||||
|
lyricsItem
|
||||||
}
|
}
|
||||||
lyricsItem.replace($$"${R=}", "")
|
|
||||||
} else {
|
|
||||||
lyricsItem
|
|
||||||
}
|
|
||||||
L[i].setLyrics(stanzaNumber, strippedLyrics)
|
L[i].setLyrics(stanzaNumber, strippedLyrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun appendLyricsItem(stanzaNumber: Int, i: Int, lyricsItem: String) {
|
private fun appendLyricsItem(stanzaNumber: Int, i: Int, lyricsItem: String) {
|
||||||
if (L.size > i) {
|
if (L.size > i) {
|
||||||
L[i].appendDSLyrics(stanzaNumber, lyricsItem)
|
L[i].appendDSLyrics(stanzaNumber, lyricsItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MutableList<POneVoiceNote>.addWithPadding(index: Int, element: POneVoiceNote) {
|
fun MutableList<POneVoiceNote>.addWithPadding(index: Int, element: POneVoiceNote) {
|
||||||
if (index < this.size) {
|
if (index < this.size) {
|
||||||
// L'index existe déjà, on remplace l'élément.
|
// L'index existe déjà, on remplace l'élément.
|
||||||
|
|
@ -803,4 +879,4 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
this.add(element)
|
this.add(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,11 +8,15 @@ import mg.dot.feufaro.solfa.TimeUnitObject
|
||||||
class SharedScreenModel() : ScreenModel {
|
class SharedScreenModel() : ScreenModel {
|
||||||
private val _nextLabel = MutableStateFlow<String>("Next ...")
|
private val _nextLabel = MutableStateFlow<String>("Next ...")
|
||||||
val nextLabel: StateFlow<String> = _nextLabel.asStateFlow()
|
val nextLabel: StateFlow<String> = _nextLabel.asStateFlow()
|
||||||
|
|
||||||
|
private val _loadFile = MutableStateFlow<String>("Load ...")
|
||||||
|
|
||||||
|
val loadFile: StateFlow<String> = _loadFile.asStateFlow()
|
||||||
private val _measure = MutableStateFlow<String>("")
|
private val _measure = MutableStateFlow<String>("")
|
||||||
val measure: StateFlow<String> = _measure.asStateFlow()
|
val measure: StateFlow<String> = _measure.asStateFlow()
|
||||||
private val _songTitle = MutableStateFlow<String>("")
|
private val _songTitle = MutableStateFlow<String>("")
|
||||||
val songTitle: StateFlow<String> = _songTitle.asStateFlow()
|
val songTitle: StateFlow<String> = _songTitle.asStateFlow()
|
||||||
private val _stanza = MutableStateFlow<Int>( 0)
|
private val _stanza = MutableStateFlow<Int>(0)
|
||||||
val stanza: StateFlow<Int> = _stanza.asStateFlow()
|
val stanza: StateFlow<Int> = _stanza.asStateFlow()
|
||||||
private val _songKey = MutableStateFlow<String>("")
|
private val _songKey = MutableStateFlow<String>("")
|
||||||
val songKey: StateFlow<String> = _songKey.asStateFlow()
|
val songKey: StateFlow<String> = _songKey.asStateFlow()
|
||||||
|
|
@ -37,70 +41,88 @@ class SharedScreenModel() : ScreenModel {
|
||||||
private var _nextPlayed = MutableStateFlow(0)
|
private var _nextPlayed = MutableStateFlow(0)
|
||||||
val nextPlayed: StateFlow<Int> = _nextPlayed.asStateFlow()
|
val nextPlayed: StateFlow<Int> = _nextPlayed.asStateFlow()
|
||||||
private val tempTimeUnitObjectList = mutableListOf<TimeUnitObject>()
|
private val tempTimeUnitObjectList = mutableListOf<TimeUnitObject>()
|
||||||
var _hasMarker = MutableStateFlow<Boolean>( false)
|
var _hasMarker = MutableStateFlow<Boolean>(false)
|
||||||
val hasMarker: StateFlow<Boolean> = _hasMarker.asStateFlow()
|
val hasMarker: StateFlow<Boolean> = _hasMarker.asStateFlow()
|
||||||
|
|
||||||
fun appendData(otherData: String) {
|
fun appendData(otherData: String) {
|
||||||
_nextLabel.value += otherData
|
_nextLabel.value += otherData
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
tempTimeUnitObjectList.clear()
|
tempTimeUnitObjectList.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun lastTUO(): TimeUnitObject? {
|
fun lastTUO(): TimeUnitObject? {
|
||||||
return tempTimeUnitObjectList.lastOrNull()
|
return tempTimeUnitObjectList.lastOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addTUO(newTUO: TimeUnitObject) {
|
fun addTUO(newTUO: TimeUnitObject) {
|
||||||
tempTimeUnitObjectList.add(newTUO)
|
tempTimeUnitObjectList.add(newTUO)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doneTUOList() {
|
fun doneTUOList() {
|
||||||
_tuoList.value = tempTimeUnitObjectList.toList()
|
_tuoList.value = tempTimeUnitObjectList.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setMeasure(theMeasure: String) {
|
fun setMeasure(theMeasure: String) {
|
||||||
_measure.value = theMeasure
|
_measure.value = theMeasure
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSongTitle(theTitle: String) {
|
fun setSongTitle(theTitle: String) {
|
||||||
_songTitle.value = theTitle
|
_songTitle.value = theTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setStanza(theStanza: Int) {
|
fun setStanza(theStanza: Int) {
|
||||||
try {
|
try {
|
||||||
_stanza.value = theStanza
|
_stanza.value = theStanza
|
||||||
} catch(e: NumberFormatException) {
|
} catch (e: NumberFormatException) {
|
||||||
_stanza.value = 0
|
_stanza.value = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSongKey(theSongKey: String) {
|
fun setSongKey(theSongKey: String) {
|
||||||
_songKey.value = theSongKey
|
_songKey.value = theSongKey
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTransposeTo(key: String) {
|
fun setTransposeTo(key: String) {
|
||||||
_transposeTo.value = key
|
_transposeTo.value = key
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTransposeAsIf(key: String) {
|
fun setTransposeAsIf(key: String) {
|
||||||
_transposeAsIf.value = key
|
_transposeAsIf.value = key
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSongAuthor(theSongAuthor: String) {
|
fun setSongAuthor(theSongAuthor: String) {
|
||||||
_songAuthor.value = theSongAuthor
|
_songAuthor.value = theSongAuthor
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSongComposer(theSongComposer: String) {
|
fun setSongComposer(theSongComposer: String) {
|
||||||
_songComposer.value = theSongComposer
|
_songComposer.value = theSongComposer
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSongRhythm(theSongRhythm: String) {
|
fun setSongRhythm(theSongRhythm: String) {
|
||||||
_songRhythm.value = theSongRhythm
|
_songRhythm.value = theSongRhythm
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setNbStanzas(nbStanzas: Int) {
|
fun setNbStanzas(nbStanzas: Int) {
|
||||||
_nbStanzas.value = nbStanzas
|
_nbStanzas.value = nbStanzas
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setPlaylist(thePlaylist: List<String>) {
|
fun setPlaylist(thePlaylist: List<String>) {
|
||||||
_playlist.value = thePlaylist
|
_playlist.value = thePlaylist
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setHasMarker(theHasMarker: Boolean) {
|
fun setHasMarker(theHasMarker: Boolean) {
|
||||||
_hasMarker.value = theHasMarker
|
_hasMarker.value = theHasMarker
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun playNext() {
|
fun playNext() {
|
||||||
val nextIndex = (_nextPlayed.value + 1) % _playlist.value.size
|
val nextIndex = (_nextPlayed.value + 1) % _playlist.value.size
|
||||||
_nextPlayed.value = nextIndex
|
_nextPlayed.value = nextIndex
|
||||||
setStanza(1)
|
setStanza(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun currentPlayed(): String {
|
fun currentPlayed(): String {
|
||||||
val playlistIndex = _nextPlayed.value
|
val playlistIndex = _nextPlayed.value
|
||||||
return _playlist.value[playlistIndex]
|
return _playlist.value[playlistIndex]
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,20 @@ package mg.dot.feufaro.viewmodel
|
||||||
import cafe.adriel.voyager.core.model.ScreenModel
|
import cafe.adriel.voyager.core.model.ScreenModel
|
||||||
import mg.dot.feufaro.solfa.Solfa
|
import mg.dot.feufaro.solfa.Solfa
|
||||||
|
|
||||||
class SolfaScreenModel (
|
class SolfaScreenModel(
|
||||||
private val solfa: Solfa
|
private val solfa: Solfa
|
||||||
) : ScreenModel{
|
) : ScreenModel {
|
||||||
init {}
|
init {}
|
||||||
|
|
||||||
fun loadNextInPlaylist() {
|
fun loadNextInPlaylist() {
|
||||||
solfa.loadNextInPlaylist()
|
solfa.loadNextInPlaylist()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reload() {
|
fun reload() {
|
||||||
solfa.loadSolfa()
|
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