/* test_now_playing_widgets.c — M7.0b Now Playing 控件化宿主验证。 * * 复现 run_now_playing() 所建控件集(np_widgets_create:meow_progress 进度条 + meow_iconbtn * 三钮,play/pause 同位双钮按状态只画其一),验证: * N1 进度条:value clamp 0-100 + track/fill 渲染(填充分界像素不同); * N2 三钮圆形命中:圆心命中、角部不命中; * N3 play/pause 同位切换:两钮图标位图不同 → 中心像素不同(画 PAUSE vs PLAY_ARROW); * N4 主题四态(MD3/MIUIx × 明暗)下进度条+三钮渲染非背景像素。 * * 几何常量与 now_playing.c 同源(镜像);控件创建方式与 np_widgets_create 同。 * 编译(在 patch_v2/meow_launcherd 下): * gcc -Wall -Wextra -o test_now_playing_widgets test_now_playing_widgets.c \ * ../sdk/test_host_stub.c ../sdk/meow_ui_gfx.c ../sdk/meow_ui_sys.c \ * ../sdk/meow_ui_theme.c ../sdk/meow_ui_vol.c ../sdk/meow_ui_log.c \ * ../sdk/meow_ui_widget.c ../sdk/meow_ui_input.c ../sdk/meow_ui_activity.c \ * ../sdk/meow_ui_dialog.c ../sdk/meow_ui_ime.c ../sdk/meow_ui_str.c ../sdk/meow_pinyin.c \ * ../sdk/meow_ui_draw.c ../sdk/meow_ui_view.c ../sdk/meow_ui_box.c ../sdk/meow_ui_anim.c \ * ../sdk/meow_ui_scroll.c ../sdk/meow_ui_img.c ../sdk/meow_ui_media.c \ * ../sdk/meow_notify_ipc.c ../sdk/stb_image.c \ * ../sdk/meow_lyric.c ../sdk/meow_lyric_view.c \ * -I../sdk -I. -DMEOW_UI_HOST_TEST -pthread -lm * 运行:./test_now_playing_widgets */ #include "meow_ui.h" #include "meow_ui_internal.h" /* meow_ui_back_buf/pitch/bpp */ #include "np_gesture.h" /* 批4:双页方向感知手势决策(纯逻辑,宿主可单测) */ #include "meow_lyric_view.h" /* 批2:歌词页控件(批4接入,数据批3 meow_media_lyric_*) */ #include "meow_img_color.h" /* 批5b:封面取色主题派生(局部重绘进度条/按钮带取色用例) */ #include #include #include #include static int g_fail = 0; #define CHECK(cond, name) do { \ if (cond) printf(" PASS %s\n", name); \ else { printf(" FAIL %s\n", name); g_fail++; } } while (0) /* ---- 与 now_playing.c 同源几何(镜像) ---- */ #define NP_PROG_X 40 #define NP_PROG_W (480 - 80) /* 400 */ #define NP_PROG_Y 518 #define NP_TIME_Y 492 #define NP_BTN_Y 568 #define NP_PLAY_CX 240 #define NP_PREV_CX (NP_PLAY_CX - 78) /* 162 */ #define NP_NEXT_CX (NP_PLAY_CX + 78) /* 318 */ #define NP_PLAY_R 30 #define NP_PREV_R 22 #define NP_SENTINEL 0x51 static meow_widget *prog = NULL, *prev = NULL, *play = NULL, *pause = NULL, *next = NULL; static void rd_px(int x, int y, unsigned short *p) { unsigned char *bb = meow_ui_back_buf(); int line = meow_ui_back_buf_pitch(), bpp = meow_ui_back_buf_bpp(); if (!bb || x < 0 || y < 0) { *p = 0; return; } if (bpp == 16) *p = *(unsigned short *)(bb + (size_t)y * line + (size_t)x * 2); else *p = (unsigned short)(*(unsigned int *)(bb + (size_t)y * line + (size_t)x * 4) >> 16); } static unsigned short px565(int x, int y) { unsigned short p; rd_px(x, y, &p); return p; } static unsigned short rgb565(uint32_t c) { return (unsigned short)(((c >> 8) & 0xF800) | ((c >> 5) & 0x07E0) | ((c >> 3) & 0x001F)); } static int region_nonbg(int x, int y, int w, int h, uint32_t bg) { unsigned short bg565 = ((bg >> 8) & 0xF800) | ((bg >> 5) & 0x07E0) | ((bg >> 3) & 0x001F); int cnt = 0; for (int dy = 0; dy < h; dy++) for (int dx = 0; dx < w; dx++) if (px565(x + dx, y + dy) != bg565) cnt++; return cnt; } static void mk_widgets(void) { meow_ui_activity_push(NP_SENTINEL); prog = meow_progress_create(NP_PROG_X, NP_PROG_Y, NP_PROG_W, 6, 0); prev = meow_iconbtn_create(NP_PREV_CX - NP_PREV_R, NP_BTN_Y - NP_PREV_R, NP_PREV_R * 2, MEOW_ICON_SKIP_PREV); play = meow_iconbtn_create(NP_PLAY_CX - NP_PLAY_R, NP_BTN_Y - NP_PLAY_R, NP_PLAY_R * 2, MEOW_ICON_PLAY_ARROW); pause = meow_iconbtn_create(NP_PLAY_CX - NP_PLAY_R, NP_BTN_Y - NP_PLAY_R, NP_PLAY_R * 2, MEOW_ICON_PAUSE); next = meow_iconbtn_create(NP_NEXT_CX - NP_PREV_R, NP_BTN_Y - NP_PREV_R, NP_PREV_R * 2, MEOW_ICON_SKIP_NEXT); /* 主播放钮强调:primary/onPrimary(镜像 np_widgets_create) */ const meow_theme *th = meow_theme_get(); meow_widget_opts op; memset(&op, 0, sizeof op); op.bg = th->primary; op.fg = th->onPrimary; meow_widget_set_opts(play, &op); meow_widget_set_opts(pause, &op); meow_ui_activity_pop(); } /* 歌词视图宽度测量(宿主:字节数近似,够用不裂屏;launcher 侧为 ui_width)。 */ static int lv_test_width(const char *u, int size, void *ctx) { (void)size; (void)ctx; return (int)strlen(u); } int main(void) { setbuf(stdout, NULL); setenv("MEOW_UI_DUMP", "/tmp/nowplaying.ppm", 1); meow_ui_opts o = { 480, 720 }; assert(meow_ui_init(&o) == 0); meow_ui_activity_push(NP_SENTINEL); mk_widgets(); const meow_theme *th = meow_theme_get(); meow_ui_set_style(MEOW_STYLE_MD3); meow_theme_set_mode(MEOW_THEME_DARK); th = meow_theme_get(); /* ============ N1 进度条 clamp + track/fill 渲染 ============ */ printf("N1 progress value + track/fill\n"); meow_widget_set_opts(prog, &(meow_widget_opts){ .bg = 0 }); meow_ui_clear(0); meow_progress_set(prog, 150); /* clamp → 100 */ meow_widget_draw(prog); unsigned short fill_end = px565(NP_PROG_X + NP_PROG_W - 2, NP_PROG_Y + 3); unsigned short track_mid = px565(NP_PROG_X + NP_PROG_W / 2, NP_PROG_Y + 3); CHECK(fill_end != 0 && track_mid != 0, "value 150 clamp 100 -> full fill renders"); meow_progress_set(prog, 50); meow_widget_draw(prog); /* 50% 填充区 [40,240) 内像素应为主色;240 之后的轨道区应为轨道色(surfaceVariant) */ unsigned short infill = px565(NP_PROG_X + NP_PROG_W / 4, NP_PROG_Y + 3); /* x=140,填充区 */ unsigned short empty = px565(NP_PROG_X + NP_PROG_W - 4, NP_PROG_Y + 3); /* x=436,轨道区 */ CHECK(infill != empty, "value 50 -> fill region differs from empty tail"); /* ============ N2 三钮圆形命中 ============ */ printf("N2 circular hit\n"); CHECK(meow_widget_hit(prev, NP_PREV_CX, NP_BTN_Y), "prev center hits"); CHECK(!meow_widget_hit(prev, NP_PREV_CX - NP_PREV_R, NP_BTN_Y - NP_PREV_R), "prev corner MISSES"); CHECK(meow_widget_hit(play, NP_PLAY_CX, NP_BTN_Y), "play center hits"); CHECK(meow_widget_hit(pause, NP_PLAY_CX, NP_BTN_Y), "pause(overlay) center hits"); CHECK(!meow_widget_hit(play, NP_PLAY_CX - NP_PLAY_R, NP_BTN_Y - NP_PLAY_R), "play corner MISSES"); CHECK(meow_widget_hit(next, NP_NEXT_CX, NP_BTN_Y), "next center hits"); /* ============ N3 play/pause 同位切换(两钮位图不同 → 像素不同) ============ */ printf("N3 play/pause overlay icon switch\n"); meow_ui_clear(0); meow_widget_draw(play); meow_ui_clear(0); /* 只画 play */ meow_widget_draw(play); unsigned short p_play = px565(NP_PLAY_CX, NP_BTN_Y); /* 中心=图标墨色 */ meow_ui_clear(0); meow_widget_draw(pause); unsigned short p_pause = px565(NP_PLAY_CX, NP_BTN_Y); CHECK(p_play != p_pause, "play vs pause icon differs at centre (overlay switch works)"); /* 圆心区域非页面底色(画出来了) */ meow_ui_clear(0); meow_widget_draw(pause); CHECK(region_nonbg(NP_PLAY_CX - NP_PLAY_R, NP_BTN_Y - NP_PLAY_R, NP_PLAY_R * 2, NP_PLAY_R * 2, th->surface) > 0, "pause button renders non-bg in circle"); /* ============ N4 主题四态:进度条+三钮渲染非背景 ============ */ printf("N4 theme 4-state render\n"); const int styles[2] = { MEOW_STYLE_MD3, MEOW_STYLE_MIUIX }; const int modes[2] = { MEOW_THEME_LIGHT, MEOW_THEME_DARK }; for (int si = 0; si < 2; si++) { for (int mi = 0; mi < 2; mi++) { meow_ui_set_style(styles[si]); meow_theme_set_mode((meow_theme_mode)modes[mi]); th = meow_theme_get(); meow_theme ex; meow_theme_export(&ex); CHECK(ex.primary == th->primary && ex.surface == th->surface && ex.surfaceVariant == th->surfaceVariant, "export == get (spot roles)"); meow_ui_clear(0); meow_progress_set(prog, 40); meow_widget_draw(prog); meow_widget_draw(prev); meow_widget_draw(pause); meow_widget_draw(next); char nm[80]; int progpx = region_nonbg(NP_PROG_X, NP_PROG_Y, NP_PROG_W, 6, th->surface); int btnpx = region_nonbg(NP_PLAY_CX - NP_PLAY_R, NP_BTN_Y - NP_PLAY_R, NP_PLAY_R * 2, NP_PLAY_R * 2, th->surface); snprintf(nm, sizeof nm, "style=%s mode=%s prog+btn render", styles[si] ? "MIUIx" : "MD3", modes[mi] ? "dark" : "light"); CHECK(progpx > 0 && btnpx > 0, nm); } } /* ============ R1 批5b:局部重绘取色——进度条 fill=accent/track=fg_dim + 默认回退 ============ * 镜像 np_theme_widgets(取色有效→进度条 opts.bg=fg_dim/opts.fg=accent)+ np_draw_progress。 * 用「直接 fill_rect 参考像素」对比,绕开 565 精度差异(同一渲染器同色 → 同 565)。 */ printf("R1 progress cover-theme fill/track + default fallback\n"); meow_ui_set_style(MEOW_STYLE_MD3); meow_theme_set_mode(MEOW_THEME_DARK); th = meow_theme_get(); meow_img_color_theme cc; memset(&cc, 0, sizeof cc); meow_img_color_derive(0xE53935u, 0x1E88E5u, th, &cc); /* 红/蓝两色 → 派生取色主题 */ /* 覆盖取色:进度条 fill=accent / track=fg_dim */ { meow_widget_opts op; memset(&op, 0, sizeof op); op.bg = cc.fg_dim; op.fg = cc.accent; meow_widget_set_opts(prog, &op); meow_ui_clear(0); meow_ui_fill_rect(NP_PROG_X, NP_PROG_Y, 5, 6, cc.accent); /* fill 参考 */ unsigned short ref_fill = px565(NP_PROG_X + 2, NP_PROG_Y + 3); meow_ui_clear(0); meow_ui_fill_rect(NP_PROG_X + NP_PROG_W - 4, NP_PROG_Y, 3, 6, cc.fg_dim); /* track 参考 */ unsigned short ref_track = px565(NP_PROG_X + NP_PROG_W - 3, NP_PROG_Y + 3); meow_ui_clear(0); meow_progress_set(prog, 50); meow_widget_draw(prog); int fill_x = NP_PROG_X + NP_PROG_W / 4; /* 50% 填充区内 */ int track_x = NP_PROG_X + NP_PROG_W - 4; /* 尾部轨道区 */ CHECK(px565(fill_x, NP_PROG_Y + 3) == ref_fill, "cover: progress fill == accent"); CHECK(px565(track_x, NP_PROG_Y + 3) == ref_track, "cover: progress track == fg_dim"); /* 默认回退:清 opts → 回到主题 primary/surfaceVariant(无取色回退默认) */ memset(&op, 0, sizeof op); meow_widget_set_opts(prog, &op); meow_ui_clear(0); meow_ui_fill_rect(NP_PROG_X, NP_PROG_Y, 5, 6, th->primary); unsigned short ref_pri = px565(NP_PROG_X + 2, NP_PROG_Y + 3); meow_ui_clear(0); meow_progress_set(prog, 50); meow_widget_draw(prog); CHECK(px565(fill_x, NP_PROG_Y + 3) == ref_pri, "default: progress fill == theme primary"); CHECK(px565(fill_x, NP_PROG_Y + 3) != ref_fill, "default vs cover fill differ"); } /* ============ R2 批5b:进度/按钮带底色随取色渐变(非默认 surface) ============ * 镜像 np_repaint_progress 的带底色分支(np_page_bg_row 按整页 span 插值)。 * 旧 bug:本地重绘用 th->surface 清带 → 带内被刷成默认色;现应取色渐变且 != surface。 */ printf("R2 band background uses cover gradient (not default surface)\n"); { #define NP_SB_H 28 int H = 720; meow_ui_clear(0); for (int yy = NP_TIME_Y; yy < NP_BTN_Y + NP_PLAY_R; yy++) { int t = (H - NP_SB_H <= 1) ? 0 : (yy - NP_SB_H) * 255 / (H - NP_SB_H - 1); if (t < 0) t = 0; else if (t > 255) t = 255; int tr = (cc.bg_top >> 16) & 255, tg = (cc.bg_top >> 8) & 255, tb = cc.bg_top & 255; int br = (cc.bg_bottom >> 16) & 255, bg = (cc.bg_bottom >> 8) & 255, bb = cc.bg_bottom & 255; int r = tr + ((br - tr) * t + 128) / 255; int g = tg + ((bg - tg) * t + 128) / 255; int b = tb + ((bb - tb) * t + 128) / 255; meow_ui_fill_rect(0, yy, 480, 1, ((uint32_t)r << 16) | ((uint32_t)g << 8) | (uint32_t)b); } unsigned short bandpx = px565(10, NP_TIME_Y + 55); CHECK(bandpx != rgb565(th->surface), "cover: band bg != default surface"); CHECK(bandpx != 0, "cover: band bg rendered"); } /* ============ R3 批5b:控制三钮(含 prev/next)随取色 accent + 默认回退 ============ * 镜像 np_theme_widgets:取色有效→四钮 opts.bg=accent/opts.fg=accent_fg(prev/next 不再默认底色)。 */ printf("R3 control buttons follow cover accent\n"); { meow_widget_opts op; memset(&op, 0, sizeof op); op.bg = cc.accent; op.fg = cc.accent_fg; meow_widget_set_opts(prev, &op); meow_widget_set_opts(next, &op); meow_widget_set_opts(play, &op); meow_widget_set_opts(pause, &op); meow_ui_clear(0); meow_ui_fill_rect(NP_PREV_CX - 2, NP_BTN_Y - 18, 4, 2, cc.accent); /* accent 参考(圆底上方、图标外) */ unsigned short ref_acct = px565(NP_PREV_CX, NP_BTN_Y - 17); meow_ui_clear(0); meow_widget_draw(prev); /* r=22,cy-17 在圆内且高于图标(cy-13) */ CHECK(px565(NP_PREV_CX, NP_BTN_Y - 17) == ref_acct, "cover: prev bg == accent"); meow_ui_clear(0); meow_widget_draw(play); /* r=30,cy-26 在圆内且高于图标(cy-18) */ CHECK(px565(NP_PLAY_CX, NP_BTN_Y - 26) == ref_acct, "cover: play bg == accent"); /* 默认回退:清 prev/next opts → 回 surfaceContainerLow(无取色不回归旧形态) */ memset(&op, 0, sizeof op); meow_widget_set_opts(prev, &op); meow_widget_set_opts(next, &op); meow_ui_clear(0); meow_ui_fill_rect(NP_PREV_CX - 2, NP_BTN_Y - 18, 4, 2, th->surfaceContainerLow); unsigned short ref_def = px565(NP_PREV_CX, NP_BTN_Y - 17); meow_ui_clear(0); meow_widget_draw(prev); CHECK(px565(NP_PREV_CX, NP_BTN_Y - 17) == ref_def, "default: prev bg == surfaceContainerLow"); } /* ============ G5 双页手势方向感知(np_gesture.h,纯逻辑) ============ */ printf("G5 dual-page direction-aware gestures\n"); /* 播放页:右→左滑 → 进歌词页 */ CHECK(np_gesture_decide(NP_PAGE_PLAY, 200, 100, -50, 5) == NP_GEST_NEXT, "play: left-swipe -> lyric"); /* 播放页:左缘右滑 → 回桌面(保留 M6.26) */ CHECK(np_gesture_decide(NP_PAGE_PLAY, 8, 100, 80, 5) == NP_GEST_EXIT, "play: edge right-swipe -> exit"); /* 播放页:任意右滑 → 返回桌面(用户定案「播放页任意右滑回桌面」,含非左缘;np_gesture.h 恒 EXIT) */ CHECK(np_gesture_decide(NP_PAGE_PLAY, 200, 100, 80, 5) == NP_GEST_EXIT, "play: non-edge right-swipe -> EXIT"); /* 歌词页:左→右滑 → 回播放页(不是回桌面) */ CHECK(np_gesture_decide(NP_PAGE_LYRIC, 200, 100, 60, 5) == NP_GEST_PREV, "lyric: right-swipe -> play"); /* 歌词页:左缘右滑 → 回播放页(不接桌面,避免误退) */ CHECK(np_gesture_decide(NP_PAGE_LYRIC, 8, 100, 80, 5) == NP_GEST_PREV, "lyric: edge right-swipe -> play (not exit)"); /* 歌词页:右→左滑 → 歌词页是末页,忽略 */ CHECK(np_gesture_decide(NP_PAGE_LYRIC, 200, 100, -60, 5) == NP_GEST_NONE, "lyric: left-swipe -> none"); /* 顶部热区下滑 → 通知中心(两个页面同语义) */ CHECK(np_gesture_decide(NP_PAGE_PLAY, 100, 10, 0, 70) == NP_GEST_TOP, "top swipe-down -> notif"); /* 近点按 → TAP;纵向主导 → NONE(不误切) */ CHECK(np_gesture_decide(NP_PAGE_PLAY, 200, 300, 5, 5) == NP_GEST_TAP, "near tap -> TAP"); CHECK(np_gesture_decide(NP_PAGE_PLAY, 200, 300, 5, 80) == NP_GEST_NONE, "vertical dominant -> NONE"); /* ============ G5b 批② 底部上滑(home)手势(np_gesture.h np_home_gesture,纯逻辑) ============ */ printf("G5b bottom-swipe-up home gesture\n"); const int FBRES = 720; /* 屏高(宿主 480x720;真机 fb_yres=720) */ const int BZ = FBRES - NP_HOME_EDGE_H; /* 底部起滑区上界 692 */ /* 底部起滑 + 向上主导 ≥阈值 → HOME */ CHECK(np_home_gesture(200, BZ + 10, 0, -120, FBRES) == 1, "home: bottom zone + up-swipe -> HOME"); CHECK(np_home_gesture(100, FBRES - 1, 20, -80, FBRES) == 1, "home: very bottom + slight right-drift up -> HOME"); /* 与左缘返回互斥:左缘起点(down_x NOT home (reserved for edge-back)"); /* 起点不在底部起滑区(顶部/中部)不认 home */ CHECK(np_home_gesture(200, 10, 0, -120, FBRES) == 0, "home: top origin -> NOT home"); CHECK(np_home_gesture(200, 300, 0, -120, FBRES) == 0, "home: mid origin -> NOT home"); /* 横向主导(向右滑)不认 home(该判给左缘返回/切页) */ CHECK(np_home_gesture(200, BZ + 10, 120, 0, FBRES) == 0, "home: right-dominant -> NOT home"); /* 向下滑 / 未达阈值 / 竖向不主导 不认 home */ CHECK(np_home_gesture(200, BZ + 10, 0, 120, FBRES) == 0, "home: downward -> NOT home"); CHECK(np_home_gesture(200, BZ + 10, 0, -NP_HOME_SWIPE + 1, FBRES) == 0, "home: below up-threshold -> NOT home"); CHECK(np_home_gesture(200, BZ + 10, -120, -80, FBRES) == 0, "home: horizontal-dominant up -> NOT home"); /* 与 now_playing.c 集成顺序一致:np_gesture_decide 对底部纵滑返回 NONE,再由 home 覆盖为 HOME */ { int dx = 0, dy = -120, tdx = 200, tdy = BZ + 10; np_gest_t gnp = np_gesture_decide(NP_PAGE_PLAY, tdx, tdy, dx, dy); if (np_home_gesture(tdx, tdy, dx, dy, FBRES)) gnp = NP_GEST_HOME; CHECK(gnp == NP_GEST_HOME, "integration: bottom up-swipe -> HOME (overrides decide-NONE)"); } /* 集成:左缘起点底部上滑不被误判为 home(保留给左缘返回) */ { int tdx = 8, tdy = BZ + 10, dx = 0, dy = -120; /* 左缘 + 上滑(竖向主导) */ np_gest_t gnp = np_gesture_decide(NP_PAGE_PLAY, tdx, tdy, dx, dy); if (np_home_gesture(tdx, tdy, dx, dy, FBRES)) gnp = NP_GEST_HOME; CHECK(gnp != NP_GEST_HOME, "integration: left-edge origin up-swipe -> NOT home"); } /* ============ G6 歌词页:空态 + 渲染(批2 控件 + 批3 数据语义) ============ */ printf("G6 lyric view: empty + render\n"); meow_ui_activity_push(NP_SENTINEL); meow_lyric_view *lv = meow_lyric_view_create(0, 28, 480, 720 - 28, lv_test_width, NULL); meow_lyric_view_set_empty(lv, "暂无歌词"); meow_ui_activity_pop(); CHECK(lv != NULL, "lyric_view created"); if (lv) { /* 无歌词空态:无解析 → 0 行、visible=0(视图内建空态文案) */ meow_lyric_clear(); CHECK(meow_lyric_count() == 0, "clear -> 0 lines"); CHECK(meow_lyric_view_visible(lv, 0, NULL, 0) == 0, "empty -> 0 visible entries"); /* 有词:解析两行 → count/line_at/visible/当前行色 */ int np = meow_lyric_parse("[00:01.00]第一行歌词\n[00:05.00]第二行歌词", ""); CHECK(np == 2, "parse -> 2 lines"); CHECK(meow_lyric_count() == 2, "count == 2"); CHECK(meow_lyric_line_at(0) == 0, "line_at(0) -> first"); CHECK(meow_lyric_line_at(3000) == 0, "line_at(3000) -> first"); CHECK(meow_lyric_line_at(6000) == 1, "line_at(6000) -> second"); CHECK(strcmp(meow_lyric_line_text(0), "第一行歌词") == 0, "text(0) == 第一行歌词"); meow_lyric_view_vis vb[9]; int vn = meow_lyric_view_visible(lv, 3000, vb, 9); CHECK(vn > 0, "visible(3000) > 0"); CHECK(meow_lyric_view_cur_color(lv) == meow_theme_get()->onSurface, "cur_color == theme onSurface"); /* 批5 取色预留:set_colors 可接入(覆盖活动行为主题 accent 后再还原默认) */ meow_lyric_view_colors c; memset(&c, 0, sizeof c); c.cur = meow_theme_get()->accent; meow_lyric_view_set_colors(lv, &c); CHECK(meow_lyric_view_cur_color(lv) == meow_theme_get()->accent, "set_colors cur override works"); meow_lyric_view_set_colors(lv, NULL); /* 回主题默认 */ CHECK(meow_lyric_view_cur_color(lv) == meow_theme_get()->onSurface, "set_colors NULL -> theme default"); meow_lyric_view_free(lv); } meow_ui_activity_pop(); meow_ui_shutdown(); printf(g_fail ? "\nRESULT: %d FAIL(S)\n" : "\nRESULT: ALL PASS\n", g_fail); return g_fail; }