From 3883a39f7473315864ff3627ac41ea1998805640 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Fri, 4 Aug 2023 00:16:05 +0200 Subject: [PATCH] feat: Add OutputFormatTile --- app/build.gradle | 1 + .../myzel394/locationtest/db/AppSettings.kt | 35 +++++- .../SettingsScreen/atoms/OutputFormatTile.kt | 109 ++++++++++++++++++ .../locationtest/ui/screens/SettingsScreen.kt | 3 + 4 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/OutputFormatTile.kt diff --git a/app/build.gradle b/app/build.gradle index 7c1732c..53e905b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,5 +83,6 @@ dependencies { implementation 'com.maxkeppeler.sheets-compose-dialogs:core:1.2.0' implementation 'com.maxkeppeler.sheets-compose-dialogs:duration:1.2.0' + implementation 'com.maxkeppeler.sheets-compose-dialogs:list:1.2.0' implementation 'com.maxkeppeler.sheets-compose-dialogs:input:1.2.0' } \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt b/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt index aa45019..6ddd6f7 100644 --- a/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt +++ b/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt @@ -2,6 +2,7 @@ package app.myzel394.locationtest.db import android.media.MediaRecorder import android.os.Build +import com.maxkeppeler.sheets.list.models.ListOption import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import kotlinx.serialization.json.decodeFromStream @@ -43,7 +44,13 @@ data class AudioRecorderSettings( fun getSamplingRate(): Int = samplingRate ?: when(getOutputFormat()) { MediaRecorder.OutputFormat.AAC_ADTS -> 96000 MediaRecorder.OutputFormat.THREE_GPP -> 44100 - else -> throw Exception("Unknown output format") + MediaRecorder.OutputFormat.MPEG_4 -> 44100 + MediaRecorder.OutputFormat.MPEG_2_TS -> 48000 + MediaRecorder.OutputFormat.WEBM -> 48000 + MediaRecorder.OutputFormat.AMR_NB -> 8000 + MediaRecorder.OutputFormat.AMR_WB -> 16000 + MediaRecorder.OutputFormat.OGG -> 48000 + else -> 48000 } fun getEncoder(): Int = encoder ?: @@ -56,7 +63,13 @@ data class AudioRecorderSettings( when(getOutputFormat()) { MediaRecorder.OutputFormat.AAC_ADTS -> "aac" MediaRecorder.OutputFormat.THREE_GPP -> "3gp" - else -> throw Exception("Unknown output format") + MediaRecorder.OutputFormat.MPEG_4 -> "mp4" + MediaRecorder.OutputFormat.MPEG_2_TS -> "ts" + MediaRecorder.OutputFormat.WEBM -> "webm" + MediaRecorder.OutputFormat.AMR_NB -> "amr" + MediaRecorder.OutputFormat.AMR_WB -> "awb" + MediaRecorder.OutputFormat.OGG -> "ogg" + else -> "raw" } fun setIntervalDuration(duration: Long): AudioRecorderSettings { @@ -84,8 +97,8 @@ data class AudioRecorderSettings( return copy(samplingRate = samplingRate) } - fun setOutputFormat(outputFormat: Int): AudioRecorderSettings { - if (outputFormat < 0 || outputFormat > 11) { + fun setOutputFormat(outputFormat: Int?): AudioRecorderSettings { + if (outputFormat != null && (outputFormat < 0 || outputFormat > 11)) { throw Exception("OutputFormat is not a MediaRecorder.OutputFormat constant") } @@ -126,5 +139,19 @@ data class AudioRecorderSettings( 48000, 96000, ) + val OUTPUT_FORMAT_INDEX_TEXT_MAP = mapOf( + 0 to "Default", + 1 to "THREE_GPP", + 2 to "MPEG_4", + 3 to "AMR_NB", + 4 to "AMR_WB", + 5 to "AAC_ADIF", + 6 to "AAC_ADTS", + 7 to "OUTPUT_FORMAT_RTP_AVP", + 8 to "MPEG_2_TS", + 9 to "WEBM", + 10 to "HEIF", + 11 to "OGG", + ) } } diff --git a/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/OutputFormatTile.kt b/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/OutputFormatTile.kt new file mode 100644 index 0000000..185a6c9 --- /dev/null +++ b/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/OutputFormatTile.kt @@ -0,0 +1,109 @@ +package app.myzel394.locationtest.ui.components.SettingsScreen.atoms + +import android.app.ProgressDialog.show +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AudioFile +import androidx.compose.material.icons.filled.RadioButtonChecked +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.input.KeyboardType +import app.myzel394.locationtest.dataStore +import app.myzel394.locationtest.db.AppSettings +import app.myzel394.locationtest.db.AudioRecorderSettings +import app.myzel394.locationtest.ui.components.atoms.ExampleListRoulette +import app.myzel394.locationtest.ui.components.atoms.SettingsTile +import com.maxkeppeker.sheets.core.models.base.IconSource +import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState +import com.maxkeppeler.sheets.input.InputDialog +import com.maxkeppeler.sheets.input.models.InputHeader +import com.maxkeppeler.sheets.input.models.InputSelection +import com.maxkeppeler.sheets.input.models.InputTextField +import com.maxkeppeler.sheets.input.models.InputTextFieldType +import com.maxkeppeler.sheets.input.models.ValidationResult +import com.maxkeppeler.sheets.list.ListDialog +import com.maxkeppeler.sheets.list.models.ListOption +import com.maxkeppeler.sheets.list.models.ListSelection +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun OutputFormatTile() { + val scope = rememberCoroutineScope() + val showDialog = rememberUseCaseState() + val dataStore = LocalContext.current.dataStore + val settings = dataStore + .data + .collectAsState(initial = AppSettings.getDefaultInstance()) + .value + + fun updateValue(outputFormat: Int?) { + scope.launch { + dataStore.updateData { + it.setAudioRecorderSettings( + it.audioRecorderSettings.setOutputFormat(outputFormat) + ) + } + } + } + + ListDialog( + state = showDialog, + selection = ListSelection.Single( + showRadioButtons = true, + options = IntRange(0, 11).map { index -> + ListOption( + titleText = AudioRecorderSettings.OUTPUT_FORMAT_INDEX_TEXT_MAP[index]!!, + selected = settings.audioRecorderSettings.outputFormat == index, + ) + }.toList() + ) {index, option -> + updateValue(index) + }, + ) + SettingsTile( + title = "Output Format", + description = "Define the output format of the audio file.", + leading = { + Icon( + Icons.Default.AudioFile, + contentDescription = null, + ) + }, + trailing = { + Button( + onClick = showDialog::show, + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + shape = MaterialTheme.shapes.medium, + ) { + Text( + text = if (settings.audioRecorderSettings.outputFormat == null) { + "Auto" + } else { + AudioRecorderSettings.OUTPUT_FORMAT_INDEX_TEXT_MAP[settings.audioRecorderSettings.outputFormat]!! + } + ) + } + }, + extra = { + ExampleListRoulette( + items = listOf(null), + onItemSelected = ::updateValue, + ) { + Text( + text = "Auto" + ) + } + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/locationtest/ui/screens/SettingsScreen.kt b/app/src/main/java/app/myzel394/locationtest/ui/screens/SettingsScreen.kt index e13daca..13ebd6e 100644 --- a/app/src/main/java/app/myzel394/locationtest/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/app/myzel394/locationtest/ui/screens/SettingsScreen.kt @@ -13,6 +13,7 @@ import androidx.compose.material.icons.filled.Mic import androidx.compose.material.icons.filled.Tune import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Divider import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -33,6 +34,7 @@ import app.myzel394.locationtest.db.AppSettings import app.myzel394.locationtest.db.AudioRecorderSettings import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.BitrateTile import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.IntervalDurationTile +import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.OutputFormatTile import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.SamplingRateTile import app.myzel394.locationtest.ui.components.atoms.GlobalSwitch import app.myzel394.locationtest.ui.components.atoms.SettingsTile @@ -95,6 +97,7 @@ fun SettingsScreen( IntervalDurationTile() BitrateTile() SamplingRateTile() + OutputFormatTile() } } }