mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
feat: Allow user to show all hidden microphones
This commit is contained in:
parent
3f72efc8e6
commit
c15c4b59fa
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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>
|
Loading…
x
Reference in New Issue
Block a user