Files
MeowOS-For-R3P2/patch_v2/ncm_app/app/app.c
T
MeowOS e0136213fe ncm A2: 音频输出迁移 meow_audiod(SINK_AUDIOD 默认后端)— 修无声根因
- audio_out.c: 新增 SINK_AUDIOD 默认(SDK meow_audio_* 连 audiod);NCM_AUDIO_SINK=file/null/alsa
  与 MEOW_AUDIO_DIRECT=1 保留调试后端;ALSA 保底修两大坑(hw_params 全放行初始化 + mask 清零
  再单点)——旧 memset0 interval=「只能取0」→ HW_PARAMS 恒 EINVAL 即播放无声根因
- 新增 audio_out_pause:PAUSED 沿向 audiod 发 pause(停时钟不丢流);resume 流死自动重开
- player_manager: 注册 meow_audio_on_preempt → g_play 命令通道暂停;播放事件全量 meow_log
  (open 参数/grant_*/write 错误节流/切歌/暂停/seek/done)
- appstate/app: /tmp/ncm_autoplay 真机联调 hook(仅播已缓存曲目,绝不发 song_url)
- bench/audiod_chain_sim.c: 真实 audiod_host 假 socket 全链离线回归 14 项全 PASS
- 验证: host 0 warning / WAV 回归 / qemu core PASS / mipsel 0 warning;真机 OPEN→grant 已通,
  持续写帧被 M2.90 设备 PCM 播放内核硬挂死阻断(REPORT §16.3,4/4 复现,留主会话)
- ncm md5 db5b78ad9e8f40e6306484efe2a08eb3(已热更设备)
2026-09-01 01:17:21 +08:00

