update ui tempo settings

This commit is contained in:
hasinarak3@gmail.com 2026-02-04 16:02:32 +03:00
parent 9fa116641b
commit 2f0be71dd8
8 changed files with 5157 additions and 316 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="256"
android:viewportHeight="256"
android:width="256dp"
android:height="256dp">
<path
android:pathData="M202.2 119.6c-2.1 0 -3.8 1.7 -3.8 3.8V171c0 2.1 1.7 3.8 3.8 3.8c2.1 0 3.8 -1.7 3.8 -3.8v-47.7C206 121.3 204.3 119.6 202.2 119.6z"
android:fillColor="#000000" />
<path
android:pathData="M192.7 117h19c2.1 0 3.8 -1.7 3.8 -3.8V74.4c0 -2.1 -1.7 -3.8 -3.8 -3.8H206V54.9c0 -2.1 -1.7 -3.8 -3.8 -3.8c-2.1 0 -3.8 1.7 -3.8 3.8v15.7h-5.7c-2.1 0 -3.8 1.7 -3.8 3.8v38.8C188.9 115.3 190.6 117 192.7 117zM196.5 78.2h11.4v31.2h-11.4V78.2z"
android:fillColor="#000000" />
<path
android:pathData="M152.7 158.5c-2.1 0 -3.8 1.7 -3.8 3.8v9.3c0 2.1 1.7 3.8 3.8 3.8c2.1 0 3.8 -1.7 3.8 -3.8v-9.3C156.6 160.2 154.9 158.5 152.7 158.5z"
android:fillColor="#000000" />
<path
android:pathData="M143.2 155.9h19c2.1 0 3.8 -1.7 3.8 -3.8v-38.8c0 -2.1 -1.7 -3.8 -3.8 -3.8h-5.7v-54c0 -2.1 -1.7 -3.8 -3.8 -3.8c-2.1 0 -3.8 1.7 -3.8 3.8v54h-5.7c-2.1 0 -3.8 1.7 -3.8 3.8v38.8C139.4 154.2 141.1 155.9 143.2 155.9zM147 117.1h11.4v31.2H147V117.1z"
android:fillColor="#000000" />
<path
android:pathData="M103.3 119.6c-2.1 0 -3.8 1.7 -3.8 3.8V171c0 2.1 1.7 3.8 3.8 3.8c2.1 0 3.8 -1.7 3.8 -3.8v-47.7C107.1 121.3 105.4 119.6 103.3 119.6z"
android:fillColor="#000000" />
<path
android:pathData="M93.7 117h19c2.1 0 3.8 -1.7 3.8 -3.8V74.4c0 -2.1 -1.7 -3.8 -3.8 -3.8H107V54.9c0 -2.1 -1.7 -3.8 -3.8 -3.8c-2.1 0 -3.8 1.7 -3.8 3.8v15.7h-5.7c-2.1 0 -3.8 1.7 -3.8 3.8v38.8C89.9 115.3 91.6 117 93.7 117zM97.5 78.2H109v31.2H97.6L97.5 78.2L97.5 78.2z"
android:fillColor="#000000" />
<path
android:pathData="M53.8 158.5c-2.1 0 -3.8 1.7 -3.8 3.8v9.3c0 2.1 1.7 3.8 3.8 3.8s3.8 -1.7 3.8 -3.8v-9.3C57.6 160.2 55.9 158.5 53.8 158.5z"
android:fillColor="#000000" />
<path
android:pathData="M44.3 155.9h19c2.1 0 3.8 -1.7 3.8 -3.8v-38.8c0 -2.1 -1.7 -3.8 -3.8 -3.8h-5.7v-54c0 -2.1 -1.7 -3.8 -3.8 -3.8S50 53.4 50 55.5v54h-5.7c-2.1 0 -3.8 1.7 -3.8 3.8v38.8C40.4 154.2 42.1 155.9 44.3 155.9zM48.1 117.1h11.4v31.2H48.1V117.1z"
android:fillColor="#000000" />
<path
android:pathData="M242.2 31.1H13.8c-2.1 0 -3.8 1.7 -3.8 3.8v178.6c0 6.3 5.1 11.4 11.4 11.4h213.2c6.3 0 11.4 -5.1 11.4 -11.4V34.9C246 32.8 244.3 31.1 242.2 31.1zM238.4 38.7v149.1H17.6V38.7H238.4zM234.6 217.3H21.4c-2.1 0 -3.8 -1.7 -3.8 -3.8v-18h220.8v18C238.4 215.5 236.7 217.3 234.6 217.3z"
android:fillColor="#000000" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="512"
android:viewportHeight="512"
android:width="800dp"
android:height="800dp">
<path
android:pathData="M468.826 97.292v103.374h-55.943V48.647h-36.484v152.019h-55.943V0.001h-36.484v200.665h-55.943V0h-36.484v200.666h-55.943V48.647H99.117v152.019H43.174V97.293H6.689V512h498.621V97.292H468.826zM99.117 334.442H43.174v-36.484h55.943V334.442zM135.602 297.958h55.943v36.484h-55.943V297.958zM228.025 475.516H191.54V370.927h36.484V475.516zM228.03 297.958h55.943v36.484H228.03V297.958zM320.452 475.516h-36.484V370.927h36.484V475.516zM376.399 334.442h-55.943v-36.484h55.943V334.442zM468.826 334.442h-55.943v-36.484h55.943V334.442z"
android:fillColor="#000000" />
</vector>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="256"
android:viewportHeight="256"
android:width="256dp"
android:height="256dp">
<path
android:pathData="M202.2 119.6c-2.1 0 -3.8 1.7 -3.8 3.8V171c0 2.1 1.7 3.8 3.8 3.8c2.1 0 3.8 -1.7 3.8 -3.8v-47.7C206 121.3 204.3 119.6 202.2 119.6z"
android:fillColor="#000000" />
<path
android:pathData="M192.7 117h19c2.1 0 3.8 -1.7 3.8 -3.8V74.4c0 -2.1 -1.7 -3.8 -3.8 -3.8H206V54.9c0 -2.1 -1.7 -3.8 -3.8 -3.8c-2.1 0 -3.8 1.7 -3.8 3.8v15.7h-5.7c-2.1 0 -3.8 1.7 -3.8 3.8v38.8C188.9 115.3 190.6 117 192.7 117zM196.5 78.2h11.4v31.2h-11.4V78.2z"
android:fillColor="#000000" />
<path
android:pathData="M152.7 158.5c-2.1 0 -3.8 1.7 -3.8 3.8v9.3c0 2.1 1.7 3.8 3.8 3.8c2.1 0 3.8 -1.7 3.8 -3.8v-9.3C156.6 160.2 154.9 158.5 152.7 158.5z"
android:fillColor="#000000" />
<path
android:pathData="M143.2 155.9h19c2.1 0 3.8 -1.7 3.8 -3.8v-38.8c0 -2.1 -1.7 -3.8 -3.8 -3.8h-5.7v-54c0 -2.1 -1.7 -3.8 -3.8 -3.8c-2.1 0 -3.8 1.7 -3.8 3.8v54h-5.7c-2.1 0 -3.8 1.7 -3.8 3.8v38.8C139.4 154.2 141.1 155.9 143.2 155.9zM147 117.1h11.4v31.2H147V117.1z"
android:fillColor="#000000" />
<path
android:pathData="M103.3 119.6c-2.1 0 -3.8 1.7 -3.8 3.8V171c0 2.1 1.7 3.8 3.8 3.8c2.1 0 3.8 -1.7 3.8 -3.8v-47.7C107.1 121.3 105.4 119.6 103.3 119.6z"
android:fillColor="#000000" />
<path
android:pathData="M93.7 117h19c2.1 0 3.8 -1.7 3.8 -3.8V74.4c0 -2.1 -1.7 -3.8 -3.8 -3.8H107V54.9c0 -2.1 -1.7 -3.8 -3.8 -3.8c-2.1 0 -3.8 1.7 -3.8 3.8v15.7h-5.7c-2.1 0 -3.8 1.7 -3.8 3.8v38.8C89.9 115.3 91.6 117 93.7 117zM97.5 78.2H109v31.2H97.6L97.5 78.2L97.5 78.2z"
android:fillColor="#000000" />
<path
android:pathData="M53.8 158.5c-2.1 0 -3.8 1.7 -3.8 3.8v9.3c0 2.1 1.7 3.8 3.8 3.8s3.8 -1.7 3.8 -3.8v-9.3C57.6 160.2 55.9 158.5 53.8 158.5z"
android:fillColor="#000000" />
<path
android:pathData="M44.3 155.9h19c2.1 0 3.8 -1.7 3.8 -3.8v-38.8c0 -2.1 -1.7 -3.8 -3.8 -3.8h-5.7v-54c0 -2.1 -1.7 -3.8 -3.8 -3.8S50 53.4 50 55.5v54h-5.7c-2.1 0 -3.8 1.7 -3.8 3.8v38.8C40.4 154.2 42.1 155.9 44.3 155.9zM48.1 117.1h11.4v31.2H48.1V117.1z"
android:fillColor="#000000" />
<path
android:pathData="M242.2 31.1H13.8c-2.1 0 -3.8 1.7 -3.8 3.8v178.6c0 6.3 5.1 11.4 11.4 11.4h213.2c6.3 0 11.4 -5.1 11.4 -11.4V34.9C246 32.8 244.3 31.1 242.2 31.1zM238.4 38.7v149.1H17.6V38.7H238.4zM234.6 217.3H21.4c-2.1 0 -3.8 -1.7 -3.8 -3.8v-18h220.8v18C238.4 215.5 236.7 217.3 234.6 217.3z"
android:fillColor="#000000" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="512"
android:viewportHeight="512"
android:width="800dp"
android:height="800dp">
<path
android:pathData="M468.826 97.292v103.374h-55.943V48.647h-36.484v152.019h-55.943V0.001h-36.484v200.665h-55.943V0h-36.484v200.666h-55.943V48.647H99.117v152.019H43.174V97.293H6.689V512h498.621V97.292H468.826zM99.117 334.442H43.174v-36.484h55.943V334.442zM135.602 297.958h55.943v36.484h-55.943V297.958zM228.025 475.516H191.54V370.927h36.484V475.516zM228.03 297.958h55.943v36.484H228.03V297.958zM320.452 475.516h-36.484V370.927h36.484V475.516zM376.399 334.442h-55.943v-36.484h55.943V334.442zM468.826 334.442h-55.943v-36.484h55.943V334.442z"
android:fillColor="#000000" />
</vector>

