Files
arcs/apps/arcs-mini/tone/app_tone.c
2026-08-13 16:50:52 +08:00

175 lines
4.8 KiB
C

#define TAG "tone"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "app_tone.h"
#include "lisa_log.h"
#include "lisa_mem.h"
#include "config_parser.h"
#include "romfs/romfs.h"
#include "tone.h"
static tone_hdr_t *s_tone_hdr = NULL;
static void _app_tone_uninit()
{
if (s_tone_hdr) {
if (s_tone_hdr->item) {
for (int i = 0; i < s_tone_hdr->total_cnt; i++) {
if (s_tone_hdr->item[i].url) {
lisa_mem_free(s_tone_hdr->item[i].url);
}
}
lisa_mem_free(s_tone_hdr->item);
}
lisa_mem_free(s_tone_hdr);
s_tone_hdr = NULL;
}
}
int app_tone_init(uint32_t flash_addr, uint32_t flash_size)
{
struct romfs *tone_fs = NULL;
struct romfs_dir_iter iter;
char path[ROMFS_PATH_MAX];
uint8_t *data = NULL;
uint32_t size = 0;
bool is_dir = false;
int tone_id = 0;
int tone_id_max = 0;
char tone_url[MAX_URL_LEN];
uint32_t total_mem_size = 0;
_app_tone_uninit();
if (flash_addr == 0 || flash_size == 0) {
LISA_LOGE(TAG, "Invalid tone ROMFS addr/size: addr=%p, size=%u", (void *)flash_addr, flash_size);
return -1;
}
s_tone_hdr = lisa_mem_calloc(1, sizeof(tone_hdr_t));
if (!s_tone_hdr) {
return -1;
}
total_mem_size += sizeof(tone_hdr_t);
// 初始化 ROMFS
if (romfs_init(&tone_fs, (const void *)flash_addr, flash_size) != 0) {
LISA_LOGE(TAG, "ROMFS init failed for tone addr=%p size=%u", (void *)flash_addr, flash_size);
goto TONE_INIT_FAIL;
}
LISA_LOGI(TAG, "Loading tone with ROMFS addr=%p size=%u", (void *)flash_addr, flash_size);
// 预扫描一遍,获取最大 tone_id
if (romfs_dir_iter_start(tone_fs, "/", &iter) != 0) {
LISA_LOGE(TAG, "ROMFS iterator start fail for tone");
goto TONE_INIT_FAIL;
}
while (romfs_dir_iter_next(&iter, path, sizeof(path), &data, &size, &is_dir) == 0) {
if (is_dir || data == NULL || size == 0 || path[0] != '/' || strlen(path) < 5) {
continue;
}
if (sscanf(path + 1, "%03d", &tone_id) != 1) {
continue;
}
if (tone_id > tone_id_max) {
tone_id_max = tone_id;
}
}
s_tone_hdr->total_cnt = tone_id_max + 1;
LISA_LOGI(TAG, "Found %d tones", s_tone_hdr->total_cnt);
// 分配 tone 映射表
total_mem_size += (s_tone_hdr->total_cnt * sizeof(tone_dsc_t));
s_tone_hdr->item = lisa_mem_calloc(s_tone_hdr->total_cnt, sizeof(tone_dsc_t));
if (!s_tone_hdr->item) {
LISA_LOGE(TAG, "Failed to alloc tone item table for %d items", s_tone_hdr->total_cnt);
goto TONE_INIT_FAIL;
}
// 从 ROMFS 创建音频索引
if (romfs_dir_iter_start(tone_fs, "/", &iter) != 0) {
LISA_LOGE(TAG, "ROMFS iterator start fail for tone");
goto TONE_INIT_FAIL;
}
while (romfs_dir_iter_next(&iter, path, sizeof(path), &data, &size, &is_dir) == 0) {
LISA_LOGD(TAG, "Found ROMFS file: %s, addr=%p size=%u", path, data, size);
if (is_dir || data == NULL || size == 0 || path[0] != '/' || strlen(path) < 5) {
continue;
}
if (sscanf(path + 1, "%03d", &tone_id) != 1) {
LISA_LOGI(TAG, "Ignore invalid tone file: %s", path);
continue;
}
if (tone_id >= s_tone_hdr->total_cnt) {
LISA_LOGW(TAG, "Tone id %d exceed max %d", tone_id, s_tone_hdr->total_cnt);
continue;
}
char tone_url[MAX_URL_LEN];
memset(tone_url, 0, MAX_URL_LEN);
snprintf(tone_url, MAX_URL_LEN, "mem://addr=%usize=%u", (uint32_t)data, size);
uint32_t url_len = strlen(tone_url) + 1;
s_tone_hdr->item[tone_id].tone_id = tone_id;
s_tone_hdr->item[tone_id].url = lisa_mem_alloc(url_len);
if (!s_tone_hdr->item[tone_id].url) {
LISA_LOGE(TAG, "Tone URL alloc fail for id %d", tone_id);
goto TONE_INIT_FAIL;
}
strcpy(s_tone_hdr->item[tone_id].url, tone_url);
total_mem_size += url_len;
LISA_LOGI(TAG, "Loaded tone[%d] from ROMFS: %s, size: %u", tone_id, path, size);
}
LISA_LOGI(TAG, "Loaded %d tones from ROMFS, total mem size: %u bytes", s_tone_hdr->total_cnt, total_mem_size);
return 0;
TONE_INIT_FAIL:
_app_tone_uninit();
return -1;
}
char *app_tone_get_url(uint16_t tone_id)
{
tone_dsc_t *item = NULL;
if (!s_tone_hdr || !s_tone_hdr->item) {
LISA_LOGE(TAG, "Tone not init or no item");
return NULL;
}
if (tone_id >= s_tone_hdr->total_cnt) {
LISA_LOGE(TAG, "Invalid tone id %d, exceed max %d", tone_id, s_tone_hdr->total_cnt);
return NULL;
}
item = &s_tone_hdr->item[tone_id];
if (item->url == NULL) {
LISA_LOGE(TAG, "Tone id %d url is null", tone_id);
return NULL;
}
return item->url;
}