Files
MeowOS-For-R3P2/patch_v2/ncm_app/app/play/meta_gate.c
T
AskaEth 7f4e18b0ed fix(ncm): META 改「变化+低频心跳」,不再每 100ms 刷 launcher(M10)
根因:ipc_media 主循环 `if (now - last_meta >= 1000)` 同样依赖 meow_ui_time_ms()
的坏 64 位值(REPORT §42)→ 条件恒真 → 每个 IPC 轮次都发 MSG_META。
launcher 日志 meow_20261105_122541.log:单次启动 21016 条
`ipc: META app=dev.player.ncm state=0 pos=0/0 -> ACK`,间隔 ~100ms,且全是
无变化的静止帧;launcher 每帧写 2 行日志+归并会话,SD 写放大到整机卡死。

修复:
- 新增 app/play/meta_gate.{h,c}(纯逻辑):状态/时长/标题/歌手/专辑/封面/歌词
  标志变化 → 立即报;播放中位置偏移 ≥5s 重锚(launcher 自己按 last_active 外推);
  心跳播放中 5s / 非播放 30s;硬下限 250ms(任何路径 ≤4 帧/秒);时钟回退不下溢;
  字符串按发送侧截断长度比较(超长标题不得恒判「变了」)。
- ipc_media.send_meta 改为「组快照 → 闸判定 → 才发」,删除 1s 定时器;
  时间改 ncm_monotonic_ms();首帧仍必发(注册媒体源);发送走 DEBUG 日志。
2026-11-05 13:00:28 +08:00

75 lines
2.7 KiB
C

/* play/meta_gate.c — 见 meta_gate.h 头注释(M10 媒体会话 META 上报闸)。 */
#include "meta_gate.h"
#include <string.h>
static void gate_cp(char *dst, size_t cap, const char *src)
{
size_t i = 0;
if (!dst || cap == 0) return;
if (src) {
for (; src[i] && i + 1 < cap; i++) dst[i] = src[i];
}
dst[i] = 0;
}
void ncm_meta_gate_init(ncm_meta_gate *g)
{
if (g) memset(g, 0, sizeof *g);
}
static void gate_record(ncm_meta_gate *g, const ncm_meta_snap *s, int64_t now_ms)
{
g->inited = 1;
g->state = s->state;
g->dur_ms = s->dur_ms;
g->flags = s->flags;
g->last_pos_ms = s->pos_ms;
g->last_send_ms = now_ms;
gate_cp(g->title, sizeof g->title, s->title);
gate_cp(g->artist, sizeof g->artist, s->artist);
gate_cp(g->album, sizeof g->album, s->album);
gate_cp(g->artwork, sizeof g->artwork, s->artwork);
}
/* 只比较「会被发送的那部分」:发送侧同样按 cap 截断,超长串不得因截断而恒判「变了」。 */
static int str_diff(const char *stored, size_t cap, const char *now)
{
size_t i = 0;
if (!now) now = "";
for (; i + 1 < cap && stored[i] && stored[i] == now[i]; i++) { }
if (i + 1 >= cap) return 0; /* 前 cap-1 字符一致且已到截断长度 → 相同 */
return stored[i] != now[i];
}
int ncm_meta_gate_should_send(ncm_meta_gate *g, const ncm_meta_snap *s, int64_t now_ms)
{
if (!g || !s) return 0;
if (!g->inited) { gate_record(g, s, now_ms); return 1; } /* 首帧:注册媒体源 */
int64_t gap = now_ms - g->last_send_ms;
if (gap < 0) { /* 时钟回退/异常:重定基准,差值按 0 处理(防下溢成「恒该发」) */
g->last_send_ms = now_ms;
gap = 0;
}
int changed = (s->state != g->state) ||
(s->dur_ms != g->dur_ms) ||
(s->flags != g->flags) ||
str_diff(g->title, sizeof g->title, s->title) ||
str_diff(g->artist, sizeof g->artist, s->artist) ||
str_diff(g->album, sizeof g->album, s->album) ||
str_diff(g->artwork, sizeof g->artwork, s->artwork);
int64_t dpos = (int64_t)s->pos_ms - (int64_t)g->last_pos_ms;
if (dpos < 0) dpos = -dpos; /* seek 前后跳都算偏移 */
int playing = (s->state == NCM_META_ST_PLAYING || s->state == NCM_META_ST_BUFFER);
int64_t hb = playing ? NCM_META_HB_PLAY_MS : NCM_META_HB_IDLE_MS;
if (!changed && dpos < NCM_META_POS_RESEND_MS && gap < hb) return 0;
if (gap < NCM_META_MIN_GAP_MS) return 0; /* 硬下限:变化挂起,下一轮再发(不快于 4 帧/秒) */
gate_record(g, s, now_ms);
return 1;
}