ln: 2687/1
authorluozheng <1732036298@qq.com>
Wed, 5 Nov 2025 09:31:45 +0000 (17:31 +0800)
committerluozheng <1732036298@qq.com>
Wed, 5 Nov 2025 09:31:45 +0000 (17:31 +0800)
1.ota界面添加升级描述更新
2.解决日程界面无语音播放问题

14 files changed:
code/sdk/application/wearable/ln/nativeapp/nativeui/include/uiservice/ui_service.h
code/sdk/application/wearable/ln/nativeapp/nativeui/ota/include/OtaModel.h
code/sdk/application/wearable/ln/nativeapp/nativeui/ota/src/OtaModel.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/ota/src/OtaNormalView.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/ota/src/OtaObviousView.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/ota/src/OtaUpdateNowView.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/uiservice/src/ui_service.cpp
code/sdk/zhihui/leiniao/imsl_ln/ln_api_ota.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api_schedule.c
code/sdk/zhihui/leiniao/ln_api_cpp/CMakeLists.txt
code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.cpp
code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.h
code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.cpp [new file with mode: 0644]
code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.h [new file with mode: 0644]

index a7ce3d1..c950878 100644 (file)
@@ -72,6 +72,7 @@ typedef enum {
     HAND_AUDIO_RECORDING_END_NOTIFY, // 录音结束通知
     HAND_NPC_EMOTION_CHANGE_NOTIFY, // npc表情变化通知
     HAND_TIMELINE_STATUS_CHANGE_NOTIFY, // 时间线状态变化通知
+    HAND_UPGRADE_DESCRIPTION_NOTIFY, // 升级描述通知
     MAX_NUM_HANDLER, 
 } UiServiceMsgId;
 
index 5618ccf..6a03427 100644 (file)
@@ -72,6 +72,9 @@ namespace OHOS
         void HandleDownloadProgress(int progress);  
         void HandleDownloadEta(int seconds);
         void HandleDownloadFail(int type);
+        
+        void SetUpgradeDescription(const std::string& description);
+        std::string GetUpgradeDescription() const;
     private:
         OtaModel();
         virtual ~OtaModel();
@@ -92,6 +95,8 @@ namespace OHOS
         
         // 夜间更新状态
         bool m_nightUpdateEnabled; // 夜间更新是否启用
+
+        std::string m_upgradeDescription; // 升级描述
     };
 }
 
index 505d062..c0a8bcc 100644 (file)
@@ -497,4 +497,14 @@ namespace OHOS
         UtilsSetValue("night_update_enabled", "0");
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "OtaModel: Night update status cleared from KV storage");
     }
+
+    void OtaModel::SetUpgradeDescription(const std::string& description)
+    {
+        m_upgradeDescription = description;
+    }
+
+    std::string OtaModel::GetUpgradeDescription() const
+    {
+        return m_upgradeDescription;
+    }
 }
index cbe21bf..4489412 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "ota/include/OtaNormalView.h"
 #include "ota/include/OtaPresenter.h"
+#include "ota/include/OtaModel.h"
 #include "wearable_log.h"
 
 namespace OHOS
@@ -62,7 +63,7 @@ namespace OHOS
             LittleTextLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
             LittleTextLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 18);
             LittleTextLabel->SetStyle(STYLE_TEXT_COLOR, 0xffcccccc);
-            LittleTextLabel->SetText("全新功能已推出,现在Amby可以哄你睡觉");
+            LittleTextLabel->SetText(OtaModel::GetInstance()->GetUpgradeDescription().c_str());
             LittleTextLabel->SetVisible(true);
             group->Add(LittleTextLabel);
         }
index 51ddb48..fe5c90f 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "ota/include/OtaObviousView.h"
 #include "ota/include/OtaPresenter.h"
+#include "ota/include/OtaModel.h"
 #include "wearable_log.h"
 
 namespace OHOS
@@ -64,7 +65,7 @@ namespace OHOS
             LittleTextLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
             LittleTextLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 18);
             LittleTextLabel->SetStyle(STYLE_TEXT_COLOR, 0xffcccccc);
