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:
1 parent
ef6eca86b1
commit
8c165bb8e6
6 files changed
+359
-13
No files matched your search
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user