From 659c470eba542383987aad227b7f918100f131fa Mon Sep 17 00:00:00 2001
From: wangzhibo <wangzhibo@shsening.com>
Date: 星期五, 11 九月 2026 15:09:05 +0800
Subject: [PATCH] 小智终端 5种 场景模式 OK

---
 xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c |   89 ++++++++++++++++++++++++++++++++++++--------
 1 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c b/xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c
index a9c94be..d1c2a1f 100644
--- a/xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c
+++ b/xiaozhi-esp32-2.2.6/main/boards/sening-xiaozhi-s3/system.c
@@ -126,6 +126,45 @@
     ESP_LOGI(TAG, "offline command triggered: %s", OFFLINE_COMMAND_WORD);
 }
 
+bool Board_Is_Mode_Switch_Command(const char *command)
+{
+    return command &&
+           (strcmp(command, OFFLINE_COMMAND_WORD) == 0 ||
+            strcmp(command, OFFLINE_COMMAND_WORD_PINYIN) == 0 ||
+            strcmp(command, OFFLINE_COMMAND_WORD_ALT) == 0 ||
+            strcmp(command, OFFLINE_COMMAND_WORD_ALT_PINYIN) == 0);
+}
+
+bool Board_Is_Chat_Return_Command(const char *command)
+{
+    if (!command || command[0] == '\0') {
+        return false;
+    }
+    return strcmp(command, OFFLINE_CHAT_WORD) == 0 ||
+           strcmp(command, OFFLINE_CHAT_WORD_PINYIN) == 0 ||
+           strcmp(command, OFFLINE_CHAT_WORD_FULL) == 0 ||
+           strcmp(command, OFFLINE_CHAT_WORD_FULL_PINYIN) == 0 ||
+           strcmp(command, OFFLINE_EXIT_REPEATER_WORD) == 0 ||
+           strcmp(command, OFFLINE_EXIT_REPEATER_WORD_PINYIN) == 0 ||
+           strcmp(command, OFFLINE_EXIT_SHADOWING_WORD) == 0 ||
+           strcmp(command, OFFLINE_EXIT_SHADOWING_WORD_PINYIN) == 0 ||
+           strstr(command, OFFLINE_CHAT_WORD_FULL) ||
+           strstr(command, OFFLINE_CHAT_WORD) ||
+           strstr(command, OFFLINE_EXIT_REPEATER_WORD) ||
+           strstr(command, OFFLINE_EXIT_SHADOWING_WORD);
+}
+
+bool Board_Is_App_Launch_Command(const char *command)
+{
+    if (!command || command[0] == '\0') {
+        return false;
+    }
+    return strcmp(command, OFFLINE_REPEATER_WORD) == 0 ||
+           strcmp(command, OFFLINE_START_REPEATER_WORD) == 0 ||
+           strstr(command, OFFLINE_REPEATER_WORD) ||
+           strstr(command, OFFLINE_START_REPEATER_WORD);
+}
+
 bool Board_Handle_Offline_Command(const char *command)
 {
     if (!command || Board_Is_Power_Off()) {
@@ -134,7 +173,7 @@
     if (Board_Handle_Voice_Command(command)) {
         return true;
     }
-    if (strcmp(command, OFFLINE_COMMAND_WORD) != 0 && strcmp(command, OFFLINE_COMMAND_WORD_PINYIN) != 0) {
+    if (!Board_Is_Mode_Switch_Command(command)) {
         return false;
     }
 
@@ -530,19 +569,23 @@
     return build_media_list_json(mp3_list_buffer, sizeof(mp3_list_buffer), mp3_name_has_extension);
 }
 
-static bool is_supported_mp3_speed(float speed)
+float SDCard_Clamp_MP3_Speed(float speed)
 {
-    const float supported_speeds[] = {0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 2.0f};
-    for (size_t i = 0; i < sizeof(supported_speeds) / sizeof(supported_speeds[0]); ++i) {
-        float diff = speed - supported_speeds[i];
-        if (diff < 0) {
-            diff = -diff;
-        }
-        if (diff < 0.001f) {
-            return true;
-        }
+    if (speed != speed) {
+        return SDCARD_MP3_SPEED_DEFAULT;
     }
-    return false;
+    if (speed < SDCARD_MP3_SPEED_MIN) {
+        return SDCARD_MP3_SPEED_MIN;
+    }
+    if (speed > SDCARD_MP3_SPEED_MAX) {
+        return SDCARD_MP3_SPEED_MAX;
+    }
+    return speed;
+}
+
+bool SDCard_Resolve_MP3_Path(const char *mp3_name, char *path, size_t path_size)
+{
+    return resolve_mp3_path(mp3_name, path, path_size);
 }
 
 esp_err_t SDCard_Play_MP3(char *mp3_name)
@@ -557,11 +600,7 @@
 
 esp_err_t SDCard_Play_MP3_With_Speed_Repeat(char *mp3_name, float speed, int repeat, bool power_off_after)
 {
-    if (!is_supported_mp3_speed(speed)) {
-        ESP_LOGW(TAG, "invalid MP3 playback speed: %.2f", speed);
-        SDCard_Resume_Play();
-        return ESP_ERR_INVALID_ARG;
-    }
+    speed = SDCard_Clamp_MP3_Speed(speed);
 
     char path[SDCARD_PATH_MAX_LEN];
     if (!resolve_mp3_path(mp3_name, path, sizeof(path))) {
@@ -610,6 +649,22 @@
     return ESP_OK;
 }
 
+esp_err_t SDCard_Ensure_Business_Dir(const char *business_path)
+{
+    char sd_path[SDCARD_PATH_MAX_LEN];
+    esp_err_t err = SDCard_Map_Business_Path(business_path, sd_path, sizeof(sd_path));
+    if (err != ESP_OK) {
+        return err;
+    }
+    err = mkdir_recursive(sd_path);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "ensure dir failed: %s", sd_path);
+        return err;
+    }
+    ESP_LOGI(TAG, "ensure dir: %s", sd_path);
+    return ESP_OK;
+}
+
 esp_err_t SDCard_Prepare_Business_File(const char *business_path,
                                        char *final_path,
                                        size_t final_path_size,

--
Gitblit v1.9.1