-            LittleTextLabel->SetText("全新功能已推出,现在Amby可以哄你睡觉");
+            LittleTextLabel->SetText(OtaModel::GetInstance()->GetUpgradeDescription().c_str());
             LittleTextLabel->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
             LittleTextLabel->SetVisible(true);
             group->Add(LittleTextLabel);
index c41183e..6e0ea54 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include "ota/include/OtaUpdateNowView.h"
 #include "ota/include/OtaPresenter.h"
+#include "ota/include/OtaModel.h"
 #include "wearable_log.h"
 
 namespace OHOS
@@ -65,7 +66,7 @@ namespace OHOS
             LittleTextLabel->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
             LittleTextLabel->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 18);
             LittleTextLabel->SetStyle(STYLE_TEXT_COLOR, 0xffcccccc);
-            LittleTextLabel->SetText("为保障您的产品安全,部分功能将在更新后恢复使用");
+            LittleTextLabel->SetText(OtaModel::GetInstance()->GetUpgradeDescription().c_str());
             LittleTextLabel->SetVisible(true);
             group->Add(LittleTextLabel);
         }
index 79dcafe..c29510e 100644 (file)
@@ -108,6 +108,7 @@ static void HandAudioRecordingStartNotify(Request *request);
 static void HandAudioRecordingEndNotify(Request *request);
 static void HandNpcEmotionChangeNotify(Request *request);
 static void HandTimelineStatusChangeNotify(Request *request);
+static void HandUpgradeDescriptionNotify(Request *request);
 // 消息处理程序项数组(每个消息类型对应一个处理函数,函数名以 Handle 开头)
 MsgHandlerEntry msgHandlers[] = {
     {HANDLE_JUMP_OTA_VIEW, HandleJumpOtaView},
@@ -132,6 +133,7 @@ MsgHandlerEntry msgHandlers[] = {
     {HAND_AUDIO_RECORDING_END_NOTIFY,HandAudioRecordingEndNotify},
     {HAND_NPC_EMOTION_CHANGE_NOTIFY,HandNpcEmotionChangeNotify},
     {HAND_TIMELINE_STATUS_CHANGE_NOTIFY,HandTimelineStatusChangeNotify},
+    {HAND_UPGRADE_DESCRIPTION_NOTIFY,HandUpgradeDescriptionNotify},
 };
 /* -------------------------------------------------------------------------- */
 void ScreenTurnOn(int32_t timeout)
@@ -777,6 +779,15 @@ void HandTimelineStatusChangeNotify(Request *request)
             }
         });
 }
+
+void HandUpgradeDescriptionNotify(Request *request)
+{
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandUpgradeDescriptionNotify msg_id = %d", request->msgId);
+    std::string description(static_cast<char*>(request->data), request->len);
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandUpgradeDescriptionNotify description = %s", description.c_str());
+    GraphicService::GetInstance()->PostGraphicEvent(
+        std::bind(&OHOS::OtaModel::SetUpgradeDescription,OHOS::OtaModel::GetInstance(), description.c_str()));
+}
 /* -------------------------------------------------------------------------- */
 #ifdef __cplusplus
 }
index f394b39..ea53de2 100644 (file)
@@ -160,11 +160,33 @@ static void ln_handle_ota_task_response(const char *json_buf, int json_len)
         return;
     }
 
+    /*
+        {
+            "errorCode": null,
+            "message": null,
+            "data": {
+                "updateId": 123,  升级任务ID
+                "sourceVersion": "1.0.0", 源版本号
+                "targetVersion": "1.1.0", 目标版本号
+                "updateType": 1, 升级类型,0:紧急修复,1:重要更新,2:普通更新
+                "packageId": 456, 升级包ID
+                "packageUrl": "https://example.com/firmware/update_1.1.0.bin", 升级包下载URL
+                "packageMd5": "a1b2c3d4e5f6789012345678901234567890", 升级包MD5校验值
+                "packageSize": 1048576, 升级包大小(字节)
+                "description": "升级描述" 升级描述
+            }
+        }
+    */
+
+    cJSON *updateId = cJSON_GetObjectItem(data, "updateId");
+    cJSON *sourceVersion = cJSON_GetObjectItem(data, "sourceVersion");
     cJSON *targetVersion = cJSON_GetObjectItem(data, "targetVersion");
     cJSON *updateType = cJSON_GetObjectItem(data, "updateType");
