diff --git a/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt b/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt index f7fdfbd..0dc32f9 100644 --- a/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt +++ b/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt @@ -142,6 +142,7 @@ data class AudioRecorderSettings( val samplingRate: Int? = null, val outputFormat: Int? = null, val encoder: Int? = null, + val showAllMicrophones: Boolean = false, ) { fun getOutputFormat(): Int { if (outputFormat != null) { @@ -269,6 +270,10 @@ data class AudioRecorderSettings( return copy(forceExactMaxDuration = forceExactMaxDuration) } + fun setShowAllMicrophones(showAllMicrophones: Boolean): AudioRecorderSettings { + return copy(showAllMicrophones = showAllMicrophones) + } + fun isEncoderCompatible(encoder: Int): Boolean { if (outputFormat == null || outputFormat == MediaRecorder.OutputFormat.DEFAULT) { return true diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/organisms/RecordingStatus.kt b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/organisms/RecordingStatus.kt index 36d1ebf..c395f39 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/organisms/RecordingStatus.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/organisms/RecordingStatus.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.material3.LinearProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -23,6 +24,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import app.myzel394.alibi.dataStore +import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.ui.components.AudioRecorder.atoms.DeleteButton import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneDisconnectedDialog import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneReconnectedDialog @@ -138,8 +141,18 @@ fun RecordingStatus( } } - - val microphones = MicrophoneInfo.fetchDeviceMicrophones(context) + val dataStore = LocalContext.current.dataStore + val settings = dataStore + .data + .collectAsState(initial = AppSettings.getDefaultInstance()) + .value + val microphones = MicrophoneInfo.fetchDeviceMicrophones(context).let { + if (settings.audioRecorderSettings.showAllMicrophones) { + it + } else { + MicrophoneInfo.filterMicrophones(it) + } + } val microphoneStatus = audioRecorder.microphoneStatus val previousStatus = rememberPrevious(microphoneStatus) diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/ShowAllMicrophonesTile.kt b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/ShowAllMicrophonesTile.kt new file mode 100644 index 0000000..f2a1d8e --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/ShowAllMicrophonesTile.kt @@ -0,0 +1,57 @@ +package app.myzel394.alibi.ui.components.SettingsScreen.atoms + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.GraphicEq +import androidx.compose.material.icons.filled.MicExternalOn +import androidx.compose.material3.Icon +import androidx.compose.material3.Switch +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.res.stringResource +import app.myzel394.alibi.R +import app.myzel394.alibi.dataStore +import app.myzel394.alibi.db.AppSettings +import app.myzel394.alibi.ui.components.atoms.SettingsTile +import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState +import kotlinx.coroutines.launch + + +@Composable +fun ShowAllMicrophonesTile() { + val scope = rememberCoroutineScope() + val dataStore = LocalContext.current.dataStore + val settings = dataStore + .data + .collectAsState(initial = AppSettings.getDefaultInstance()) + .value + + fun updateValue(showAllMicrophones: Boolean) { + scope.launch { + dataStore.updateData { + it.setAudioRecorderSettings( + it.audioRecorderSettings.setShowAllMicrophones(showAllMicrophones) + ) + } + } + } + + + SettingsTile( + title = stringResource(R.string.ui_settings_option_showAllMicrophones_title), + description = stringResource(R.string.ui_settings_option_showAllMicrophones_description), + leading = { + Icon( + Icons.Default.MicExternalOn, + contentDescription = null, + ) + }, + trailing = { + Switch( + checked = settings.audioRecorderSettings.showAllMicrophones, + onCheckedChange = ::updateValue, + ) + }, + ) +} \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt index a1db378..c12ad60 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt @@ -43,6 +43,7 @@ import app.myzel394.alibi.ui.components.SettingsScreen.atoms.IntervalDurationTil import app.myzel394.alibi.ui.components.SettingsScreen.atoms.MaxDurationTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.OutputFormatTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.SamplingRateTile +import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ShowAllMicrophonesTile import app.myzel394.alibi.ui.components.atoms.GlobalSwitch import app.myzel394.alibi.ui.components.atoms.MessageBox import app.myzel394.alibi.ui.components.atoms.MessageType @@ -80,7 +81,7 @@ fun SettingsScreen( }, modifier = Modifier .nestedScroll(scrollBehavior.nestedScrollConnection) - ) {padding -> + ) { padding -> Column( modifier = Modifier .fillMaxSize() @@ -129,6 +130,7 @@ fun SettingsScreen( .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 32.dp) ) + ShowAllMicrophonesTile() BitrateTile() SamplingRateTile() EncoderTile(snackbarHostState = snackbarHostState) diff --git a/app/src/main/java/app/myzel394/alibi/ui/utils/available-microphones.kt b/app/src/main/java/app/myzel394/alibi/ui/utils/available-microphones.kt index 3601a5c..ec6aa4a 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/utils/available-microphones.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/utils/available-microphones.kt @@ -55,21 +55,24 @@ data class MicrophoneInfo( fun fetchDeviceMicrophones(context: Context): List { return try { val audioManager = context.getSystemService(Context.AUDIO_SERVICE)!! as AudioManager - val availableDevices = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { audioManager.availableCommunicationDevices.map(::fromDeviceInfo) } else { audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS).map(::fromDeviceInfo) } - - availableDevices.filter { - ALLOWED_MICROPHONE_TYPES.contains(it.deviceInfo.type) && it.deviceInfo.isSink - } } catch (error: Exception) { Log.getStackTraceString(error) emptyList() } } + + /// Filter microphones to only show normal ones + fun filterMicrophones(microphones: List): List { + return microphones.filter { + ALLOWED_MICROPHONE_TYPES.contains(it.deviceInfo.type) && it.deviceInfo.isSink + } + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f93dd1b..c56fa4f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -69,4 +69,6 @@ %s disconnected. Alibi will use the default microphone instead. We will automatically switch back to %s once it reconnects. Microphone reconnected %s reconnected! Alibi automatically changed the microphone input to it. + Show hidden microphones + Show all microphones, including internal ones \ No newline at end of file