Files
MeowOS-For-R3P2/patch_v2/meow_launcherd/test_media.c
T

170 lines
6.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* test_media.c — 宿主单测:meow_media 媒体会话(阶段D附录B)。
*
* 验证:
* 1) META 上报 → 注册会话,current()=最近上报者;
* 2) 最近活跃切换(两个源,后上报者胜);
* 3) has_source()(state=0 停止 → 0);
* 4) PLAYCTL 下发字节格式(socketpair 对端可读回 MSG_PLAYCTL 帧,cmd/seek 正确);
* 5) meow_media_playctl 无源 → -1;
* 6) clear(app) 清会话 → current()=NULL。
* 只依赖 meow_media.c + meow_ipc.h(纯 C),宿主 gcc 直编。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/socket.h>
#include "meow_media.h"
#include "meow_ipc.h"
static int g_fails = 0;
#define CHECK(cond, msg) do { \
if (cond) printf("PASS: %s\n", msg); \
else { printf("FAIL: %s\n", msg); g_fails++; } } while (0)
/* ops.send:把帧写到 fd(socketpair 一端)。 */
static size_t test_send(int fd, uint16_t type, uint32_t req_id,
const void *payload, uint32_t len)
{
uint8_t hdr[MEOW_IPC_HDR_LEN];
uint32_t magic = MEOW_IPC_MAGIC;
uint16_t ver = MEOW_IPC_VERSION;
memcpy(hdr + 0, &magic, 4);
memcpy(hdr + 4, &ver, 2);
memcpy(hdr + 6, &type, 2);
memcpy(hdr + 8, &req_id, 4);
memcpy(hdr + 12, &len, 4);
size_t off = 0;
while (off < sizeof hdr) {
ssize_t w = write(fd, hdr + off, sizeof hdr - off);
if (w <= 0) return off;
off += (size_t)w;
}
if (len && payload) {
size_t p = 0;
while (p < len) {
ssize_t w = write(fd, (const uint8_t *)payload + p, len - p);
if (w <= 0) break;
p += (size_t)w;
}
off += p;
}
return off;
}
static void fill_meta(m_meta_t *m, const char *app, uint32_t state, uint32_t pos, uint32_t dur,
const char *title, const char *artist)
{
memset(m, 0, sizeof *m);
snprintf(m->app_id, sizeof m->app_id, "%s", app);
m->state = state; m->pos_ms = pos; m->dur_ms = dur;
snprintf(m->title, sizeof m->title, "%s", title);
snprintf(m->artist, sizeof m->artist, "%s", artist);
}
/* 从 fd 读一帧(头+负载),校验 magic/ver,返回负载类型;不足返回 -1。 */
static int read_frame(int fd, uint16_t *type, uint32_t *req_id, uint8_t *rbuf, uint32_t rcap)
{
uint8_t rhdr[MEOW_IPC_HDR_LEN];
size_t off = 0;
while (off < sizeof rhdr) {
ssize_t r = read(fd, rhdr + off, sizeof rhdr - off);
if (r <= 0) return -1;
off += (size_t)r;
}
uint32_t magic, len; uint16_t ver;
memcpy(&magic, rhdr, 4); memcpy(&ver, rhdr + 4, 2); memcpy(type, rhdr + 6, 2);
memcpy(req_id, rhdr + 8, 4); memcpy(&len, rhdr + 12, 4);
if (magic != MEOW_IPC_MAGIC || ver != MEOW_IPC_VERSION) return -1;
if (len > rcap) len = rcap;
off = 0;
while (off < len) {
ssize_t r = read(fd, rbuf + off, len - off);
if (r <= 0) return -1;
off += (size_t)r;
}
return (int)len;
}
int main(void)
{
meow_media_ops ops;
ops.send = test_send;
ops.log = NULL; /* 静默 */
meow_media_init(&ops);
int sv[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0) { perror("socketpair"); return 1; }
/* sv[0]=会话 fd(launcher 下发端);sv[1]=测试读回端(模拟 App)。 */
/* 1) 单源注册 */
m_meta_t m;
fill_meta(&m, "com.ncm", MEOW_MEDIA_PLAYING, 120000, 240000, "Song A", "Artist A");
CHECK(meow_media_meta(&m, sv[0]) == 0, "meta registers source");
const meow_media_session_t *cur = meow_media_current();
CHECK(cur && !strcmp(cur->app_id, "com.ncm"), "current() == com.ncm");
CHECK(cur && cur->state == MEOW_MEDIA_PLAYING, "state == PLAYING");
CHECK(meow_media_has_source() == 1, "has_source == 1 (playing)");
/* 2) 多源最近活跃切换 */
fill_meta(&m, "com.player2", MEOW_MEDIA_PLAYING, 0, 180000, "Song B", "Artist B");
CHECK(meow_media_meta(&m, sv[0]) == 0, "meta registers second source");
cur = meow_media_current();
CHECK(cur && !strcmp(cur->app_id, "com.player2"), "current() == com.player2 (newest)");
fill_meta(&m, "com.ncm", MEOW_MEDIA_PLAYING, 30000, 240000, "Song A", "Artist A");
meow_media_meta(&m, sv[0]);
cur = meow_media_current();
CHECK(cur && !strcmp(cur->app_id, "com.ncm"), "current() == com.ncm after re-report (newest)");
/* 3) state=0 停止 → has_source=0(但会话仍在,current() 仍指向它) */
fill_meta(&m, "com.ncm", MEOW_MEDIA_STOPPED, 0, 0, "Song A", "Artist A");
meow_media_meta(&m, sv[0]);
cur = meow_media_current();
CHECK(cur && !strcmp(cur->app_id, "com.ncm"), "current() still == com.ncm (stopped)");
CHECK(meow_media_has_source() == 0, "has_source == 0 (stopped)");
/* 恢复播放,准备 PLAYCTL 下发验证 */
fill_meta(&m, "com.ncm", MEOW_MEDIA_PLAYING, 1000, 240000, "Song A", "Artist A");
meow_media_meta(&m, sv[0]);
/* 4) PLAYCTL 下发:cmd=1(播放),读回端应收到 MSG_PLAYCTL/第11号 req */
CHECK(meow_media_playctl(1, 0) == 0, "playctl sends (cmd=play)");
uint8_t rbuf[512];
uint16_t type; uint32_t req;
int n = read_frame(sv[1], &type, &req, rbuf, sizeof rbuf);
CHECK(n == (int)sizeof(m_playctl_t), "downlink frame payload == m_playctl_t size");
CHECK(type == MSG_PLAYCTL, "downlink type == MSG_PLAYCTL");
m_playctl_t c;
memcpy(&c, rbuf, sizeof c);
CHECK(c.cmd == 1 && c.seek_ms == 0, "downlink cmd=1 seek=0");
/* 5) seek:cmd=5 seek=12345 */
CHECK(meow_media_playctl(5, 12345) == 0, "playctl sends (cmd=seek)");
n = read_frame(sv[1], &type, &req, rbuf, sizeof rbuf);
memcpy(&c, rbuf, sizeof c);
CHECK(type == MSG_PLAYCTL && c.cmd == 5 && c.seek_ms == 12345, "downlink seek cmd=5 seek=12345");
/* playctl_to 目标 app(另一会话) */
CHECK(meow_media_playctl_to("com.player2", 3, 0) == 0, "playctl_to player2 sends");
n = read_frame(sv[1], &type, &req, rbuf, sizeof rbuf);
memcpy(&c, rbuf, sizeof c);
CHECK(type == MSG_PLAYCTL && c.cmd == 3, "downlink to player2 cmd=3");
CHECK(meow_media_playctl_to("no.such.app", 1, 0) == -1, "playctl_to unknown app == -1");
/* 6) 无源:清全部 → playctl -1 / has_source 0 */
meow_media_clear(NULL);
CHECK(meow_media_current() == NULL, "current() == NULL after clear all");
CHECK(meow_media_playctl(1, 0) == -1, "playctl no source == -1");
CHECK(meow_media_has_source() == 0, "has_source == 0 after clear");
close(sv[0]); close(sv[1]);
/* 7) 空 app_id 拒绝 */
fill_meta(&m, "", MEOW_MEDIA_PLAYING, 0, 0, "x", "y");
CHECK(meow_media_meta(&m, sv[0]) == -1, "meta empty app_id == -1");
printf("\n%s (%d fails)\n", g_fails ? "FAILED" : "ALL PASS", g_fails);
return g_fails ? 1 : 0;
}