+    cJSON *packageId = cJSON_GetObjectItem(data, "packageId");
     cJSON *packageUrl  = cJSON_GetObjectItem(data, "packageUrl");
     cJSON *packageMd5  = cJSON_GetObjectItem(data, "packageMd5");
     cJSON *packageSize = cJSON_GetObjectItem(data, "packageSize");
+    cJSON *description = cJSON_GetObjectItem(data, "description");
     uapi_ln_set_ota_package_size(packageSize ? (int)packageSize->valuedouble : 0);
 
     if (!(targetVersion && cJSON_IsString(targetVersion) && updateType && (cJSON_IsNumber(updateType) || cJSON_IsString(updateType))))
@@ -181,10 +203,11 @@ static void ln_handle_ota_task_response(const char *json_buf, int json_len)
     else if (cJSON_IsString(updateType)) ut = atoi(updateType->valuestring);
     g_ln_last_update_type = ut;
 
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] task parsed: targetVersion=%s updateType=%d url=%s md5=%s",
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] task parsed: targetVersion=%s updateType=%d url=%s md5=%s description=%s",
            targetVersion->valuestring, ut,
            (packageUrl && cJSON_IsString(packageUrl)) ? packageUrl->valuestring : "<null>",
-           (packageMd5 && cJSON_IsString(packageMd5)) ? packageMd5->valuestring : "<null>");
+           (packageMd5 && cJSON_IsString(packageMd5)) ? packageMd5->valuestring : "<null>",
+           (description && cJSON_IsString(description)) ? description->valuestring : "<null>");
     /* 记录必要字段供后续 AT^LN_OTA_DOWNLOAD 使用 */
     if (g_ln_last_target_version) { free(g_ln_last_target_version); g_ln_last_target_version = NULL; }
     if (g_ln_last_package_url) { free(g_ln_last_package_url); g_ln_last_package_url = NULL; }
@@ -210,21 +233,23 @@ static void ln_handle_ota_task_response(const char *json_buf, int json_len)
         if (g_ln_last_package_size < 0) g_ln_last_package_size = 0;
     }
 
-    if (ut == 1)
+    if (description && cJSON_IsString(description)) {
+        push_upgrade_description_notification(description->valuestring);
+    } else {
+        push_upgrade_description_notification("");
+    }
+    
+    if (ut == 0)
     {
         /* 强制升级:直接触发下载 */
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] force upgrade: trigger download(强制升级:直接触发下载)");
         push_ota_status(OTA_UI_STATUS_FORCE_START);
     }
-    else if (ut == 0)
+    else
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] optional upgrade: waiting for user confirmation(可选升级:等待用户确认)");
         push_ota_status(OTA_UI_STATUS_OPTIONAL_START);
     }
-    else
-    {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"[OTA] unknown updateType, skip");
-    }
 
     cJSON_Delete(root);
     free(text);
index 2353a6b..ed8b78e 100644 (file)
@@ -7,6 +7,7 @@
 #include "wearable_log.h"
 #include "ai_media.h"
 #include "audio_stream_player.h"
+#include "ln_audio_simple.h"
 
 ScheduleReminder g_schedule_reminder = {0};
 ScheduleReminderConfig g_schedule_reminder_config = {0};
@@ -232,9 +233,10 @@ void ln_parse_schedule_reminder(const char *json_buf, int json_len)
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] vibration:不执行震动\n");
             }
             // 从文件中读取数据放到音频流内