152 lines
6.0 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.
/* app.c — dev.player.ncm 应用装配层:main + 组装 + 事件分发。
*
* 职责(对齐 hello_app/app.c):main 只做初始化/建页/跑事件循环/清理;把 meow_ui_run 的平铺输入
* 回调(key/tap/swipe/tick/touch)路由到当前活动页。页面切换统一走 meow_view_page_push/pop/replace。
* 播放线程(player_manager)+ 媒体会话 IPC 线程(ipc_media)在 main 起动、退出时停。
*
* 铁律(APPS.md §3.4.1):物理键禁映射——on_key 不处理任何键语义;返回=左缘左滑/返回钮/request_exit。
* 左缘返回:播放页→歌单→主页→退出(登录页→退出)。
*/
#include "ncm_app_internal.h"
#include <signal.h>
ncm_app_state_t g_st;
ncm_play_run_t g_play = { .mu = PTHREAD_MUTEX_INITIALIZER,
.state = NCM_PC_STOPPED, .cur_song = -1 };
volatile int g_app_quit = 0;
volatile int g_net_ready = 0;
int g_host_mock = 0;
static meow_view *g_login_view, *g_home_view, *g_pl_view, *g_plr_view, *g_set_view,
*g_search_view;
static void on_sigterm(int s) { (void)s; meow_ui_request_exit(); }
/* ============================================================ */
/* 事件分发:meow_ui_run 平铺回调 → 当前页 */
/* ============================================================ */
static void app_on_key(int keycode, int is_down)
{
(void)keycode; (void)is_down; /* 物理键系统语义;App 不映射(§3.4.1) */
}
static void app_on_tap(int x, int y)
{
if (login_is_active()) { login_on_tap(x, y); return; }
if (player_is_active()) { player_on_tap(x, y); return; }
if (settings_is_active()) { settings_on_tap(x, y); return; }
if (playlist_is_active()) { playlist_on_tap(x, y); return; }
if (search_is_active()) { search_on_tap(x, y); return; }
home_on_tap(x, y);
}
static void app_on_swipe(int dir, int dx, int dy)
{
(void)dx;
if (dir == MEOW_SWIPE_LEFT) {
if (player_is_active()) { meow_view_page_pop(); return; }
if (settings_is_active()) { meow_view_page_pop(); return; }
if (playlist_is_active()) { meow_view_page_pop(); return; }
if (search_is_active()) { meow_view_page_pop(); return; }
/* home / login = 根 → 退出 */
meow_log(MEOW_LOG_INFO, "exit:swipe");
meow_ui_request_exit();
return;
}
if (home_is_active()) { home_swipe(dir, dy); return; }
if (playlist_is_active()) { playlist_swipe(dir, dy); return; }
if (search_is_active()) { search_swipe(dir, dy); return; }
if (player_is_active()) { player_on_swipe(dir, dy); return; }
}
static void app_on_touch_down(int x, int y)
{
if (home_is_active()) home_touch_down(x, y);
else if (playlist_is_active()) playlist_touch_down(x, y);
else if (settings_is_active()) settings_touch_down(x, y);
else if (search_is_active()) search_touch_down(x, y);
}
static void app_on_touch_move(int x, int y)
{
if (home_is_active()) home_touch_move(x, y);
else if (playlist_is_active()) playlist_touch_move(x, y);
else if (settings_is_active()) settings_touch_move(x, y);
else if (search_is_active()) search_touch_move(x, y);
}
static void app_on_swipe_progress(int x_start, int dx)
{
meow_ui_swipe_hint(x_start + dx);
}
static void app_on_tick(void)
{
uint64_t now = meow_ui_time_ms();
autoplay_maybe(); /* 真机联调 hook:/tmp/ncm_autoplay 存在则自动播已缓存曲目(一次性) */
if (login_is_active()) { login_tick(now); return; }
if (player_is_active()) { player_tick(now); return; }
if (search_is_active()) { search_tick(now); return; }
if (home_is_active()) { home_tick(now); }
if (playlist_is_active()) { playlist_tick(now); }
chrome_tick();
}
/* ============================================================ */
/* main */
/* ============================================================ */
int main(void)
{
meow_log(MEOW_LOG_INFO, "start");
meow_ui_opts o = { APP_W, APP_H };
if (meow_ui_init(&o) != 0) { meow_log(MEOW_LOG_ERROR, "init failed"); return 1; }
/* 主题侦听:登记真实回调(旧代码 pass NULL 无效),系统明暗切换 → ncm_on_theme 实时换肤。
* 初始同步一次 g_dark(listener 只在变化时被调,初次状态需显式对齐)。 */
g_dark = (meow_theme_get_mode() == MEOW_THEME_DARK);
meow_theme_add_listener(ncm_on_theme);
signal(SIGTERM, on_sigterm);
/* 应用数据/核心库上下文(cookie/deviceId/cache/设置) */
appstate_init();
/* M2.82-联调修复:设备无系统 CA 库(真机 rc=-5 TLS 错误根因)——App 自带 Mozilla CA bundle,
* 显式指给 core HTTP 层(保持 verify=1,不降级为不校验) */
ncm_http_set_verify_default(1, "/usr/data/mnt/sd_0/MeowAPPs/dev.player.ncm/cacert.pem");
/* 播放 + 媒体会话线程(UI 不卡;无 launcher socket 时 ipc 优雅跳过) */
player_manager_start();
ipc_media_start();
g_net_ready = 1;
/* 建六页 view */
g_login_view = login_view_create();
g_home_view = home_view_create();
g_pl_view = playlist_view_create();
g_plr_view = player_view_create();
g_set_view = settings_view_create();
g_search_view = search_view_create();
/* 进入根页:已登录→home,否则→login */
meow_view_page_push(g_st.logged_in ? ACT_HOME : ACT_LOGIN);
meow_ui_events ev = {
app_on_key, app_on_tap, app_on_swipe, app_on_tick, app_on_swipe_progress,
app_on_touch_down, app_on_touch_move,
};
meow_ui_run(&ev);
/* 清理:停线程 → 释放页 */
g_app_quit = 1;
player_manager_stop_thread();
ipc_media_stop();
meow_view_free(g_set_view);
meow_view_free(g_plr_view);
meow_view_free(g_pl_view);
meow_view_free(g_home_view);
meow_view_free(g_login_view);
meow_view_free(g_search_view);
meow_ui_shutdown();
meow_log(MEOW_LOG_INFO, "exit");
return 0;
}