feat: Allow user to show all hidden microphones

This commit is contained in:
Myzel394 2023-10-21 23:47:04 +02:00
parent 3f72efc8e6
commit c15c4b59fa
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
6 changed files with 90 additions and 8 deletions

View File

@ -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

View File

@ -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)

View File

@ -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,
)
},
)
}

View File

@ -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)

View File

@ -55,21 +55,24 @@ data class MicrophoneInfo(
fun fetchDeviceMicrophones(context: Context): List<MicrophoneInfo> {
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<MicrophoneInfo>): List<MicrophoneInfo> {
return microphones.filter {
ALLOWED_MICROPHONE_TYPES.contains(it.deviceInfo.type) && it.deviceInfo.isSink
}
}
}

View File

@ -69,4 +69,6 @@
<string name="ui_audioRecorder_error_microphoneDisconnected_message"><xliff:g name="name">%s</xliff:g> disconnected. Alibi will use the default microphone instead. We will automatically switch back to <xliff:g name="nam">%s</xliff:g> once it reconnects.</string>
<string name="ui_audioRecorder_error_microphoneReconnected_title">Microphone reconnected</string>
<string name="ui_audioRecorder_error_microphoneReconnected_message"><xliff:g name="name">%s</xliff:g> reconnected! Alibi automatically changed the microphone input to it.</string>
<string name="ui_settings_option_showAllMicrophones_title">Show hidden microphones</string>
<string name="ui_settings_option_showAllMicrophones_description">Show all microphones, including internal ones</string>
</resources>