feat: M6.40批 — 阅读器UI改版(书架list·grid+空态骨架+界面设置+App设置页+header·footer+背景黑默认) + 系统级音量翻页映射 + P1 MD3(select面板28/对话框按钮胶囊) + MeowPanel写端点护栏 + SDK公开仓·文档同步
- reader: app.c/shelf.c/reader.c 全套UI; 新增 reader_conf(reader.conf)/settings(App设置页)/reader_ipc(音量翻页IPC响应); app.json加volume_page - launcher: keys.c meow_volpage_*门 + util.c app_id→fd映射(HELLO记fd/断开清) + app_launcher.c 前台三处接线(进入sink/按键路径volpage_key/离开clear) → 前台声明volume_page的App音量键→MSG_KEY_PAGEUP/PAGEDOWN翻页(非阅读器前台音量照旧) - sdk: meow_select.c 底部面板28 + meow_ui_dialog.c 对话框按钮胶囊(h/2) + test_meow_ui_select.c修采样 - meowpanel: /api/net/policy·/api/power/policy 加防自锁+policy默认关两条护栏(panel.policy_enabled默认0) - 文档: MEOW_APP_SDK.md §12.6 + meowpanel README端点表 0warning;宿主测试全过;二进制留批量批次未入库
This commit is contained in:
1 parent
b364b6371a
commit
2826c1e905
27 files changed
+1704
-129
No files matched your search
@@ -0,0 +1,186 @@
|
||||
/* app/reader_ipc.c — 系统翻页信号接收(见 app/reader_ipc.h)。 */
|
||||
#include "reader_ipc.h"
|
||||
#include "../reader_internal.h" /* reader_page_key() */
|
||||
#include "meow_ipc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
static pthread_mutex_t g_mu = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int g_fd = -1;
|
||||
static pthread_t g_thr;
|
||||
static int g_thr_on = 0;
|
||||
static volatile int g_quit = 0;
|
||||
|
||||
static const char *sock_path(void)
|
||||
{
|
||||
const char *e = getenv("MEOW_IPC_SOCK");
|
||||
return (e && e[0]) ? e : MEOW_IPC_PATH;
|
||||
}
|
||||
|
||||
static void app_id_of(char *out, int outsz)
|
||||
{
|
||||
const char *e = getenv("MEOW_LOG_APP");
|
||||
snprintf(out, (size_t)outsz, "%s", (e && e[0]) ? e : "os.meow.reader");
|
||||
}
|
||||
|
||||
static int connect_path(const char *path)
|
||||
{
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0) 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) { close(fd); return -1; }
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int write_all(int fd, const uint8_t *p, size_t n)
|
||||
{
|
||||
size_t off = 0;
|
||||
while (off < n) {
|
||||
ssize_t w = write(fd, p + off, n - off);
|
||||
if (w < 0) { if (errno == EINTR) continue; return 0; }
|
||||
if (w == 0) return 0;
|
||||
off += (size_t)w;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_all(int fd, uint8_t *p, size_t n)
|
||||
{
|
||||
size_t off = 0;
|
||||
while (off < n) {
|
||||
ssize_t r = read(fd, p + off, n - off);
|
||||
if (r < 0) { if (errno == EINTR) continue; return 0; }
|
||||
if (r == 0) return 0;
|
||||
off += (size_t)r;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int send_frame(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);
|
||||
if (!write_all(fd, hdr, sizeof hdr)) return -1;
|
||||
if (len && payload && !write_all(fd, payload, len)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_frame(int fd, uint16_t *type, uint8_t *rbuf, uint32_t rcap)
|
||||
{
|
||||
uint8_t hdr[MEOW_IPC_HDR_LEN];
|
||||
if (!read_all(fd, hdr, sizeof hdr)) return -1;
|
||||
uint32_t magic, len; uint16_t ver;
|
||||
memcpy(&magic, hdr, 4); memcpy(&ver, hdr + 4, 2); memcpy(type, hdr + 6, 2);
|
||||
memcpy(&len, hdr + 12, 4);
|
||||
if (magic != MEOW_IPC_MAGIC || ver != MEOW_IPC_VERSION) return -1;
|
||||
if (len > rcap) len = rcap;
|
||||
if (len > 0 && !read_all(fd, rbuf, len)) return -1;
|
||||
return (int)len;
|
||||
}
|
||||
|
||||
static int conn_locked(void)
|
||||
{
|
||||
if (g_fd >= 0) return g_fd;
|
||||
int fd = connect_path(sock_path());
|
||||
if (fd < 0) return -1;
|
||||
char app[MEOW_APP_ID_MAX];
|
||||
app_id_of(app, (int)sizeof app);
|
||||
m_hello_t h;
|
||||
memset(&h, 0, sizeof h);
|
||||
snprintf(h.app_id, sizeof h.app_id, "%s", app);
|
||||
h.version = 1;
|
||||
h.flags = 0; /* 非媒体源;仅声明存在,收系统翻页信号 */
|
||||
if (send_frame(fd, MSG_HELLO, 1, &h, sizeof h) != 0) { close(fd); return -1; }
|
||||
uint8_t rbuf[256];
|
||||
uint16_t rt;
|
||||
if (read_frame(fd, &rt, rbuf, sizeof rbuf) < 0 ||
|
||||
(rt != MSG_ACK && rt != MSG_ERR)) { close(fd); return -1; }
|
||||
g_fd = fd;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void mark_dead_locked(void)
|
||||
{
|
||||
if (g_fd >= 0) { close(g_fd); g_fd = -1; }
|
||||
}
|
||||
|
||||
static void *ipc_thread_main(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
while (!g_quit) {
|
||||
pthread_mutex_lock(&g_mu);
|
||||
int fd = g_fd;
|
||||
if (fd < 0) fd = conn_locked(); /* 懒连/重连(best-effort;失败则重试) */
|
||||
pthread_mutex_unlock(&g_mu);
|
||||
if (fd < 0) { usleep(500000); continue; }
|
||||
|
||||
struct pollfd p;
|
||||
p.fd = fd; p.events = POLLIN; p.revents = 0;
|
||||
int pr = poll(&p, 1, 200);
|
||||
if (pr < 0 && errno != EINTR) {
|
||||
pthread_mutex_lock(&g_mu); mark_dead_locked(); pthread_mutex_unlock(&g_mu);
|
||||
continue;
|
||||
}
|
||||
if (pr > 0 && (p.revents & (POLLHUP | POLLERR | POLLNVAL))) {
|
||||
pthread_mutex_lock(&g_mu); mark_dead_locked(); pthread_mutex_unlock(&g_mu);
|
||||
continue;
|
||||
}
|
||||
if (pr > 0 && (p.revents & POLLIN)) {
|
||||
uint8_t rbuf[MEOW_IPC_MAX];
|
||||
uint16_t type;
|
||||
int n = read_frame(fd, &type, rbuf, sizeof rbuf);
|
||||
if (n < 0) {
|
||||
pthread_mutex_lock(&g_mu); mark_dead_locked(); pthread_mutex_unlock(&g_mu);
|
||||
continue;
|
||||
}
|
||||
/* UI 线程经 reader_on_tick 消费(跨线程仅置 pending 计数,不直接改页) */
|
||||
if (type == MSG_KEY_PAGEUP) reader_page_key(-1);
|
||||
else if (type == MSG_KEY_PAGEDOWN) reader_page_key(1);
|
||||
}
|
||||
}
|
||||
pthread_mutex_lock(&g_mu); mark_dead_locked(); pthread_mutex_unlock(&g_mu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void reader_ipc_start(void)
|
||||
{
|
||||
pthread_mutex_lock(&g_mu);
|
||||
int need = !g_thr_on;
|
||||
if (need) { g_quit = 0; g_thr_on = 1; }
|
||||
pthread_mutex_unlock(&g_mu);
|
||||
if (need) {
|
||||
pthread_attr_t at;
|
||||
pthread_attr_init(&at);
|
||||
pthread_attr_setstacksize(&at, 64 * 1024); /* 小栈:阅读态 ≤8MB 纪律 */
|
||||
pthread_create(&g_thr, &at, ipc_thread_main, NULL);
|
||||
pthread_attr_destroy(&at);
|
||||
pthread_detach(g_thr);
|
||||
}
|
||||
}
|
||||
|
||||
void reader_ipc_stop(void)
|
||||
{
|
||||
pthread_mutex_lock(&g_mu);
|
||||
g_quit = 1;
|
||||
mark_dead_locked();
|
||||
g_thr_on = 0;
|
||||
pthread_mutex_unlock(&g_mu);
|
||||
}
|
||||
Reference in new issue
Block a user