diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt index 8ebf168c..f3246533 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt @@ -179,8 +179,12 @@ class RadioAudioEngine { /** Начать прослушивание канала (переключатель рации вкл). * Тяжёлая инициализация аудио выполняется на io-потоке, не блокируя main. */ - fun start(group: Long) { - if (active && groupId == group) return + fun start(group: Long, onReady: ((Boolean) -> Unit)? = null) { + if (active && groupId == group) { + val version = generation + io.execute { mainHandler.post { onReady?.invoke(active && generation == version && audioTrack != null) } } + return + } mainHandler.removeCallbacks(releaseTalk) val version = ++generation active = true @@ -189,7 +193,7 @@ class RadioAudioEngine { pttHolds.cancel() _talkingFlow.value = false io.execute { - if (!active || generation != version) return@execute + if (!active || generation != version) { mainHandler.post { onReady?.invoke(false) }; return@execute } releaseLocked() audioGroup = group vadWindow.restart(SystemClock.elapsedRealtime()) @@ -201,6 +205,8 @@ class RadioAudioEngine { if (generation == version) active = false } } + val ready = active && generation == version && audioTrack != null + mainHandler.post { onReady?.invoke(ready && active && generation == version) } } } diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt index 136a120e..c8b8701a 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt @@ -991,9 +991,26 @@ class ChatViewModel : ViewModel() { fun toggleRadio() { val ch = _currentChannel.value ?: return + setRadioEnabled(ch, radioChannelId != ch.id) + } + + /** Вызов выбирает конкретный канал; повторное принятие не выключает уже работающую рацию. */ + fun enableRadioForCall(channelId: String, onReady: (Boolean) -> Unit) { + val channel = _channels.value.firstOrNull { it.id == channelId } + if (channel == null) { + LogManager.addLog("ERROR", "radio", "Call activation channel missing id=$channelId") + onReady(false); return + } + selectChannel(channel) + if (radioChannelId == channel.id) { + radioAudio.start(channel.id.toULong().toLong(), onReady) + return + } + setRadioEnabled(channel, true, onReady) + } + + private fun setRadioEnabled(ch: Channel, next: Boolean, onReady: ((Boolean) -> Unit)? = null) { val groupId = ch.id.toULongOrNull()?.toLong() ?: return - val wasOnHere = radioChannelId == ch.id - val next = !wasOnHere radioToggleCount++ val caller = Throwable().stackTrace.drop(1).take(8) .joinToString(" <- ") { "${it.className.substringAfterLast('.')}.${it.methodName}:${it.lineNumber}" } @@ -1008,7 +1025,10 @@ class ChatViewModel : ViewModel() { _radioTalkState.value = RadioTalkState(groupId) _radioTalking.value = null NativeLib.radioSetActive(groupId, true) - radioAudio.start(groupId) + radioAudio.start(groupId) { ready -> + if (!ready && radioChannelId == ch.id && !radioAudio.isActive()) turnRadioOff() + onReady?.invoke(ready) + } radioAudio.router.onChanged = { r, headset -> _radioRoute.value = r _radioHeadsetAvailable.value = headset