fix(lyric/bt): ①桌面歌词页封面不显示修复(根因:歌词页从不画封面+scrim逐秒叠涂压黑→新增np_draw_lyric_coverbg封面背景+1s整页重绘;播放页封面宿实证非批5破坏) ②alsa.conf pcm.bluealsa DEV自动识别(bt_dev.c:audiod BT打开时bluealsa-cli检测a2dpsrc设备幂等改写DEV=保留codec/ldac_eqmid等);test_bt_dev 14/14,0warning

This commit is contained in:
AskaEth committed 2026-09-03 22:36:17 +08:00
1 parent ef6eca86b1
commit 8c165bb8e6
6 files changed
+359 -13

No files matched your search

+138
View File
@@ -0,0 +1,138 @@
/* bt_dev.c — 蓝牙 A2DP 设备自识别(纯逻辑实现,见 bt_dev.h 契约)。
*
* 纯 libc(string / stdlib),无任何 meow_* 调用、无 popen、无文件 I/O —— meow_audiod 负责
* 读取 /usr/data/alsa.conf、执行 `bluealsa-cli list-pcms` 及写回。宿主单测零链路重。
*/
#include "bt_dev.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/* 解析 bluealsa-cli list-pcms 输出,取第一个 a2dpsrc/a2dp_source 端点的设备 MAC。
* 端点形如 `a2dpsrc/AA:BB:CC:DD:EE:FF`(MAC 在端点 token 内最后一个 '/' 之后到空白前)。
* 逐个**有界行**匹配(strstr 必须在行内,避免跨换行误把后一行当本行端点——如行 1
* "profile/aptx" 与行 3 "a2dp_source/..." 的经典误判)。 */
int bt_dev_detect_mac(const char *listpcms, char *mac, size_t macsz)
{
if (!listpcms || !mac || macsz < 2) return -1;
mac[0] = 0;
const char *ln = listpcms;
while (ln && *ln) {
const char *nl = strchr(ln, '\n');
const char *le = nl ? nl : (ln + strlen(ln));
size_t linelen = (size_t)(le - ln);
char line[256];
if (linelen >= sizeof line) linelen = sizeof line - 1;
memcpy(line, ln, linelen); line[linelen] = 0;
const char *p = line;
while (*p == ' ' || *p == '\t') p++;
const char *hit = strstr(p, "a2dpsrc");
if (!hit) hit = strstr(p, "a2dp_source");
if (hit) {
const char *te = hit;
while (*te && *te != ' ' && *te != '\t' && *te != '\n') te++;
const char *slash = NULL;
for (const char *q = hit; q < te; q++) if (*q == '/') slash = q;
if (slash && (slash + 1) < te) {
const char *start = slash + 1;
size_t len = (size_t)(te - start);
if (len > 0 && len < macsz) {
memcpy(mac, start, len);
mac[len] = 0;
return 0;
}
}
}
if (!nl) break;
ln = nl + 1;
}
return -1;
}
/* 在单行内把 anchor("DEV=" / "device")后的 MAC 值替换为 mac,保留引号风格。
* 行未含 anchor → 返回 1(out=原样);含 anchor → 写回新行并返回 0。 */
static int line_replace_mac(char *out, size_t outsz, const char *line,
const char *anchor, const char *mac)
{
const char *at = strstr(line, anchor);
if (!at) { snprintf(out, outsz, "%s", line); return 1; }
const char *vp = at + strlen(anchor);
while (*vp == ' ' || *vp == '\t') vp++;
if (*vp == '"') vp++; /* 引号风格:值可带双引号 */
const char *ve = vp;
while (*ve && *ve != ' ' && *ve != '\t' && *ve != '\n' &&
*ve != '"' && *ve != '{' && *ve != '}') ve++;
size_t prefix = (size_t)(vp - line); /* 前段(含开引号,若带) */
size_t tail = (size_t)(ve - line); /* 值终点(不含闭引号,若带) */
/* 前段 + mac + 尾段(尾段保留闭引号与其后内容) */
snprintf(out, outsz, "%.*s%s%s", (int)prefix, line, mac, line + tail);
return 0;
}
/* 幂等改写 alsa.conf:只把 `pcm.bluealsa` 块内 `DEV=` 与 `device` 后的 MAC 换成 mac。
* 逐行处理;无 pcm.bluealsa / 无 DEV= / device token → -1;两端已一致 → 1;改了 → 0。 */
int bt_dev_rewrite(const char *in, size_t in_len, const char *mac,
char **out, size_t *out_len)
{
if (!in || !mac || !mac[0] || !out || !out_len || in_len == 0) return -1;
if (!strstr(in, "pcm.bluealsa") ||
(!strstr(in, "DEV=") && !strstr(in, "device"))) return -1;
size_t cap = in_len + 128;
char *res = malloc(cap ? cap : 1);
if (!res) return -1;
size_t o = 0, changed = 0;
const char *p = in, *end = in + in_len;
while (p < end) {
const char *nl = memchr(p, '\n', (size_t)(end - p));
const char *le = nl ? nl : end;
size_t linelen = (size_t)(le - p);
char line[512], newline[512];
if (linelen >= sizeof line) linelen = sizeof line - 1;
memcpy(line, p, linelen); line[linelen] = 0;
const char *k = line;
while (*k == ' ' || *k == '\t') k++;
int anchored = 0;
if (strstr(k, "DEV=")) {
line_replace_mac(newline, sizeof newline, line, "DEV=", mac);
anchored = 1;
} else if (strncmp(k, "device", 6) == 0 &&
(k[6] == ' ' || k[6] == '\t' || k[6] == 0)) {
line_replace_mac(newline, sizeof newline, line, "device", mac);
anchored = 1;
}
if (anchored) {
if (strcmp(line, newline) != 0) changed = 1;
size_t n = strlen(newline);
if (o + n + 2 > cap) {
cap = o + n + 256;
char *t = realloc(res, cap);
if (!t) { free(res); return -1; }
res = t;
}
memcpy(res + o, newline, n); o += n;
if (nl) res[o++] = '\n';
} else {
size_t n = linelen;
if (o + n + 2 > cap) {
cap = o + n + 256;
char *t = realloc(res, cap);
if (!t) { free(res); return -1; }
res = t;
}
memcpy(res + o, p, n); o += n;
if (nl) res[o++] = '\n';
}
if (!nl) break;
p = nl + 1;
}
if (!changed) { free(res); return 1; }
res[o] = 0;
*out = res;
*out_len = o;
return 0;
}