Files
MeowOS-For-R3P2/patch_v2/sdk/meow_ui_vol.c
T

122 lines
4.9 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.
/*
* meow_ui_vol.c — SDK 状态栏音量换算纯函数 + settings.conf 读取(A-0 核心数源)。
*
* 单独成 TU 的目的:
* 1. 纯函数(clamp / 键读取)不依赖 meow_ui 其它子系统,宿主 gcc 直接可测
* (test_meow_ui_vol.c),无需链整库/stub。
* 2. 把「音量从 settings 读数并 clamp 到 volume_max」这一语义钉死在单点,
* 与 launcher 的 vol_clamp(audio.c)口径对齐,杜绝两端音量漂移。
*
* 数据源:/usr/data/meow/settings.conf 扁平 key=value。launcher meow_settings.c
* 落盘为 "key = value"(带空格),本解析兼容无空格/多空格,与 launcher 读循环
* 及 sdk meow_ui_theme.c 的 get_setting_str 同款解析。
*/
#include "meow_ui_vol.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int meow_ui_vol_clamp(int vol, int vol_max)
{
if (vol < 0) vol = 0;
if (vol > MEOW_UI_VOL_MAX) vol = MEOW_UI_VOL_MAX;
if (vol_max < 0) vol_max = 0; /* 异常上限兜底:不进负值 */
if (vol > vol_max) vol = vol_max;
return vol;
}
int meow_ui_vol_read(const char *path, const char *key, int def)
{
if (!path || !key) return def;
FILE *f = fopen(path, "r");
if (!f) return def;
int kl = (int)strlen(key);
char line[160];
char *found = NULL;
while (fgets(line, sizeof line, f)) {
char *eq = strchr(line, '=');
if (!eq) continue; /* 非 key=value 行(注释/空行)跳过 */
char *k = line;
while (*k == ' ' || *k == '\t') k++; /* key 左去空白 */
int n = (int)(eq - k);
while (n > 0 && (k[n-1] == ' ' || k[n-1] == '\t')) n--; /* key 右去空白 */
if (n != kl || strncmp(k, key, (size_t)kl) != 0) continue; /* key 不精确匹配 */
found = eq + 1; /* 命中所求键 */
break;
}
fclose(f);
if (!found) return def;
while (*found == ' ' || *found == '\t') found++; /* value 左去空白;atoi 天然停于非数字 */
return atoi(found);
}
/* 改 settings.conf 一个 int 键:流式拷贝原文件到 <path>.tmp,命中键行改写为
* "key = value"(launcher 落盘格式,带空格),键缺失则末尾追加;rename 原子替换。
* 保留其余行(注释/其它设置)——绝不 O_TRUNC 整文件。 */
int meow_ui_vol_set(const char *path, const char *key, int val)
{
if (!path || !path[0] || !key || !key[0]) return -1;
FILE *in = fopen(path, "r");
char tmp[512];
int kl = (int)strlen(key);
snprintf(tmp, sizeof tmp, "%s.tmp", path);
FILE *out = fopen(tmp, "w");
if (!out) { if (in) fclose(in); return -1; }
int found = 0;
char line[256];
while (in && fgets(line, sizeof line, in)) {
char *eq = strchr(line, '=');
char *k = line;
while (*k == ' ' || *k == '\t') k++;
int n = eq ? (int)(eq - k) : 0;
while (n > 0 && (k[n-1] == ' ' || k[n-1] == '\t')) n--;
if (eq && n == kl && strncmp(k, key, (size_t)kl) == 0) {
fprintf(out, "%s = %d\n", key, val); /* 命中:改写为规范格式 */
found = 1;
} else {
fputs(line, out); /* 其它行原样保留 */
}
}
if (in) fclose(in);
if (!found) fprintf(out, "%s = %d\n", key, val);
fclose(out);
if (rename(tmp, path) != 0) { remove(tmp); return -1; }
return 0;
}
/* 音量步进(系统语义,与 launcher 设置页/watchdog 同源:volume_step/volume_max 约束)。
* 只做 settings 逻辑 + 持久化;DAC 写入由调用方(meow_ui_vol_dac_write)负责。 */
int meow_ui_vol_step(const char *path, int dir)
{
int vol = meow_ui_vol_read(path, "audio.volume", MEOW_UI_VOL_DEFAULT);
int vol_max= meow_ui_vol_read(path, "audio.volume_max", MEOW_UI_VOL_MAX_DEF);
int step = meow_ui_vol_read(path, "audio.volume_step", 1);
if (step < 1) step = 1;
if (step > 5) step = 5; /* 与 watchdog 读取口径一致(1..5) */
if (dir < 0) dir = -1;
else if (dir > 0) dir = 1;
else return vol;
int v = meow_ui_vol_clamp(vol + dir * step, vol_max);
if (v == vol) return vol; /* 已在上下限:无进展,不写 */
meow_ui_vol_set(path, "audio.volume", v);
return v;
}
/* 真实 DAC 音量(CS43198, numid 1/2, 0-255),pct→255 映射直写两声道。
* 与 launcher meow_dac_vol_write / watchdog wd_vol_write 完全同路径(语义同源)。 */
void meow_ui_vol_dac_write(int pct)
{
int dac = 255 - pct * 255 / 100; /* CS43198 寄存器=衰减量(0=最响 255=静音),用户 pct 越大越响 → 反转映射 */
if (dac < 0) dac = 0;
if (dac > 255) dac = 255;
char cmd[160];
snprintf(cmd, sizeof cmd,
"amixer -c 0 cset numid=1 %d >/dev/null 2>&1; amixer -c 0 cset numid=2 %d >/dev/null 2>&1",
dac, dac);
system(cmd);
}