-            play_mp3_audio_from_file(LN_REMINDER_AUDIO_FILE);
+            // play_mp3_audio_from_file(LN_REMINDER_AUDIO_FILE);
             // 下载成功后
             // ln_audio_player_play_file(LN_REMINDER_AUDIO_FILE);
+            ln_audio_simple_play(LN_REMINDER_AUDIO_FILE);
         }
         else
         {
index 2ac4dd9..2ca54bd 100644 (file)
@@ -16,12 +16,16 @@ ${ROOT_DIR}/middleware/services/media/foundation/audiomanager/frameworks/audiost
 ${ROOT_DIR}/middleware/services/media/foundation/sample/wrapper
 ${ROOT_DIR}/middleware/services/media/foundation/utils/include
 ${ROOT_DIR}/application/wearable/ln/nativeapp/nativeui/
+${ROOT_DIR}/open_source/openharmony/foundation/multimedia/player/interfaces/kits/
+${ROOT_DIR}/middleware/services/gui/uikit/surface/interfaces/kits/
+${ROOT_DIR}/open_source/openharmony/drivers/peripheral/display/interfaces/include/
 )
 
 set(AI_SOURCES
 ${CMAKE_CURRENT_SOURCE_DIR}/audio_stream_player.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/ln_api_interface.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/audio_stream_player.cpp
+${CMAKE_CURRENT_SOURCE_DIR}/ln_audio_simple.cpp
 )
 
 set(SOURCES
index 3519492..bfa7c57 100644 (file)
@@ -298,6 +298,13 @@ void push_timeline_status_change_notification(const char *description, const cha
     (void)snprintf(payload, sizeof(payload) - 1, "%s|%s", d, e);
     SendMsgToUIService(HAND_TIMELINE_STATUS_CHANGE_NOTIFY, 0, (void *)payload, (int32_t)strlen(payload));
 }
+
+//推送升级描述
+void push_upgrade_description_notification(const char *description)
+{
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[UPGRADE_DESCRIPTION] description=%s", description);
+    SendMsgToUIService(HAND_UPGRADE_DESCRIPTION_NOTIFY, 0, (void *)description, (int32_t)strlen(description));
+}
 #ifdef __cplusplus
 };
 #endif
\ No newline at end of file
index befc686..e6cccc3 100644 (file)
@@ -111,6 +111,8 @@ void push_audio_recording_end_notification(void);
 void push_npc_emotion_change_notification(const char *emotion);
 //通知时间线状态变化
 void push_timeline_status_change_notification(const char *description, const char *emotion);
+//推送升级描述
+void push_upgrade_description_notification(const char *description);
 #ifdef __cplusplus
 }
 #endif
