Browse Source

Move Android VAD activation to the radio toolbar

master
evgeny 7 days ago
parent
commit
9ff1f5645f
  1. 1
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt
  2. 13
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/ChatScreen.kt
  3. 13
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/SettingsScreen.kt
  4. 13
      tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt
  5. 2
      tools/chatgui-android/app/src/main/res/values-ru/strings.xml
  6. 2
      tools/chatgui-android/app/src/main/res/values/strings.xml

1
tools/chatgui-android/app/src/main/java/com/utun/chat/data/ConfigProvider.kt

@ -349,6 +349,7 @@ class ConfigProvider(private val context: Context) {
}
val radioOverlayEnabled: Flow<Boolean> = context.dataStore.data.map { it[radioOverlayKey] ?: false }
val radioVadEnabled: Flow<Boolean> = context.dataStore.data.map { (it[radioVadEnabledKey] ?: 0) != 0 }
@Volatile private var radioOverlayCached = false
@Volatile private var radioOverlayLoaded = false

13
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/ChatScreen.kt

@ -249,7 +249,7 @@ private fun RadioPttButton(
}
}
/* Единый выбор входа/выхода и переключатель плавающей PTT-кнопки. */
/* Единый выбор входа/выхода, VAD и плавающая PTT-кнопка. */
@Composable
private fun RadioSourceBar(viewModel: ChatViewModel) {
val radioAuto by viewModel.radioAuto.collectAsState()
@ -260,6 +260,7 @@ private fun RadioSourceBar(viewModel: ChatViewModel) {
val provider = ChatApplication.instance.configProvider
val scope = rememberCoroutineScope()
val overlayEnabled by provider.radioOverlayEnabled.collectAsState(initial = provider.getRadioOverlay())
val vadEnabled by provider.radioVadEnabled.collectAsState(initial = provider.getInt("radio.vad_enabled") != 0)
val overlayShown by RadioOverlayService.isShown.collectAsState()
val overlayStatus by RadioOverlayService.status.collectAsState()
@ -299,6 +300,10 @@ private fun RadioSourceBar(viewModel: ChatViewModel) {
}
}
VerticalDivider(modifier = Modifier.height(32.dp), color = Color(0xFF344550))
RadioControlButton(null, stringResource(if (vadEnabled) R.string.disable_vad else R.string.enable_vad),
vadEnabled, text = stringResource(R.string.vad_button)) {
viewModel.setRadioVad(!vadEnabled)
}
RadioControlButton(null, stringResource(R.string.floating_ptt), overlayShown, floating = true) {
scope.launch {
if (overlayEnabled && !overlayShown) RadioOverlayService.requestPermissions()
@ -317,7 +322,7 @@ private fun RadioSourceBar(viewModel: ChatViewModel) {
@Composable
private fun RadioControlButton(
icon: ImageVector?, label: String, active: Boolean,
centerIcon: ImageVector? = null, bluetooth: Boolean = false, floating: Boolean = false, onClick: () -> Unit
centerIcon: ImageVector? = null, bluetooth: Boolean = false, floating: Boolean = false, text: String? = null, onClick: () -> Unit
) {
IconToggleButton(
checked = active,
@ -327,6 +332,10 @@ private fun RadioControlButton(
containerColor = Color(0xFF24323D), contentColor = Color(0xFFAEBCC8),
checkedContainerColor = Color(0xFF1F6FEB), checkedContentColor = Color.White)
) {
if (text != null) {
Text(text, fontSize = 12.sp, modifier = Modifier.semantics { contentDescription = label })
return@IconToggleButton
}
if (floating) {
RadioFloatingIcon(label)
return@IconToggleButton

13
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/SettingsScreen.kt

@ -567,24 +567,11 @@ private fun RadioSettingsTab() {
modifier = Modifier.padding(16.dp).verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
var vadEnabled by remember { mutableStateOf(provider.getInt("radio.vad_enabled") != 0) }
var vadThreshold by remember { mutableStateOf(provider.getInt("radio.vad_threshold")) }
var vadHangover by remember { mutableStateOf(provider.getInt("radio.vad_hangover_ms")) }
var vadCompMaxGain by remember { mutableStateOf(provider.getInt("radio.vad_compressor_max_gain_db")) }
val vadActive by RadioAudioEngine.instance().vadActiveFlow.collectAsState()
Text(stringResource(R.string.radio_vad), style = MaterialTheme.typography.titleMedium)
Row(verticalAlignment = Alignment.CenterVertically) {
Text(stringResource(R.string.enable_vad), modifier = Modifier.weight(1f))
Switch(checked = vadEnabled, onCheckedChange = { enabled ->
vadEnabled = enabled
scope.launch {
provider.setValue("radio.vad_enabled", if (enabled) "1" else "0")
NativeLib.setChatSetting("radio_vad_enabled", if (enabled) "1" else "0")
if (enabled) RadioOverlayService.requestPermissions() else RadioOverlayService.sync(ChatApplication.instance)
RadioAudioEngine.instance().reconfigure()
}
})
}
Text(stringResource(if (vadActive) R.string.vad_active else R.string.vad_inactive),
style = MaterialTheme.typography.bodySmall)
Text(stringResource(R.string.vad_screen_hint),

13
tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt

@ -661,6 +661,19 @@ class ChatViewModel : ViewModel() {
radioAudio.talkEnd()
}
/** Переключатель авто-PTT на панели рации: сохранить выбор и перенастроить захват. */
fun setRadioVad(enabled: Boolean) {
if (!_radioActive.value) return
viewModelScope.launch {
val ctx = ChatApplication.instance
ctx.configProvider.setValue("radio.vad_enabled", if (enabled) "1" else "0")
NativeLib.setChatSetting("radio_vad_enabled", if (enabled) "1" else "0")
LogManager.addLog("INFO", "RadioAudio", "Panel VAD enabled=$enabled channel=$radioChannelId")
if (enabled) RadioOverlayService.requestPermissions() else RadioOverlayService.sync(ctx)
radioAudio.reconfigure()
}
}
/** Ручной выбор выхода рации (динамик/гарнитура) — синхронизирует вход. */
fun setRadioRoute(r: AudioRoute) {
if (!_radioActive.value) return

2
tools/chatgui-android/app/src/main/res/values-ru/strings.xml

@ -205,6 +205,8 @@
<string name="delete_all">"Удалить всё"</string>
<string name="radio_vad">"Автоматическая передача по голосу (VAD)"</string>
<string name="enable_vad">"Включить VAD"</string>
<string name="disable_vad">"Выключить VAD"</string>
<string name="vad_button">"VAD"</string>
<string name="vad_active">"VAD активен: микрофон включён"</string>
<string name="vad_inactive">"VAD неактивен"</string>
<string name="vad_screen_hint">"Работает 15 минут при включённом экране. При следующем включении экрана запускается автоматически."</string>

2
tools/chatgui-android/app/src/main/res/values/strings.xml

@ -205,6 +205,8 @@
<string name="delete_all">"Delete all"</string>
<string name="radio_vad">"Automatic voice transmission (VAD)"</string>
<string name="enable_vad">"Enable VAD"</string>
<string name="disable_vad">"Disable VAD"</string>
<string name="vad_button">"VAD"</string>
<string name="vad_active">"VAD active: microphone is on"</string>
<string name="vad_inactive">"VAD inactive"</string>
<string name="vad_screen_hint">"Runs for 15 minutes while the screen is on. Starts automatically when the screen turns on again."</string>

Loading…
Cancel
Save