fix(multimodal): harden playback and client lifecycle handling

- retry the server connection prompt after transient playback failures
- serialize multimodal client and session start-stop operations
- tag downstream responses to ignore stale packets and playback events
- complete bounded teardown and clean callbacks after partial startup
This commit is contained in:
chenjintao
2026-08-14 15:24:29 +08:00
parent c56c65462e
commit 0cfb10252c
12 changed files with 436 additions and 188 deletions
@@ -435,7 +435,9 @@ static const char *domain_wifi_prompt_file_path(domain_wifi_prompt_id_t prompt)
}
}
static void domain_downstream_playback_dispatch(domain_multimodal_downstream_playback_event_type_t type)
static void domain_downstream_playback_dispatch(
domain_multimodal_downstream_playback_event_type_t type,
uint32_t playback_generation)
{
domain_multimodal_downstream_playback_callback_t cb = NULL;
void *cb_user_data = NULL;
@@ -446,32 +448,41 @@ static void domain_downstream_playback_dispatch(domain_multimodal_downstream_pla
const domain_multimodal_downstream_playback_event_t event = {
.type = type,
.playback_generation = playback_generation,
};
cb(&event, cb_user_data);
}
static void domain_downstream_playback_started_adapter(void *user_data)
static void domain_downstream_playback_started_adapter(uint32_t playback_generation,
void *user_data)
{
(void)user_data;
domain_downstream_playback_dispatch(DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STARTED);
domain_downstream_playback_dispatch(DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STARTED,
playback_generation);
}
static void domain_downstream_playback_completed_adapter(void *user_data)
static void domain_downstream_playback_completed_adapter(uint32_t playback_generation,
void *user_data)
{
(void)user_data;
domain_downstream_playback_dispatch(DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_COMPLETED);
domain_downstream_playback_dispatch(DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_COMPLETED,
playback_generation);
}
static void domain_downstream_playback_stopped_adapter(void *user_data)
static void domain_downstream_playback_stopped_adapter(uint32_t playback_generation,
void *user_data)
{
(void)user_data;
domain_downstream_playback_dispatch(DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STOPPED);
domain_downstream_playback_dispatch(DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STOPPED,
playback_generation);
}
static void domain_downstream_playback_stalled_adapter(void *user_data)
static void domain_downstream_playback_stalled_adapter(uint32_t playback_generation,
void *user_data)
{
(void)user_data;
domain_downstream_playback_dispatch(DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STALLED);
domain_downstream_playback_dispatch(DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STALLED,
playback_generation);
}
static void domain_wifi_set_keep_awake_adapter(bool keep_awake, void *user_data)
@@ -687,9 +698,10 @@ esp_err_t domain_runtime_multimodal_audio_play_downstream_opus(const uint8_t *da
return platform_multimodal_audio_play_downstream_opus(data, len);
}
esp_err_t domain_runtime_multimodal_audio_begin_downstream_response(void)
esp_err_t domain_runtime_multimodal_audio_begin_downstream_response(
uint32_t *out_playback_generation)
{
return platform_multimodal_audio_begin_downstream_response();
return platform_multimodal_audio_begin_downstream_response(out_playback_generation);
}
esp_err_t domain_runtime_multimodal_audio_finish_downstream_response(void)