diff --git a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.cpp b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.cpp
new file mode 100644 (file)
index 0000000..95ff3a3
--- /dev/null
@@ -0,0 +1,264 @@
+#include <memory>
+#include <map>
+/* C 接口头文件 */
+#include "ln_audio_simple.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+/* 引入播放器相关头文件 */
+#include "player.h"
+#include "source.h"
+#include "audio_manager.h"
+#include <audio_base_type.h>
+#include <audio_player_service.h>
+#include <custom_utils.h>
+#include <los_base.h>
+
+using OHOS::Media::Player;
+using OHOS::Media::Source;
+using namespace OHOS::Media;
+using namespace ::Audio;
+using Audio::AudioManager;
+
+
+
+typedef struct
+{
+    std::shared_ptr<Player> player;
+    std::shared_ptr<Source> source;
+    std::map<std::string, std::string> header;
+
+    AudioSession sessionId;
+    std::shared_ptr<AudioInterrupt> interrupt;
+    std::shared_ptr<InterruptListener> interruptListener;
+
+    bool audio_initialized;
+    bool is_activate_audio_interrupt;
+    bool is_playing;
+    bool is_paused;
+} ln_audio_simple_impl_t;
+
+static ln_audio_simple_impl_t g_simple = {0};
+
+class SimpleSingleInterruptListener : public InterruptListener
+{
+public:
+    SimpleSingleInterruptListener(ln_audio_simple_impl_t *impl) : impl_(impl) {}
+
+    void OnInterrupt(int32_t type, int32_t hint) override
+    {
+        if (!impl_) return;
+        if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_PAUSE)
+        {
+            if (impl_->is_playing && impl_->player)
+            {
+                impl_->player->Pause();
+                impl_->is_paused = true;
+            }
+        }
+        else if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_RESUME)
+        {
+            if (impl_->is_playing && impl_->player && impl_->is_paused)
+            {
+                impl_->player->Play();
+                impl_->is_paused = false;
+            }
+        }
+        else if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_STOP)
+        {
+            if (impl_->is_playing && impl_->player)
+            {
+                impl_->player->Stop();
+                impl_->is_playing = false;
+            }
+        }
+    }
+
+private:
+    ln_audio_simple_impl_t *impl_;
+};
+
+static bool AudioInitOnce(void)
+{
+    if (g_simple.audio_initialized)
+        return true;
+
+    AudioManager &amInstance = AudioManager::GetInstance();
+    if (!amInstance.Initialize())
+    {
+        printf("[LN_AUDIO_SIMPLE] AudioManager Initialize failed\n");
+        return false;
+    }
+
+    g_simple.player = std::make_shared<Player>();
+    if (!g_simple.player)
+    {
+        printf("[LN_AUDIO_SIMPLE] Player create failed\n");
+        return false;
+    }
+
+    g_simple.audio_initialized = true;
+    g_simple.is_activate_audio_interrupt = false;
+    g_simple.is_playing = false;
+    g_simple.is_paused = false;
+    return true;
+}
+
+static bool EnsureAudioInterrupt()
+{
+    if (g_simple.is_activate_audio_interrupt)
+        return true;
+
+    AudioManager &amInstance = AudioManager::GetInstance();
+    g_simple.sessionId = amInstance.MakeSessionId();
+    if (g_simple.sessionId == AUDIO_SESSION_ID_NONE)
+    {
+        printf("[LN_AUDIO_SIMPLE] MakeSessionId failed\n");
+        return false;
+    }
+
+    g_simple.interruptListener = std::make_shared<SimpleSingleInterruptListener>(&g_simple);
+    g_simple.interrupt = std::make_shared<AudioInterrupt>();
+    g_simple.interrupt->streamType = AUDIO_STREAM_ALARM_CLOCK;
+    g_simple.interrupt->sessionID = g_simple.sessionId;
+    g_simple.interrupt->interruptListener = g_simple.interruptListener;
+
+    if (amInstance.ActivateAudioInterrupt(*g_simple.interrupt) == INTERRUPT_FAILED)
+    {
+        printf("[LN_AUDIO_SIMPLE] ActivateAudioInterrupt failed\n");
+        return false;
+    }
+
+    g_simple.is_activate_audio_interrupt = true;
+    return true;
+}
+
+static void ClearAudioInterrupt()
+{
+    if (g_simple.is_activate_audio_interrupt && g_simple.interrupt && g_simple.sessionId != AUDIO_SESSION_ID_NONE)
+    {
+        AudioManager &amInstance = AudioManager::GetInstance();
+        amInstance.DeactivateAudioInterrupt(*g_simple.interrupt);
+        g_simple.is_activate_audio_interrupt = false;
+    }
+    g_simple.interrupt.reset();
+    g_simple.interruptListener.reset();
+}
+
+extern "C" {
+
+int ln_audio_simple_play(const char *file_path)
+{
+    if (!file_path || file_path[0] == '\0')
+    {
+        printf("[LN_AUDIO_SIMPLE] invalid file path\n");
+        return -1;
+    }
+
+    if (!AudioInitOnce())
+        return -2;
+
+    // 若正在播放,先停止
+    (void)ln_audio_simple_stop();
+
+    // 设置音频源
+    g_simple.source = std::make_shared<Source>(file_path, g_simple.header);
+    if (!g_simple.source)
+    {
+        printf("[LN_AUDIO_SIMPLE] create Source failed\n");
+        return -3;
+    }
+
+    int32_t ret;
+    ret = g_simple.player->SetSource(*g_simple.source);
+    if (ret != 0)
+    {
+        printf("[LN_AUDIO_SIMPLE] SetSource failed: %d\n", ret);
+        g_simple.player->Reset();
+        return -4;
+    }
+
+    g_simple.player->EnableSingleLooping(false);
+    g_simple.player->SetAudioStreamType(AUDIO_STREAM_ALARM_CLOCK);
+
+    ret = g_simple.player->Prepare();
+    if (ret != 0)
+    {
+        printf("[LN_AUDIO_SIMPLE] Prepare failed: %d\n", ret);
+        g_simple.player->Reset();
+        return -5;
+    }
+
+    if (!EnsureAudioInterrupt())
+    {
+        g_simple.player->Reset();
+        return -6;
+    }
+
+    ret = g_simple.player->SetAudioSessionId(g_simple.sessionId);
+    if (ret != 0)
+    {
+        printf("[LN_AUDIO_SIMPLE] SetAudioSessionId failed: %d\n", ret);
+        g_simple.player->Reset();
+        ClearAudioInterrupt();
+        return -7;
+    }
+
+    ret = g_simple.player->Play();
+    if (ret != 0)
+    {
+        printf("[LN_AUDIO_SIMPLE] Play failed: %d\n", ret);
+        g_simple.player->Stop();
+        g_simple.player->Reset();
+        ClearAudioInterrupt();
+        return -8;
+    }
+
+    g_simple.is_playing = true;
+    g_simple.is_paused = false;
+    printf("[LN_AUDIO_SIMPLE] started: %s\n", file_path);
+    return 0;
+}
+
+int ln_audio_simple_stop(void)
+{
+    if (!g_simple.player)
+        return 0;
+
+    int32_t state = 0;
+    (void)g_simple.player->GetPlayerState(state);
+
+    if (state == PLAYER_STARTED || state == PLAYER_PLAYBACK_COMPLETE)
+    {
+        (void)g_simple.player->Stop();
+        (void)g_simple.player->Reset();
+    }
+    else if (state == PLAYER_PAUSED || state == PLAYER_IDLE)
+    {
+        (void)g_simple.player->Reset();
+    }
+    else
+    {
+        (void)g_simple.player->Stop();
+        (void)g_simple.player->Reset();
+    }
+
+    ClearAudioInterrupt();
+
+    g_simple.is_playing = false;
+    g_simple.is_paused = false;
+    return 0;
+}
+
+bool ln_audio_simple_is_playing(void)
+{
+    return g_simple.is_playing;
+}
+
+} // extern "C"
+
+
diff --git a/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.h b/code/sdk/zhihui/leiniao/ln_api_cpp/ln_audio_simple.h
new file mode 100644 (file)
index 0000000..70eaf9c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 简易音频播放接口(C)
+ * 设计目标:简单、稳定,用一行代码播放单个本地音频文件
+ * 用法示例:
+ *     ln_audio_simple_play("/user/audio/demo.mp3");
+ *     // ... 需要中断播放时:
+ *     ln_audio_simple_stop();
+ *     // 查询是否还在播放:
+ *     // if (ln_audio_simple_is_playing()) { ... }
+ */
+
+#ifndef LN_AUDIO_SIMPLE_H
+#define LN_AUDIO_SIMPLE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * 播放本地音频文件(目前支持常见压缩音频,如 mp3,由底层流式播放器解码)
+ * 参数:
+ *   file_path - 音频文件的绝对路径
+ * 返回:
+ *   0  成功启动播放(异步)
+ *  <0  失败
+ */
+int ln_audio_simple_play(const char *file_path);
+
+/*
+ * 主动停止播放(同步停止,确保资源释放)
+ * 返回:0 成功,<0 失败
+ */
+int ln_audio_simple_stop(void);
+
+/*
+ * 查询当前是否处于播放中
+ */
+bool ln_audio_simple_is_playing(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LN_AUDIO_SIMPLE_H */
+
+