/* play/meta_gate.c — 见 meta_gate.h 头注释(M10 媒体会话 META 上报闸)。 */ #include "meta_gate.h" #include 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; }