View file

@ -1,84 +1,22 @@
package mg.dot.feufaro.ui package mg.dot.feufaro.ui
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.*
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AvTimer import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft
import androidx.compose.material.icons.filled.Church import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
import androidx.compose.material.icons.filled.Clear import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.filled.ClearAll import androidx.compose.material3.*
import androidx.compose.material.icons.filled.Keyboard import androidx.compose.runtime.*
import androidx.compose.material.icons.filled.Loop
import androidx.compose.material.icons.filled.MusicNote
import androidx.compose.material.icons.filled.Pause
import androidx.compose.material.icons.filled.Piano
import androidx.compose.material.icons.filled.PianoOff
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.SettingsVoice
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.filled.Tonality
import androidx.compose.material.icons.filled.Tune
import androidx.compose.material.icons.automirrored.filled.VolumeUp
import androidx.compose.material.icons.automirrored.filled.VolumeOff
import androidx.compose.material.icons.filled.MoreHoriz
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledIconToggleButton
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FilterChipDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.produceState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import feufaro.composeapp.generated.resources.Res import feufaro.composeapp.generated.resources.Res
@ -88,8 +26,6 @@ import kotlinx.coroutines.delay
import mg.dot.feufaro.getPlatform import mg.dot.feufaro.getPlatform
import mg.dot.feufaro.midi.MediaPlayer import mg.dot.feufaro.midi.MediaPlayer
import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.painterResource
import org.koin.core.component.getScopeId
import javax.swing.Icon
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@ -107,32 +43,55 @@ fun MidiControlPanel(
val momo = duration.toInt() - currentPos.toInt() val momo = duration.toInt() - currentPos.toInt()
val loopState by produceState(Triple(-1L, -1L, false), mediaPlayer) { val loopState by produceState(Triple(-1L, -1L, false), mediaPlayer) {
while(true) { while (true) {
value = mediaPlayer.getLoopState() value = mediaPlayer.getLoopState()
delay(200) delay(200)
} }
} }
val voiceStates = mediaPlayer.getVoiceStates() val voiceStates = mediaPlayer.getVoiceStates()
val labels = listOf("S","A","T","B") val labels = listOf("S", "A", "T", "B")
val fullLabels = listOf("Soprano","Alto","Ténor","Basse") listOf("Soprano", "Alto", "Ténor", "Basse")
var tempo by remember { mutableStateOf(1.0f) } var tempo by remember { mutableStateOf(1.0f) }
var currentBpm by remember { mutableStateOf(mediaPlayer.getCurrentBPM()) } var currentBpm by remember { mutableStateOf(mediaPlayer.getCurrentBPM()) }
val basseBpm = 120f val basseBpm = 120f
var bpmInput by remember { mutableStateOf((basseBpm * tempo).toInt().toString()) }
var isPianoSelected by remember { mutableStateOf(true) } var isPianoSelected by remember { mutableStateOf(true) }
var showSATBTools by remember { mutableStateOf(false) } var showSATBTools by remember { mutableStateOf(false) }
var showVolumeTools by remember { mutableStateOf(false) }
var expandedCtl by remember { mutableStateOf(false) } var expandedCtl by remember { mutableStateOf(false) }
LaunchedEffect(tempo) { LaunchedEffect(tempo) {
currentBpm = mediaPlayer.getCurrentBPM() currentBpm = mediaPlayer.getCurrentBPM()
} }
Column ( fun updateTempoByBpmStep(step: Int) {
val currentBpm = (basseBpm * tempo).toInt()
val newBpm = (currentBpm + step).coerceIn((basseBpm * 0.25f).toInt(), (basseBpm * 1.5f).toInt())
val newFactor = newBpm.toFloat() / basseBpm
tempo = newFactor
mediaPlayer?.setTempo(newFactor)
}
fun updateTempoToBpm(targetBpm: Int) {
val clampedBpm = targetBpm.coerceIn((basseBpm * 0.25f).toInt(), (basseBpm * 1.5f).toInt())
val newFactor = clampedBpm.toFloat() / basseBpm
tempo = newFactor
mediaPlayer?.setTempo(newFactor)
println("tempo : $tempo")
}
Column(
modifier = Modifier.fillMaxWidth()
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.Center
) {
Column(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth(if (getPlatform().name.startsWith("Android")) 0.9f else 0.6f)
.padding(16.dp) .padding(16.dp)
.background(color = Color.Gray.copy(alpha = 0.5f), shape = RoundedCornerShape(size = 5.dp)), .background(color = Color.Gray.copy(alpha = 0.5f), shape = RoundedCornerShape(size = 5.dp)),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
@ -185,12 +144,12 @@ fun MidiControlPanel(
exit = fadeOut() + scaleOut() + slideOutVertically { it / 2 } exit = fadeOut() + scaleOut() + slideOutVertically { it / 2 }
) { ) {
Row { Row {
Column ( Column(
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
Row( Row(
modifier = Modifier.padding(vertical = 8.dp), modifier = Modifier.padding(vertical = 8.dp),
horizontalArrangement = Arrangement. spacedBy(4.dp) horizontalArrangement = Arrangement.spacedBy(4.dp)
) { ) {
labels.forEachIndexed { index, label -> labels.forEachIndexed { index, label ->
FilterChip( FilterChip(
@ -207,14 +166,102 @@ fun MidiControlPanel(
} }
} }
} }
AnimatedVisibility(
visible = !expandedCtl,
enter = fadeIn() + scaleIn() + slideInVertically { it / 2 },
exit = fadeOut() + scaleOut() + slideOutVertically { it / 2 }
) {
Row {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
modifier = Modifier
.height(45.dp)
.clip(RoundedCornerShape(12.dp))
.background(Color(0xFF2C3135))
.padding(vertical = 6.dp),
verticalAlignment = Alignment.CenterVertically
) {
if (tempo >= 0.3) { // limite 40BPM
IconButton(
modifier = Modifier.background(Color(0XFF2C3130)),
onClick = { updateTempoByBpmStep(-10) }) {
Icon(
Icons.AutoMirrored.Filled.KeyboardArrowLeft,
"gauche",
tint = Color.White.copy(0.7f),
modifier = Modifier.size(22.dp)
)
}
}
val currentBpmInt = (basseBpm * tempo).toInt()
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.padding(horizontal = 2.dp),
verticalAlignment = Alignment.CenterVertically
) {
val values = listOf(currentBpmInt - 1, currentBpmInt, currentBpmInt + 1)
values.forEach { bpmValue ->
AnimatedContent(
targetState = bpmValue,
transitionSpec = {
if (targetState > initialState) {
slideInHorizontally { it } + fadeIn() togetherWith slideOutHorizontally { -it } + fadeOut()
} else {
slideInHorizontally { -it } + fadeIn() togetherWith slideOutHorizontally { it } + fadeOut()
}
},
modifier = Modifier.padding(horizontal = 4.dp)
) { displayedBpm ->
val isCenter = displayedBpm == currentBpmInt
Text(
text = "$displayedBpm",
color = if (isCenter) Color.White else Color.Gray.copy(alpha = 0.4f),
fontSize = if (isCenter) 22.sp else 14.sp,
fontWeight = if (isCenter) FontWeight.Bold else FontWeight.Normal,
modifier = Modifier
.clip(CircleShape)
.clickable(enabled = !isCenter) { updateTempoToBpm(displayedBpm) }
.padding(horizontal = 4.dp)
)
}
}
}
if (tempo <= 1.3) { // limite 156BPM
IconButton(
modifier = Modifier.background(Color(0XFF2C3130)),
onClick = { updateTempoByBpmStep(10) }) {
Icon(
Icons.AutoMirrored.Filled.KeyboardArrowRight,
"droite",
tint = Color.White.copy(0.7f),
modifier = Modifier.size(22.dp)
)
}
}
Text(
text = "bpm",
color = Color.White.copy(0.6f),
fontSize = 12.sp,
modifier = Modifier.padding(end = 8.dp)
)
}
}
}
}
if (!expandedCtl) {
Spacer(modifier = Modifier.height(10.dp))
}
Row(
modifier = Modifier.fillMaxWidth().padding(horizontal = 5.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround ) {
){ Column {
Box( contentAlignment = Alignment.CenterStart) {
val isAtStart = loopState.first == -1L val isAtStart = loopState.first == -1L
val isWaitingForB = loopState.first != -1L && !loopState.third val isWaitingForB = loopState.first != -1L && !loopState.third
val isLooping = loopState.third val isLooping = loopState.third
@ -235,11 +282,10 @@ fun MidiControlPanel(
else -> Color.LightGray else -> Color.LightGray
} }
), ),
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 0.dp), contentPadding = PaddingValues(horizontal = 2.dp, vertical = 0.dp),
shape = RoundedCornerShape(5.dp) , shape = RoundedCornerShape(5.dp),
modifier = Modifier modifier = Modifier
.height(34.dp) .height(34.dp)
.padding(horizontal = 4.dp)
) { ) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@ -248,33 +294,35 @@ fun MidiControlPanel(
Text( Text(
text = "A", text = "A",
color = if (isWaitingForB || isLooping) Color.White else Color.Black, color = if (isWaitingForB || isLooping) Color.White else Color.Black,
fontSize = 18.sp fontSize = 16.sp
) )
Icon( Icon(
imageVector = Icons.Default.Loop, imageVector = Icons.Default.Loop,
contentDescription = null, contentDescription = null,
tint = if (isLooping) Color.White else Color.Black, tint = if (isLooping) Color.White else Color.Black,
modifier = Modifier.size(18.dp) modifier = Modifier.size(16.dp)
) )
Text( Text(
text = "B", text = "B",
color = if (isLooping) Color.White else Color.Black, color = if (isLooping) Color.White else Color.Black,
fontSize = 18.sp fontSize = 16.sp
) )
} }
} }
} }
Box(contentAlignment = Alignment.Center) { Spacer(modifier = Modifier.weight(1f))
Column {
IconButton( IconButton(
onClick = { onClick = {
showSATBTools = !showSATBTools showSATBTools = !showSATBTools
} }, modifier = Modifier
,modifier = Modifier
.size(40.dp) .size(40.dp)
.clip(CircleShape) .clip(CircleShape)
.background(if (showSATBTools) MaterialTheme.colorScheme.primary else Color.Transparent)) { .background(if (showSATBTools) MaterialTheme.colorScheme.primary else Color.Transparent)
) {
Icon( Icon(
painter = painterResource(Res.drawable.ic_mixer_satb), painter = painterResource(Res.drawable.ic_mixer_satb),
contentDescription = "SATB", contentDescription = "SATB",
@ -283,19 +331,9 @@ fun MidiControlPanel(
) )
} }
} }
Box(contentAlignment = Alignment.Center) { Spacer(modifier = Modifier.weight(1f))
IconButton(
onClick = onPlayPauseClick, Column {
modifier = Modifier.size(48.dp).background(MaterialTheme.colorScheme.primary, CircleShape)
) {
Icon(
imageVector = if (isPause) Icons.Filled.PlayArrow else Icons.Filled.Pause,
contentDescription = "Pla",
tint = Color.White
)
}
}
Box(contentAlignment = Alignment.CenterEnd) {
IconButton( IconButton(
onClick = { onClick = {
isPianoSelected = !isPianoSelected isPianoSelected = !isPianoSelected
@ -304,6 +342,7 @@ fun MidiControlPanel(
} else { } else {
mediaPlayer?.changeInstru(20) mediaPlayer?.changeInstru(20)
} }
} }
) { ) {
if (isPianoSelected) { if (isPianoSelected) {
@ -322,18 +361,44 @@ fun MidiControlPanel(
} }
} }
} }
Spacer(modifier = Modifier.weight(1f))
Column(
modifier = Modifier.wrapContentWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
IconButton(
onClick = onPlayPauseClick,
modifier = Modifier.size(48.dp).background(MaterialTheme.colorScheme.primary, CircleShape)
) {
Icon(
imageVector = if (isPause) Icons.Filled.PlayArrow else Icons.Filled.Pause,
contentDescription = "Pla",
tint = Color.White
)
}
}
Spacer(modifier = Modifier.weight(1f))
val platform = getPlatform() val platform = getPlatform()
if (platform.name.startsWith("Java")) { if (platform.name.startsWith("Java")) {
ModernVolumeSlider( ModernVolumeSlider(
volume, onVolumeChange = onVolumeChange volume, onVolumeChange = onVolumeChange
) )
} }
Spacer(modifier = Modifier.weight(1f))
Row( Row(
modifier = Modifier.wrapContentWidth(),
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically
) { ) {
Spacer(modifier = Modifier.width(8.dp)) IconButton(
IconButton(onClick = { expandedCtl = !expandedCtl }) { onClick = { expandedCtl = !expandedCtl },
modifier = Modifier.size(48.dp)
) {
Icon( Icon(
imageVector = if (expandedCtl) Icons.Default.MoreHoriz else Icons.Default.MoreVert, imageVector = if (expandedCtl) Icons.Default.MoreHoriz else Icons.Default.MoreVert,
contentDescription = "More", contentDescription = "More",
@ -343,4 +408,6 @@ fun MidiControlPanel(
} }
} }
} }
}
}
} }

View file

@ -29,6 +29,7 @@ fun ModernVolumeSlider(
volume: Float, volume: Float,
onVolumeChange: (Float) -> Unit onVolumeChange: (Float) -> Unit
) { ) {
Column {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier modifier = Modifier
@ -70,4 +71,5 @@ fun ModernVolumeSlider(
} }
) )
} }
}
} }