ncm A2: 音频输出迁移 meow_audiod(SINK_AUDIOD 默认后端)— 修无声根因
- audio_out.c: 新增 SINK_AUDIOD 默认(SDK meow_audio_* 连 audiod);NCM_AUDIO_SINK=file/null/alsa 与 MEOW_AUDIO_DIRECT=1 保留调试后端;ALSA 保底修两大坑(hw_params 全放行初始化 + mask 清零 再单点)——旧 memset0 interval=「只能取0」→ HW_PARAMS 恒 EINVAL 即播放无声根因 - 新增 audio_out_pause:PAUSED 沿向 audiod 发 pause(停时钟不丢流);resume 流死自动重开 - player_manager: 注册 meow_audio_on_preempt → g_play 命令通道暂停;播放事件全量 meow_log (open 参数/grant_*/write 错误节流/切歌/暂停/seek/done) - appstate/app: /tmp/ncm_autoplay 真机联调 hook(仅播已缓存曲目,绝不发 song_url) - bench/audiod_chain_sim.c: 真实 audiod_host 假 socket 全链离线回归 14 项全 PASS - 验证: host 0 warning / WAV 回归 / qemu core PASS / mipsel 0 warning;真机 OPEN→grant 已通, 持续写帧被 M2.90 设备 PCM 播放内核硬挂死阻断(REPORT §16.3,4/4 复现,留主会话) - ncm md5 db5b78ad9e8f40e6306484efe2a08eb3(已热更设备)
This commit is contained in:
1 parent
9bbc3a1467
commit
e0136213fe
10 files changed
+598
-41
No files matched your search
@@ -3,6 +3,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define NCM_DEFAULT_DATA "/usr/data/mnt/sd_0/MeowData/dev.player.ncm/data"
|
||||
|
||||
@@ -205,3 +206,89 @@ int appstate_current_playing(void)
|
||||
if (g_st.playing_song < 0 || g_st.playing_song >= g_st.song_count) return -1;
|
||||
return g_st.playing_song;
|
||||
}
|
||||
|
||||
/* ---- 真机联调 autoplay hook(A2 音频迁移验收用,非正式能力)----
|
||||
* 触发文件 /tmp/ncm_autoplay 存在且 home 歌单已载 → 后台线程找「已缓存」曲目并播放:
|
||||
* - 内容为纯数字 → 从该歌单下标起扫最多 AUTOPLAY_SCAN_PL 个歌单首页;
|
||||
* - 内容为其它文本 → 按歌单名子串匹配**单个**歌单(如 "Docu";避开超大歌单的
|
||||
* 全量 trackIds 解析,真机联调省时省内存);
|
||||
* - 空文件 → 从 0 起扫。
|
||||
* 风控纪律:**绝不发 song_url 下载**——无缓存命中只记日志退出;metadata 请求 = 每歌单
|
||||
* 1 detail + 1 song_detail(≤ 2×AUTOPLAY_SCAN_PL 次)。 */
|
||||
#define AUTOPLAY_TRIGGER "/tmp/ncm_autoplay"
|
||||
#define AUTOPLAY_SCAN_PL 3
|
||||
|
||||
/* 播放单个歌单首页中第一首已缓存曲目。命中播放返回 1,否则 0。 */
|
||||
static int autoplay_try_playlist(int pl)
|
||||
{
|
||||
int rc = appstate_load_playlist_songs_page(pl, 0, NCM_SONG_BATCH);
|
||||
if (rc != NCM_OK) {
|
||||
meow_log(MEOW_LOG_WARN, "autoplay: playlist[%d] load rc=%d", pl, rc);
|
||||
return 0;
|
||||
}
|
||||
char cpath[600];
|
||||
for (int i = 0; i < g_st.song_count; i++) {
|
||||
if (ncm_cache_lookup(&g_st.ctx.cache, g_st.songs[i].id, ".mp3",
|
||||
cpath, sizeof cpath) == NCM_OK) {
|
||||
g_st.active_playlist = pl;
|
||||
meow_log(MEOW_LOG_INFO, "autoplay: playlist[%d] song[%d] id=%s cached -> play",
|
||||
pl, i, g_st.songs[i].id);
|
||||
player_manager_play(i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
meow_log(MEOW_LOG_INFO, "autoplay: playlist[%d] first page %d songs, no cached track",
|
||||
pl, g_st.song_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *autoplay_worker(void *arg)
|
||||
{
|
||||
const char *sel = (const char *)arg; /* NULL=从 0 起扫;数字=起始下标;其它=歌单名子串 */
|
||||
if (sel && sel[0] && !(sel[0] >= '0' && sel[0] <= '9')) {
|
||||
for (int pl = 0; pl < g_st.playlist_count && !g_app_quit; pl++) {
|
||||
if (strstr(g_st.playlists[pl].name, sel)) {
|
||||
meow_log(MEOW_LOG_INFO, "autoplay: name '%s' -> playlist[%d] '%s' (%d tracks)",
|
||||
sel, pl, g_st.playlists[pl].name, g_st.playlists[pl].track_count);
|
||||
if (autoplay_try_playlist(pl)) { free((void *)sel); return NULL; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
meow_log(MEOW_LOG_WARN, "autoplay: no playlist name match / no cached track ('%s')", sel);
|
||||
free((void *)sel);
|
||||
return NULL;
|
||||
}
|
||||
int start = (sel && sel[0]) ? atoi(sel) : 0;
|
||||
free((void *)sel);
|
||||
if (start < 0) start = 0;
|
||||
int end = start + AUTOPLAY_SCAN_PL;
|
||||
if (end > g_st.playlist_count) end = g_st.playlist_count;
|
||||
for (int pl = start; pl < end && !g_app_quit; pl++)
|
||||
if (autoplay_try_playlist(pl)) return NULL;
|
||||
meow_log(MEOW_LOG_WARN, "autoplay: no cached track found (no download, risk control)");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void autoplay_maybe(void)
|
||||
{
|
||||
static int s_fired = 0;
|
||||
if (s_fired || g_app_quit) return;
|
||||
if (access(AUTOPLAY_TRIGGER, F_OK) != 0) return;
|
||||
if (!g_st.logged_in || g_st.playlist_count <= 0) return; /* 等 home 歌单载完 */
|
||||
s_fired = 1;
|
||||
char buf[64] = "";
|
||||
FILE *f = fopen(AUTOPLAY_TRIGGER, "r"); /* 一次性:读完即删 */
|
||||
if (f) {
|
||||
if (fgets(buf, sizeof buf, f)) {
|
||||
size_t n = strlen(buf);
|
||||
while (n && (buf[n - 1] == '\n' || buf[n - 1] == '\r' || buf[n - 1] == ' ')) buf[--n] = 0;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
unlink(AUTOPLAY_TRIGGER);
|
||||
meow_log(MEOW_LOG_INFO, "autoplay: triggered, sel='%s'", buf);
|
||||
char *sel = strdup(buf);
|
||||
pthread_t t;
|
||||
if (pthread_create(&t, NULL, autoplay_worker, sel) == 0) pthread_detach(t);
|
||||
else free(sel);
|
||||
}
|
||||
Reference in new issue
Block a user