diff --git a/components/control_plane/src/multimodal/control_plane_multimodal_local_wake.c b/components/control_plane/src/multimodal/control_plane_multimodal_local_wake.c index e6aa506..78cf954 100644 --- a/components/control_plane/src/multimodal/control_plane_multimodal_local_wake.c +++ b/components/control_plane/src/multimodal/control_plane_multimodal_local_wake.c @@ -43,6 +43,8 @@ #define CONTROL_PLANE_LOCAL_WAKE_QUEUE_LEN 4U #define CONTROL_PLANE_LOCAL_WAKE_POLL_MS 100U +#define CONTROL_PLANE_LOCAL_WAKE_BARGE_IN_WAIT_MS 2000U +#define CONTROL_PLANE_LOCAL_WAKE_BARGE_IN_POLL_MS 20U #if CONFIG_TQ_LOCAL_WAKE_TASK_CORE < 0 #define CONTROL_PLANE_LOCAL_WAKE_TASK_CORE tskNO_AFFINITY @@ -151,6 +153,64 @@ static esp_err_t local_wake_start_listening(void) return ESP_OK; } +#if CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_ENABLE +static bool local_wake_prepare_prompt_playback(void) +{ + control_plane_multimodal_runtime_state_t state = {0}; + esp_err_t state_err = control_plane_multimodal_get_runtime_state(&state); + if (state_err != ESP_OK) { + ESP_LOGW(TAG, + "Skip local wake prompt: runtime state unavailable: %s", + esp_err_to_name(state_err)); + return false; + } + + if (!state.remote_responding && !state.request_to_speak_pending) { + return true; + } + + esp_err_t request_err = control_plane_multimodal_send_request_to_speak(); + if (request_err != ESP_OK && request_err != ESP_ERR_INVALID_STATE) { + ESP_LOGW(TAG, + "Skip local wake prompt: barge-in request failed: %s", + esp_err_to_name(request_err)); + return false; + } + + TickType_t started = xTaskGetTickCount(); + TickType_t timeout_ticks = pdMS_TO_TICKS( + CONTROL_PLANE_LOCAL_WAKE_BARGE_IN_WAIT_MS); + if (timeout_ticks == 0U) { + timeout_ticks = 1U; + } + + while ((xTaskGetTickCount() - started) < timeout_ticks) { + local_wake_state_t wake_state = local_wake_snapshot(); + if (wake_state.stop_requested) { + return false; + } + + state_err = control_plane_multimodal_get_runtime_state(&state); + if (state_err == ESP_OK) { + if (!state.connected || !state.has_active_task) { + return false; + } + if (!state.remote_responding && + !state.request_to_speak_pending && + state.server_listening) { + return true; + } + } + vTaskDelay(pdMS_TO_TICKS(CONTROL_PLANE_LOCAL_WAKE_BARGE_IN_POLL_MS)); + } + + ESP_LOGW(TAG, + "Skip local wake prompt: barge-in confirmation timed out after %ums", + (unsigned)CONTROL_PLANE_LOCAL_WAKE_BARGE_IN_WAIT_MS); + return false; +} +#endif + static void local_wake_handle_detection( const domain_local_command_event_t *event) { @@ -178,7 +238,9 @@ static void local_wake_handle_detection( (unsigned)event->detection_generation); #if CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_ENABLE - if (CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_FILE[0] != '\0') { + bool prompt_playback_ready = local_wake_prepare_prompt_playback(); + if (prompt_playback_ready && + CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_FILE[0] != '\0') { esp_err_t prompt_err = domain_runtime_behavior_play_prompt_file( CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_FILE); if (prompt_err != ESP_OK) { diff --git a/components/control_plane/src/multimodal/control_plane_multimodal_session_service.c b/components/control_plane/src/multimodal/control_plane_multimodal_session_service.c index 8047171..1fb37b3 100644 --- a/components/control_plane/src/multimodal/control_plane_multimodal_session_service.c +++ b/components/control_plane/src/multimodal/control_plane_multimodal_session_service.c @@ -1336,6 +1336,7 @@ static void process_text_json(const char *json_text) notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_SERVER_NOT_LISTENING); } } else if (strcmp(output_event->valuestring, "RequestAccepted") == 0) { + stop_local_downstream_playback(); if (lock_state()) { s_server_listening = true; s_remote_responding = false; @@ -1346,7 +1347,6 @@ static void process_text_json(const char *json_text) s_drop_downstream_audio = false; unlock_state(); } - stop_local_downstream_playback(); ESP_LOGI(TAG, "PTT barge-in request accepted"); notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_SERVER_LISTENING); } else if (strcmp(output_event->valuestring, "RespondingStarted") == 0) {