A1: meow_audiod 独占音频服务(agent-244 骨架 + agent-246 真机收尾)
- meow_audiod:启动门控(/tmp/meow_boot_mode 非 meow exit 0)、IO/播放/路由三线程、
ring ~200ms、ALSA UAPI 独占直开、切率 mute-重配-恢复、抢占(后开赢+PREEMPTED)、
socket EOF 回收、xrun PREPARE 恢复;meow_route 轮询逻辑并入路由线程
- meow_audio CLI:status/tone/route/vol;services.d/audiod.conf(trigger=manual,on-fail)
- SDK meow_ui_audio.c 编进 meow_ui.a:懒连接/读线程分发 PREEMPTED 回调/EPIPE 标死/
无 audiod 返回 MEOW_ERR_NOENT 不隐式直开(MEOW_AUDIO_DIRECT=1 仅调试)
- launcher:确认 MeowOS 模式后 meow_svcd start audiod(double-fork best-effort 不阻塞)
- meow_route 退役:S89 预置换 audiod.conf + 清理旧 meow_route.conf(防拉起已删二进制
重启循环);fw_content.conf 删 meow_route、加 meow_audiod+meow_audio(md5 打包时填)
- 真机定位并修复 ALSA UAPI 两大坑(即 ncm 播放无声根因):
① hw_params 须全放行初始化(mask 全 1/interval [0,UINT_MAX]),memset 0 interval
等价只能取 0 → refine 必空 → HW_PARAMS 恒 EINVAL
② access/format mask 先清零再单点(pmask 只 OR),全 1 被 choose 成 MMAP_INTERLEAVED
→ write() 恒 EINVAL
- 附带修复:dev_write fd<0 防日志风暴丢 PCM 限频日志;SDK state 解析 app_id 截空白;
meow_ui.h 文档负错误码表述修正
- 验证:宿主 FILE sink 全 IPC 链+抢占+tone WAV 20/20,SDK 客户端 13/13;
qemu-mipsel 同过;真机 tone 44.1k/96k 切率 written=played、underrun=0、日志完整
- meow_ui.a 53a3edd2 → ncm 重链 d2031829(已热更到卡);launcher a2f932a1
This commit is contained in:
1 parent
94874107b6
commit
ade0a57353
24 files changed
+2795
-11
No files matched your search
@@ -1684,6 +1684,30 @@ static void usage(void)
|
||||
* M2.89 回归修复用,见 main() 内「开机选单期不抢屏」。 */
|
||||
#define MEOW_BOOT_MODE_PATH "/tmp/meow_boot_mode"
|
||||
|
||||
/* 拉起独占音频服务(AUDIOD_DESIGN.md §1):launcher 确认 MeowOS 模式后 `meow_svcd start audiod`。
|
||||
* 幂等(svcd cmd_start 在 pid>0 时 no-op)、best-effort(audiod 未装/失败静默)、
|
||||
* 不阻塞主循环(double-fork + 仅 waitpid 立即退出的中间子进程,避免僵尸 + 不占用 fb)。
|
||||
* 双重门控:audiod 自身读 /tmp/meow_boot_mode,非 meow 即 exit(0)——HibyOS 下物理不存在。 */
|
||||
static void meow_audiod_kick(void)
|
||||
{
|
||||
if (access("/usr/bin/meow_audiod", X_OK) != 0) return; /* 固件未装 audiod → 静默 */
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) return;
|
||||
if (pid == 0) {
|
||||
pid_t pid2 = fork(); /* double-fork:隔离执行者,防僵尸 */
|
||||
if (pid2 != 0) _exit(0); /* 中间子进程立即退出,由父进程 waitpid 回收 */
|
||||
{
|
||||
/* 执行者:重定向 stdio 到 /dev/null,exec meow_svcd start audiod */
|
||||
int devnull = open("/dev/null", O_RDWR);
|
||||
if (devnull >= 0) { dup2(devnull, 1); dup2(devnull, 2); if (devnull > 2) close(devnull); }
|
||||
execl("/usr/bin/meow_svcd", "meow_svcd", "start", "audiod", (char *)0);
|
||||
_exit(127);
|
||||
}
|
||||
}
|
||||
waitpid(pid, NULL, 0); /* 等中间子进程退出(即刻返回,不实质阻塞) */
|
||||
logmsg("audiod: meow_svcd start audiod requested");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long sim_hotkey = 0, sim_tap = 0, sim_exit = 0, dumpkeys = 0;
|
||||
@@ -1931,6 +1955,7 @@ int main(int argc, char **argv)
|
||||
/* M2.2 拔营:启动即尝试挂 TF 卡 + 联网(非阻塞);失败由 run_menu 后台周期重试。 */
|
||||
ensure_card_mounted();
|
||||
ensure_wifi();
|
||||
meow_audiod_kick(); /* 确认 MeowOS 模式 → 拉起独占音频服务(幂等、best-effort、不阻塞主循环) */
|
||||
struct app apps[MAX_APPS];
|
||||
int n = scan_apps(apps);
|
||||
int state = (n < 0) ? (n == -1 ? 1 : 2) : (n == 0 ? 2 : 0);
|
||||
|
||||
@@ -78,6 +78,20 @@ enum {
|
||||
* 语义:amsd 为「启动/终止」决策者 → launcher(执行器)执行。payload 见下。 */
|
||||
MSG_AMS_START = 0x00A0, /* → 请求 launcher 拉起某 App(pkg + 可选 activity) */
|
||||
MSG_AMS_KILL = 0x00A1, /* → 请求 launcher 终止某 App(SIGTERM 语义) */
|
||||
/* ---- audiod 独占音频服务(devdocs/plan/AUDIOD_DESIGN.md §2):0x00C0-0x00CA ----
|
||||
* 语义:App 只经 SDK 客户端 API(meow_ui_audio.c)喂 PCM,audiod 独占 hw:0,0。
|
||||
* 独占+抢占(后开赢);软混音已否决(MIPS32 软 SRC 伤音质,留混音器接口位)。 */
|
||||
MSG_AUDIO_OPEN = 0x00C0, /* ↑ 开流(m_audio_open;client 原生 rate/ch/fmt/flags) */
|
||||
MSG_AUDIO_OPEN_ACK = 0x00C1, /* ↓ 授权(stream_id + grant_rate/ch/fmt + err;grant=客户端应产出的格式) */
|
||||
MSG_AUDIO_WRITE = 0x00C2, /* ↑ PCM 字节流(按 grant 格式交织;单帧 ≤4096B,多帧连续发,无回执) */
|
||||
MSG_AUDIO_PAUSE = 0x00C3, /* ↑ 暂停(u32 stream_id) */
|
||||
MSG_AUDIO_RESUME = 0x00C4, /* ↑ 恢复(u32 stream_id) */
|
||||
MSG_AUDIO_STOP = 0x00C5, /* ↑ 停止并关流(u32 stream_id) */
|
||||
MSG_AUDIO_PREEMPTED= 0x00C6, /* ↓ 被抢占通知(m_audio_preempted;旧流被后开流赶走,App 收 UI 提示) */
|
||||
MSG_AUDIO_QUERY = 0x00C7, /* ↑ 状态快照查询(空负载) */
|
||||
MSG_AUDIO_STATE = 0x00C8, /* ↓ 状态快照文本(NUL 结尾;当前流/参数/帧数/underrun/路由/音量) */
|
||||
MSG_AUDIO_ROUTE = 0x00C9, /* ↑ 手动路由(u32 port:0=auto 2=3.5 3=4.4;调试/面板用) */
|
||||
MSG_AUDIO_VOLUME = 0x00CA, /* ↑ 音量(i32 pct:-1=查询 0-100=设置;v1 透传写 DAC numid=1/2) */
|
||||
MSG_SYS = 0x00F0 /* ↓ 系统事件(守护关闭/服务死亡/播放器状态) */
|
||||
};
|
||||
|
||||
@@ -369,4 +383,59 @@ typedef struct m_picker_result {
|
||||
char value[256]; /* 返回项(路径/文本);空=cancel */
|
||||
} m_picker_result_t; /* 320 B */
|
||||
|
||||
/* ================= audiod 独占音频服务(AUDIOD_DESIGN.md) = */
|
||||
|
||||
/* PCM 格式枚举(客户端原生 fmt 与 grant_fmt 共用):1=S16_LE 2=S24_LE 3=S32_LE 4=FLOAT_LE。
|
||||
* v1 实装 S16/S32(S16 直通 + S32 升位);S24 按 32-in-32 处理;FLOAT v1 拒绝。 */
|
||||
enum {
|
||||
AUDIO_FMT_S16 = 1,
|
||||
AUDIO_FMT_S24 = 2,
|
||||
AUDIO_FMT_S32 = 3,
|
||||
AUDIO_FMT_FLOAT = 4
|
||||
};
|
||||
|
||||
/* MSG_AUDIO_OPEN ↑:请求开流(App 原生声源参数)。grant_*(ACK)回 audiod 实际授权给客户端的
|
||||
* 产出格式(率/声道/位深)——客户端必须按 grant 格式产出 PCM(SDK meow_ui_audio 负责归一:
|
||||
* mono→stereo 复制 / S16↔S32 定值升降位)。ch>2 或 FLOAT → ERR_INVAL。 */
|
||||
typedef struct m_audio_open {
|
||||
char app_id[MEOW_APP_ID_MAX]; /* 32 */
|
||||
uint32_t rate; /* 原生采样率(应用源,如 44100/48000) */
|
||||
uint16_t ch; /* 原生声道数(1=mono 2=stereo) */
|
||||
uint16_t fmt; /* 原生格式(AUDIO_FMT_*) */
|
||||
uint32_t flags; /* 预留(0) */
|
||||
} m_audio_open_t; /* 32+4+2+2+4 = 44 B */
|
||||
|
||||
/* MSG_AUDIO_OPEN_ACK ↓:授权结果。err=MEOW_OK 才有效(stream_id>0 且 grant_* 为实际授权值);
|
||||
* err<0 时 stream_id=0、grant_* 视为无效(客户端 open 返回负错误码)。 */
|
||||
typedef struct m_audio_open_ack {
|
||||
uint32_t stream_id; /* 授权流 id(>0) */
|
||||
uint32_t grant_rate; /* 客户端应产出的采样率(=客户端 rate,无 SRC) */
|
||||
uint16_t grant_ch; /* 客户端应产出的声道数(DAC 双声道 → 通常 2) */
|
||||
uint16_t grant_fmt; /* 客户端应产出的格式(AUDIO_FMT_*,=硬件最优) */
|
||||
int32_t err; /* MEOW_OK / MEOW_ERR_INVAL / MEOW_ERR_NODEV / MEOW_ERR_BUSY 等 */
|
||||
} m_audio_open_ack_t; /* 4+4+2+2+4 = 16 B */
|
||||
|
||||
/* MSG_AUDIO_PAUSE/RESUME/STOP ↑:流控制(按 stream_id 定位)。 */
|
||||
typedef struct m_audio_stream {
|
||||
uint32_t stream_id;
|
||||
} m_audio_stream_t; /* 4 B */
|
||||
|
||||
/* MSG_AUDIO_PREEMPTED ↓:被抢占通知(后开流赢;旧流收此消息,App 应暂停 UI/提示)。
|
||||
* 旧流仍可读但 PCM 被丢弃(draining),直到客户端 CLOSE/断开。 */
|
||||
typedef struct m_audio_preempted {
|
||||
uint32_t stream_id; /* 被抢占的流 id */
|
||||
char by_app[MEOW_APP_ID_MAX]; /* 32:抢占者 app_id */
|
||||
} m_audio_preempted_t; /* 4+32 = 36 B */
|
||||
|
||||
/* MSG_AUDIO_ROUTE ↑:手动切换输出路由(调试/面板用)。port:0=auto(跟随插孔) 2=3.5 3=4.4。 */
|
||||
typedef struct m_audio_route {
|
||||
uint32_t port; /* 0=auto 2=3.5 3=4.4 */
|
||||
} m_audio_route_t; /* 4 B */
|
||||
|
||||
/* MSG_AUDIO_VOLUME ↑:音量查询/设置。pct<0(-1)=查询当前音量;0-100=设置(写 DAC numid=1/2
|
||||
* + 持久化 settings.conf `audio.volume`,与 watchdog/launcher 同源同键)。 */
|
||||
typedef struct m_audio_volume {
|
||||
int32_t pct; /* -1=查询;0-100=设置 */
|
||||
} m_audio_volume_t; /* 4 B */
|
||||
|
||||
#endif /* MEOW_IPC_H */
|
||||
Binary file not shown.
Reference in new issue
Block a user