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

630 lines
25 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.
/* meow_ipc.c — MeowOS IPC 测试钩子(阶段 D · M0+M1;与 evtool 同定位)。
*
* 向 meow_launcherd 的 AF_UNIX IPC(FRAMEWORK_DESIGN §1)发帧、收应答并打印。
* 静态 MIPS32r2 musl(用 zig-mipsel-cc 编译),qemu-mipsel 亦可用。
*
* 子命令:
* meow_ipc hello <app_id> [version] [flags] → MSG_HELLO,期望 MSG_ACK
* meow_ipc ping [app_id] → hello 别名(默认 meow_ipc)
* meow_ipc query <app_id> <activity> → MSG_ACT_QUERY,期望 MSG_ACT_RESULT
* meow_ipc declare <app_id> <route_id=chain> [...] → MSG_ACT_DECLARE,期望 MSG_ACK
* 全局:
* --sock <path> 覆盖 socket 路径(默认可被 MEOW_IPC_SOCK 覆盖,再回退 /usr/data/meow_ipc.sock)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include "meow_ipc.h"
static const char *g_sock = NULL;
static void print_err(const m_err_t *e)
{
fprintf(stderr, "ERR 0x%x: %.*s\n", e->code, e->msg_len < 64 ? e->msg_len : 64, e->msg);
}
static int connect_path(const char *path)
{
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) { perror("socket"); return -1; }
struct sockaddr_un a;
memset(&a, 0, sizeof a);
a.sun_family = AF_UNIX;
strncpy(a.sun_path, path, sizeof a.sun_path - 1);
if (connect(fd, (struct sockaddr *)&a, sizeof a) < 0) {
fprintf(stderr, "connect %s: %s\n", path, strerror(errno));
close(fd);
return -1;
}
return fd;
}
/* 发一帧(头+负载),读回一帧(头+负载)。返回应答类型;-1=失败。 */
static int xchg(int fd, uint16_t type, uint32_t req_id, const void *payload, uint32_t len,
uint8_t *rbuf, uint32_t rcap)
{
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) { perror("write hdr"); return -1; }
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) { perror("write payload"); return -1; }
p += (size_t)w;
}
}
/* read response header */
uint8_t rhdr[MEOW_IPC_HDR_LEN];
off = 0;
while (off < sizeof rhdr) {
ssize_t r = read(fd, rhdr + off, sizeof rhdr - off);
if (r <= 0) { perror("read hdr"); return -1; }
off += (size_t)r;
}
uint32_t rmagic, rlen;
uint16_t rver, rtype;
memcpy(&rmagic, rhdr, 4);
memcpy(&rver, rhdr + 4, 2);
memcpy(&rtype, rhdr + 6, 2);
memcpy(&rlen, rhdr + 12, 4);
if (rmagic != MEOW_IPC_MAGIC) { fprintf(stderr, "bad resp magic %08x\n", rmagic); return -1; }
if (rver != MEOW_IPC_VERSION) { fprintf(stderr, "bad resp version %u\n", rver); return -1; }
if (rlen > rcap) rlen = rcap;
off = 0;
while (off < rlen) {
ssize_t r = read(fd, rbuf + off, rlen - off);
if (r <= 0) { perror("read payload"); return -1; }
off += (size_t)r;
}
return (int)rtype;
}
static int cmd_hello(const char *app_id, uint32_t version, uint32_t flags)
{
const char *sock = g_sock;
int fd = connect_path(sock);
if (fd < 0) return 1;
m_hello_t h;
memset(&h, 0, sizeof h);
strncpy(h.app_id, app_id, MEOW_APP_ID_MAX - 1);
h.version = version;
h.flags = flags;
uint8_t rbuf[256];
int rt = xchg(fd, MSG_HELLO, 1, &h, sizeof h, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("HELLO ok: code=%d status=%u (apps registered)\n", a.code, a.status);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "HELLO: unexpected resp type 0x%04x\n", rt);
return 1;
}
static int cmd_query(const char *app_id, const char *activity)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_act_query_t q;
memset(&q, 0, sizeof q);
strncpy(q.app_id, app_id, MEOW_APP_ID_MAX - 1);
strncpy(q.activity, activity, MEOW_ACT_MAX - 1);
uint8_t rbuf[256];
int rt = xchg(fd, MSG_ACT_QUERY, 2, &q, sizeof q, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACT_RESULT) {
m_act_result_t r;
memcpy(&r, rbuf, sizeof r);
size_t cl = r.chain_len < MEOW_CHAIN_MAX ? r.chain_len : MEOW_CHAIN_MAX - 1;
char chain[MEOW_CHAIN_MAX];
memcpy(chain, r.chain, cl);
chain[cl] = 0;
printf("QUERY ok: app=%s act=%s depth=%u chain=%s\n", app_id, activity,
r.depth, cl ? chain : "(empty)");
return r.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "QUERY: unexpected resp type 0x%04x\n", rt);
return 1;
}
static int cmd_declare(const char *app_id, int nent, char **ents)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_act_declare_t d;
memset(&d, 0, sizeof d);
strncpy(d.app_id, app_id, MEOW_APP_ID_MAX - 1);
int n = 0;
char *p = d.entries;
for (int i = 0; i < nent && n < 8; i++) {
size_t l = strlen(ents[i]);
if (l + 1 > (size_t)(d.entries + sizeof d.entries - p)) break;
memcpy(p, ents[i], l + 1);
p += l + 1;
n++;
}
d.count = (uint16_t)n;
uint32_t len = (uint32_t)(sizeof d.app_id + 2 + 2 + (p - d.entries));
uint8_t rbuf[256];
int rt = xchg(fd, MSG_ACT_DECLARE, 3, &d, len, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("DECLARE ok: app=%s n=%d code=%d\n", app_id, n, a.code);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "DECLARE: unexpected resp type 0x%04x\n", rt);
return 1;
}
static int cmd_focus(const char *app_id, const char *activity)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_act_focus_t f;
memset(&f, 0, sizeof f);
strncpy(f.app_id, app_id, MEOW_APP_ID_MAX - 1);
strncpy(f.activity, activity, MEOW_ACT_MAX - 1);
uint8_t rbuf[256];
int rt = xchg(fd, MSG_ACT_FOCUS, 4, &f, sizeof f, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("FOCUS ok: app=%s act=%s code=%d\n", app_id, activity, a.code);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "FOCUS: unexpected resp type 0x%04x\n", rt);
return 1;
}
static int cmd_back(void)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
uint8_t rbuf[256];
int rt = xchg(fd, MSG_ACT_BACK, 5, NULL, 0, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("BACK ok: code=%d\n", a.code);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "BACK: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* M3:上报导航 → MSG_NAV,期望 MSG_ACK。
* nav report <app_id> <depth> <top> 上报栈深/顶层(MEOW_NAV_REPORT)
* nav exit <app_id> 请求退出(MEOW_NAV_EXIT) */
static int cmd_nav(const char *app_id, int exit_req, uint32_t depth, const char *top)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_nav_t n;
memset(&n, 0, sizeof n);
strncpy(n.app_id, app_id, MEOW_APP_ID_MAX - 1);
n.nav_type = exit_req ? MEOW_NAV_EXIT : MEOW_NAV_REPORT;
n.depth = depth;
if (top) strncpy(n.current, top, MEOW_ACT_MAX - 1);
uint8_t rbuf[256];
int rt = xchg(fd, MSG_NAV, 10, &n, sizeof n, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("NAV ok: app=%s type=%u depth=%u top=\"%s\" code=%d\n",
app_id, n.nav_type, depth, n.current, a.code);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "NAV: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* M2a:推送通知 → MSG_NOTIFY,期望 MSG_NOTIFY_ACK。 */
static int cmd_notify(const char *app_id, const char *category, const char *summary,
const char *body, uint32_t replaces_id, int ongoing, int media, int progress,
const char *target_activity)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_notify_t n;
memset(&n, 0, sizeof n);
strncpy(n.app_id, app_id, MEOW_APP_ID_MAX - 1);
strncpy(n.category, category, sizeof n.category - 1);
strncpy(n.summary, summary, sizeof n.summary - 1);
if (body) strncpy(n.body, body, sizeof n.body - 1);
if (target_activity) strncpy(n.target_activity, target_activity, MEOW_ACT_MAX - 1);
n.replaces_id = replaces_id;
n.ongoing = ongoing ? 1 : 0;
n.media = media ? 1 : 0;
n.progress = progress;
n.expire_timeout = ongoing ? 0xFFFFFFFFu : 0; /* ONGOING 常驻 */
uint8_t rbuf[256];
int rt = xchg(fd, MSG_NOTIFY, 6, &n, sizeof n, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_NOTIFY_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("NOTIFY ok: id=%u code=%d\n", a.status, a.code);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "NOTIFY: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* M2a:撤下通知 → MSG_NOTIFY_DISMISS,期望 MSG_ACK。 */
static int cmd_dismiss(uint32_t id)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
uint8_t rbuf[256];
int rt = xchg(fd, MSG_NOTIFY_DISMISS, 7, &id, sizeof id, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("DISMISS ok: id=%u code=%d\n", id, a.code);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "DISMISS: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* 查询当前内存活跃通知集 → MSG_NOTIFY_QUERY,期望 MSG_NOTIFY_QUERY_RESULT(打印 JSON 文本)。
* 可选 <app_id> 过滤(缺省=全部)。 */
static int cmd_querynotif(const char *app_id)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
uint8_t rbuf[MEOW_IPC_MAX];
int rt = xchg(fd, MSG_NOTIFY_QUERY, 8, app_id, app_id ? (uint32_t)strlen(app_id) : 0,
rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_NOTIFY_QUERY_RESULT) {
m_notify_query_result_t r;
memcpy(&r, rbuf, sizeof r);
uint32_t tl = r.text_len < sizeof r.text ? r.text_len : sizeof r.text - 1;
printf("QUERY ok: code=%d len=%u\n%s\n", r.code, (unsigned)tl, r.text);
return r.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "QUERY: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* 一键清除(保留 ongoing/media/progress)→ MSG_NOTIFY_DISMISS_ALL,期望 MSG_ACK(status=清除数)。 */
static int cmd_dismissall(void)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
uint8_t rbuf[256];
int rt = xchg(fd, MSG_NOTIFY_DISMISS_ALL, 9, NULL, 0, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("DISMISS_ALL ok: code=%d cleared=%u\n", a.code, a.status);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "DISMISS_ALL: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* 阶段 D 附录 B:媒体会话上报 → MSG_META,期望 MSG_ACK。
* meta <app_id> <state> <pos_ms> <dur_ms> <title> <artist> <album> [artwork] */
static int cmd_meta(const char *app_id, uint32_t state, uint32_t pos, uint32_t dur,
const char *title, const char *artist, const char *album, const char *artwork)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_meta_t mm;
memset(&mm, 0, sizeof mm);
strncpy(mm.app_id, app_id, MEOW_APP_ID_MAX - 1);
mm.state = state; mm.pos_ms = pos; mm.dur_ms = dur;
snprintf(mm.title, sizeof mm.title, "%s", title);
snprintf(mm.artist, sizeof mm.artist, "%s", artist);
snprintf(mm.album, sizeof mm.album, "%s", album);
if (artwork) snprintf(mm.artwork, sizeof mm.artwork, "%s", artwork);
uint8_t rbuf[256];
int rt = xchg(fd, MSG_META, 11, &mm, sizeof mm, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("META ok: app=%s state=%u code=%d\n", app_id, state, a.code);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "META: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* 控制转发 → MSG_PLAYCTL(launcher 转发到最近活跃媒体会话),期望 MSG_ACK。
* playctl <cmd> [seek_ms] (cmd 1=播放 2=暂停 3=上一首 4=下一首 5=seek) */
static int cmd_playctl(uint32_t cmd, int64_t seek_ms)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_playctl_t c;
memset(&c, 0, sizeof c);
c.cmd = cmd; c.seek_ms = seek_ms;
uint8_t rbuf[256];
int rt = xchg(fd, MSG_PLAYCTL, 12, &c, sizeof c, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("PLAYCTL ok: cmd=%u seek=%lld code=%d (status=%d)\n", cmd,
(long long)seek_ms, a.code, (int)a.status);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "PLAYCTL: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* 读一帧(头+负载)→ 返回负载长;-1=连接断/坏帧。type/req_id 输出。 */
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;
}
/* §10.5:App 前台顶部下滑 → 请求展开通知中心叠加会话 → MSG_NOTIF_OPEN,期望 MSG_ACK。
* notifopen <app_id> [origin_y] [hotzone] */
static int cmd_notifopen(const char *app_id, uint16_t origin_y, uint16_t hotzone)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_notif_open_t o;
memset(&o, 0, sizeof o);
strncpy(o.app_id, app_id, MEOW_APP_ID_MAX - 1);
o.event_seq = 1;
o.origin_x = 0;
o.origin_y = origin_y;
o.hotzone = hotzone;
uint8_t rbuf[256];
int rt = xchg(fd, MSG_NOTIF_OPEN, 20, &o, sizeof o, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("NOTIF_OPEN ok: app=%s oy=%u hz=%u code=%d status=%u\n",
app_id, origin_y, hotzone, a.code, a.status);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "NOTIF_OPEN: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* §10.5:App 告知结束/退出 → MSG_NOTIF_CLOSE(launcher 收尾兜底),期望 MSG_ACK。
* notifclose <app_id> <reason> */
static int cmd_notifclose(const char *app_id, uint32_t reason)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_notif_close_t o;
memset(&o, 0, sizeof o);
strncpy(o.app_id, app_id, MEOW_APP_ID_MAX - 1);
o.reason = reason;
uint8_t rbuf[256];
int rt = xchg(fd, MSG_NOTIF_CLOSE, 21, &o, sizeof o, rbuf, sizeof rbuf);
close(fd);
if (rt == MSG_ACK) {
m_ack_t a;
memcpy(&a, rbuf, sizeof a);
printf("NOTIF_CLOSE ok: app=%s reason=%u code=%d\n", app_id, reason, a.code);
return a.code == MEOW_OK ? 0 : 1;
}
if (rt == MSG_ERR) { print_err((const m_err_t *)rbuf); return 1; }
fprintf(stderr, "NOTIF_CLOSE: unexpected resp type 0x%04x\n", rt);
return 1;
}
/* 媒体源监听:HELLO(MF_PLAYBACK) + META → 保持连接等待 launcher 下发 MSG_PLAYCTL。
* listen <app_id> <state> <pos_ms> <dur_ms> <title> <artist> <album> [artwork] */
static int cmd_listen(const char *app_id, uint32_t state, uint32_t pos, uint32_t dur,
const char *title, const char *artist, const char *album,
const char *artwork)
{
int fd = connect_path(g_sock);
if (fd < 0) return 1;
m_hello_t h;
memset(&h, 0, sizeof h);
strncpy(h.app_id, app_id, MEOW_APP_ID_MAX - 1);
h.version = 1; h.flags = MF_PLAYBACK;
uint8_t rbuf[256];
int rt = xchg(fd, MSG_HELLO, 1, &h, sizeof h, rbuf, sizeof rbuf);
if (rt != MSG_ACK) { fprintf(stderr, "listen: HELLO resp 0x%04x\n", rt); close(fd); return 1; }
m_meta_t mm;
memset(&mm, 0, sizeof mm);
strncpy(mm.app_id, app_id, MEOW_APP_ID_MAX - 1);
mm.state = state; mm.pos_ms = pos; mm.dur_ms = dur;
snprintf(mm.title, sizeof mm.title, "%s", title);
snprintf(mm.artist, sizeof mm.artist, "%s", artist);
snprintf(mm.album, sizeof mm.album, "%s", album);
if (artwork) snprintf(mm.artwork, sizeof mm.artwork, "%s", artwork);
rt = xchg(fd, MSG_META, 2, &mm, sizeof mm, rbuf, sizeof rbuf);
if (rt != MSG_ACK) { fprintf(stderr, "listen: META resp 0x%04x\n", rt); close(fd); return 1; }
printf("listen: source=%s registered (state=%u) — awaiting PLAYCTL...\n", app_id, state);
fflush(stdout);
/* 阻塞读:等待 launcher 下发 MSG_PLAYCTL(同一连接)。 */
for (;;) {
uint16_t type; uint32_t req_id;
int n = read_frame(fd, &type, &req_id, rbuf, sizeof rbuf);
if (n < 0) { fprintf(stderr, "listen: conn closed\n"); close(fd); return 0; }
if (type == MSG_PLAYCTL && n >= (int)sizeof(m_playctl_t)) {
m_playctl_t c;
memcpy(&c, rbuf, sizeof c);
printf("RECV PLAYCTL: cmd=%u seek=%lld\n", c.cmd, (long long)c.seek_ms);
fflush(stdout);
} else {
printf("RECV frame type=0x%04x len=%d\n", type, n);
}
}
}
int main(int argc, char **argv)
{
const char *env = getenv("MEOW_IPC_SOCK");
g_sock = (env && env[0]) ? env : MEOW_IPC_PATH;
/* parse leading global options */
int i = 1;
for (; i < argc; i++) {
if (!strcmp(argv[i], "--sock") && i + 1 < argc) { g_sock = argv[++i]; }
else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
fprintf(stderr, "usage: meow_ipc [--sock <path>] hello|ping|query|declare ...\n"); return 0;
}
else break;
}
if (i >= argc) { fprintf(stderr, "bad args; try --help\n"); return 1; }
const char *cmd = argv[i];
if (!strcmp(cmd, "hello")) {
if (i + 1 >= argc) { fprintf(stderr, "hello needs <app_id>\n"); return 1; }
uint32_t ver = (i + 2 < argc) ? (uint32_t)strtoul(argv[i + 2], NULL, 0) : 1;
uint32_t flg = (i + 3 < argc) ? (uint32_t)strtoul(argv[i + 3], NULL, 0) : 0;
return cmd_hello(argv[i + 1], ver, flg);
}
if (!strcmp(cmd, "ping")) {
const char *app = (i + 1 < argc) ? argv[i + 1] : "meow_ipc";
return cmd_hello(app, 1, 0);
}
if (!strcmp(cmd, "query")) {
if (i + 2 >= argc) { fprintf(stderr, "query needs <app_id> <activity>\n"); return 1; }
return cmd_query(argv[i + 1], argv[i + 2]);
}
if (!strcmp(cmd, "declare")) {
if (i + 2 >= argc) { fprintf(stderr, "declare needs <app_id> <route_id=chain> [...]\n"); return 1; }
return cmd_declare(argv[i + 1], argc - i - 2, argv + i + 2);
}
if (!strcmp(cmd, "focus")) {
if (i + 2 >= argc) { fprintf(stderr, "focus needs <app_id> <activity>\n"); return 1; }
return cmd_focus(argv[i + 1], argv[i + 2]);
}
if (!strcmp(cmd, "back")) {
return cmd_back();
}
if (!strcmp(cmd, "notify")) {
/* notify <app_id> <category> <summary> [body] [replaces_id] [ongoing] [media] [progress] [target_activity] */
if (i + 2 >= argc) { fprintf(stderr, "notify needs <app_id> <category> <summary>\n"); return 1; }
const char *body = (i + 4 < argc) ? argv[i + 4] : "";
uint32_t rid = (i + 5 < argc) ? (uint32_t)strtoul(argv[i + 5], NULL, 0) : 0;
int ongoing = (i + 6 < argc) ? atoi(argv[i + 6]) : 0;
int media = (i + 7 < argc) ? atoi(argv[i + 7]) : 0;
int progress = (i + 8 < argc) ? atoi(argv[i + 8]) : -1;
const char *tgt = (i + 9 < argc) ? argv[i + 9] : "";
return cmd_notify(argv[i + 1], argv[i + 2], argv[i + 3], body, rid, ongoing, media, progress,
tgt);
}
if (!strcmp(cmd, "dismiss")) {
if (i + 1 >= argc) { fprintf(stderr, "dismiss needs <id>\n"); return 1; }
return cmd_dismiss((uint32_t)strtoul(argv[i + 1], NULL, 0));
}
if (!strcmp(cmd, "querynotif")) {
const char *app = (i + 1 < argc) ? argv[i + 1] : NULL;
return cmd_querynotif(app);
}
if (!strcmp(cmd, "dismissall")) {
return cmd_dismissall();
}
if (!strcmp(cmd, "meta")) {
/* meta <app_id> <state> <pos_ms> <dur_ms> <title> <artist> <album> [artwork] */
if (i + 7 >= argc) { fprintf(stderr, "meta needs <app_id> <state> <pos_ms> <dur_ms> <title> <artist> <album>\n"); return 1; }
uint32_t st = (uint32_t)strtoul(argv[i + 2], NULL, 0);
uint32_t pos = (uint32_t)strtoul(argv[i + 3], NULL, 0);
uint32_t dur = (uint32_t)strtoul(argv[i + 4], NULL, 0);
const char *aw = (i + 8 < argc) ? argv[i + 8] : NULL;
return cmd_meta(argv[i + 1], st, pos, dur, argv[i + 5], argv[i + 6], argv[i + 7], aw);
}
if (!strcmp(cmd, "listen")) {
/* listen <app_id> <state> <pos_ms> <dur_ms> <title> <artist> <album> [artwork] */
if (i + 7 >= argc) { fprintf(stderr, "listen needs <app_id> <state> <pos_ms> <dur_ms> <title> <artist> <album>\n"); return 1; }
uint32_t st = (uint32_t)strtoul(argv[i + 2], NULL, 0);
uint32_t pos = (uint32_t)strtoul(argv[i + 3], NULL, 0);
uint32_t dur = (uint32_t)strtoul(argv[i + 4], NULL, 0);
const char *aw = (i + 8 < argc) ? argv[i + 8] : NULL;
return cmd_listen(argv[i + 1], st, pos, dur, argv[i + 5], argv[i + 6], argv[i + 7], aw);
}
if (!strcmp(cmd, "playctl")) {
if (i + 1 >= argc) { fprintf(stderr, "playctl needs <cmd> [seek_ms]\n"); return 1; }
uint32_t cmd2 = (uint32_t)strtoul(argv[i + 1], NULL, 0);
int64_t seek = (i + 2 < argc) ? (int64_t)strtoll(argv[i + 2], NULL, 0) : 0;
return cmd_playctl(cmd2, seek);
}
if (!strcmp(cmd, "notifopen")) {
/* notifopen <app_id> [origin_y] [hotzone] */
if (i + 1 >= argc) { fprintf(stderr, "notifopen needs <app_id>\n"); return 1; }
uint16_t oy = (i + 2 < argc) ? (uint16_t)strtoul(argv[i + 2], NULL, 0) : 0;
uint16_t hz = (i + 3 < argc) ? (uint16_t)strtoul(argv[i + 3], NULL, 0) : 28;
return cmd_notifopen(argv[i + 1], oy, hz);
}
if (!strcmp(cmd, "notifclose")) {
/* notifclose <app_id> <reason> */
if (i + 1 >= argc) { fprintf(stderr, "notifclose needs <app_id>\n"); return 1; }
uint32_t r2 = (i + 2 < argc) ? (uint32_t)strtoul(argv[i + 2], NULL, 0) : 0;
return cmd_notifclose(argv[i + 1], r2);
}
if (!strcmp(cmd, "nav")) {
/* nav report <app_id> <depth> <top> | nav exit <app_id> */
if (i + 1 >= argc) { fprintf(stderr, "nav needs <app_id> and report|exit\n"); return 1; }
int exit_req = (!strcmp(argv[i + 1], "exit") || !strcmp(argv[i + 1], "EXIT"));
if (i + 2 >= argc) { fprintf(stderr, "nav needs <app_id>\n"); return 1; }
uint32_t depth = (i + 3 < argc) ? (uint32_t)strtoul(argv[i + 3], NULL, 0) : 0;
const char *top = (i + 4 < argc) ? argv[i + 4] : "";
return cmd_nav(argv[i + 2], exit_req, depth, top);
}
fprintf(stderr, "unknown cmd %s; try --help\n", cmd);
return 1;
}