Commit c4f0ffb2 authored by 957dd's avatar 957dd

修改了喇叭和麦并优化了

parent 8d1ec7b8
No preview for this file type
...@@ -458,16 +458,100 @@ static int pulse_module_exists(const char *module_name, const char *device) ...@@ -458,16 +458,100 @@ static int pulse_module_exists(const char *module_name, const char *device)
return 0; return 0;
} }
static int pulse_endpoint_score(const char *name, int is_sink)
{
if (!name)
return 0;
if (strstr(name, is_sink ? "yundea-output" : "yundea-input") != NULL)
return 4;
if (strstr(name, is_sink ? "alsa_output.usb-" : "alsa_input.usb-") != NULL)
return 3;
if (strstr(name, is_sink ? "alsa_output.hw_2_0" : "alsa_input.hw_2_0") != NULL)
return 2;
return 0;
}
static int pulse_find_existing_endpoint(int is_sink, char *name_out, size_t name_size)
{
FILE *fp;
char line[512];
int best_score = 0;
if (!name_out || name_size == 0)
return 0;
name_out[0] = '\0';
fp = popen(is_sink ? "pactl list short sinks 2>/dev/null"
: "pactl list short sources 2>/dev/null", "r");
if (!fp)
return 0;
while (fgets(line, sizeof(line), fp) != NULL) {
char *saveptr = NULL;
char *field;
char *endpoint_name;
int score;
field = strtok_r(line, "\t", &saveptr); /* index */
if (!field)
continue;
endpoint_name = strtok_r(NULL, "\t", &saveptr);
if (!endpoint_name)
continue;
score = pulse_endpoint_score(endpoint_name, is_sink);
if (score <= best_score)
continue;
strncpy(name_out, endpoint_name, name_size - 1);
name_out[name_size - 1] = '\0';
best_score = score;
}
pclose(fp);
return best_score > 0;
}
/* 返回 1=找到并设为默认,0=没有找到,-1=找到但设置失败。 */
static int pulse_activate_existing_endpoint(int is_sink, const char *label)
{
char endpoint_name[256];
char cmd[384];
int exit_code;
if (!pulse_find_existing_endpoint(is_sink, endpoint_name, sizeof(endpoint_name)))
return 0;
snprintf(cmd, sizeof(cmd), "pactl set-default-%s %s >/dev/null 2>&1",
is_sink ? "sink" : "source", endpoint_name);
exit_code = pulse_pactl_exit_code(system(cmd));
if (exit_code != 0) {
my_zlog_warn("%s 已存在但设为默认失败 exit=%d: %s",
label, exit_code, endpoint_name);
return -1;
}
my_zlog_info("%s 已存在并设为默认,复用 PulseAudio 端点: %s",
label, endpoint_name);
return 1;
}
static int pulse_load_alsa_module(const char *module_name, const char *label) static int pulse_load_alsa_module(const char *module_name, const char *label)
{ {
char cmd[256]; char cmd[256];
char output[512]; char output[512];
char line[256]; char line[256];
int is_sink = strcmp(module_name, "module-alsa-sink") == 0;
int endpoint_result;
/* module-udev-detect 通常已经注册 USB 声卡,优先复用,避免重复抢 hw:2,0。 */
endpoint_result = pulse_activate_existing_endpoint(is_sink, label);
if (endpoint_result != 0)
return endpoint_result > 0 ? 0 : -1;
if (pulse_module_exists(module_name, AUDIO_USB_ALSA_DEVICE)) { if (pulse_module_exists(module_name, AUDIO_USB_ALSA_DEVICE)) {
my_zlog_info("%s 已注册,跳过 (%s device=%s)", my_zlog_warn("%s 模块已注册但未找到对应 PulseAudio 端点 (%s device=%s)",
label, module_name, AUDIO_USB_ALSA_DEVICE); label, module_name, AUDIO_USB_ALSA_DEVICE);
return 0; return -1;
} }
snprintf(cmd, sizeof(cmd), "pactl load-module %s device=%s 2>&1", snprintf(cmd, sizeof(cmd), "pactl load-module %s device=%s 2>&1",
...@@ -494,20 +578,29 @@ static int pulse_load_alsa_module(const char *module_name, const char *label) ...@@ -494,20 +578,29 @@ static int pulse_load_alsa_module(const char *module_name, const char *label)
int exit_code = pulse_pactl_exit_code(status); int exit_code = pulse_pactl_exit_code(status);
if (exit_code == 0) { if (exit_code == 0) {
my_zlog_info("%s 注册成功 (%s device=%s)%s%s", delay_ms(100);
endpoint_result = pulse_activate_existing_endpoint(is_sink, label);
if (endpoint_result > 0)
return 0;
my_zlog_warn("%s 模块加载成功但没有可用端点 (%s device=%s)%s%s",
label, module_name, AUDIO_USB_ALSA_DEVICE, label, module_name, AUDIO_USB_ALSA_DEVICE,
output[0] ? ", pactl: " : "", output[0] ? output : ""); output[0] ? ", pactl: " : "", output[0] ? output : "");
return 0; return -1;
} }
if (pulse_output_means_already_loaded(output) || if (pulse_output_means_already_loaded(output) ||
pulse_module_exists(module_name, AUDIO_USB_ALSA_DEVICE)) { pulse_module_exists(module_name, AUDIO_USB_ALSA_DEVICE)) {
my_zlog_info("%s 已注册,跳过 (%s device=%s)%s%s", delay_ms(100);
label, module_name, AUDIO_USB_ALSA_DEVICE, endpoint_result = pulse_activate_existing_endpoint(is_sink, label);
output[0] ? ": " : "", output[0] ? output : ""); if (endpoint_result > 0)
return 0; return 0;
} }
/* 加载失败也再检查一次:常见原因是 udev 已经占用声卡。 */
endpoint_result = pulse_activate_existing_endpoint(is_sink, label);
if (endpoint_result > 0)
return 0;
my_zlog_warn("%s 注册失败 (%s device=%s): exit=%d%s%s", my_zlog_warn("%s 注册失败 (%s device=%s): exit=%d%s%s",
label, module_name, AUDIO_USB_ALSA_DEVICE, exit_code, label, module_name, AUDIO_USB_ALSA_DEVICE, exit_code,
output[0] ? ", pactl: " : ", pactl 无输出", output[0] ? ", pactl: " : ", pactl 无输出",
......
...@@ -39,7 +39,7 @@ static int diag_check_camera(char *name, size_t name_sz, char *msg, size_t msg_s ...@@ -39,7 +39,7 @@ static int diag_check_camera(char *name, size_t name_sz, char *msg, size_t msg_s
DIR *dir; DIR *dir;
struct dirent *ent; struct dirent *ent;
int found = 0; int found = 0;
char path[64]; char path[320]; /* 容纳 /dev/ + d_name(最长255) */
dir = opendir("/dev"); dir = opendir("/dev");
if (!dir) { if (!dir) {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define ZLOG_CONF_FILE PROJECT_ROOT_DIR "/zlog.conf" #define ZLOG_CONF_FILE PROJECT_ROOT_DIR "/zlog.conf"
#define LOG_KEEP_DAYS 30 #define LOG_KEEP_DAYS 30
#define MAX_SIZE_MB 200 #define MAX_SIZE_MB 200
#define LOG_TIME_SYNC_WAIT_SEC 15
static zlog_category_t *s_zlog_c = NULL; static zlog_category_t *s_zlog_c = NULL;
static char s_log_file[256]; static char s_log_file[256];
...@@ -16,6 +17,64 @@ int logconf_create(); ...@@ -16,6 +17,64 @@ int logconf_create();
void check_and_delete_log(); void check_and_delete_log();
static int create_log_dir_if_not_exist(const char *path); static int create_log_dir_if_not_exist(const char *path);
static int network_time_is_synchronized(void)
{
FILE *fp;
char value[32] = {0};
fp = popen("timedatectl show -p NTPSynchronized --value 2>/dev/null", "r");
if (!fp)
return 0;
if (fgets(value, sizeof(value), fp) == NULL)
value[0] = '\0';
pclose(fp);
value[strcspn(value, "\r\n")] = '\0';
return strcmp(value, "yes") == 0;
}
/*
* 日志文件名包含日期,因此必须尽量在 NTP 校时后生成。
* 最多等待 15 秒;无网或校时服务异常时继续启动,不能永久阻塞设备。
*/
static void wait_for_network_time_before_log(void)
{
time_t initial_wall;
if (network_time_is_synchronized())
return;
fprintf(stderr, "[INFO] 日志初始化前等待网络时间同步,最多%d秒...\n",
LOG_TIME_SYNC_WAIT_SEC);
/* 兼容 systemd-timesyncd 与本项目镜像常用的 chrony。 */
(void)system("timedatectl set-ntp true >/dev/null 2>&1");
(void)system("chronyc -a online >/dev/null 2>&1");
(void)system("chronyc -a 'burst 4/4' >/dev/null 2>&1");
initial_wall = time(NULL);
for (int waited = 1; waited <= LOG_TIME_SYNC_WAIT_SEC; waited++) {
time_t now;
double expected_elapsed;
sleep(1);
if (waited == 3)
(void)system("chronyc -a makestep >/dev/null 2>&1");
if (network_time_is_synchronized()) {
fprintf(stderr, "[INFO] 网络时间已同步,开始创建日志文件。\n");
return;
}
now = time(NULL);
expected_elapsed = difftime(now, initial_wall);
if (expected_elapsed < waited - 5.0 || expected_elapsed > waited + 5.0) {
fprintf(stderr, "[INFO] 检测到系统时间已由网络校正,开始创建日志文件。\n");
return;
}
}
fprintf(stderr, "[WARN] 网络时间同步等待超时,将使用当前系统时间创建日志。\n");
}
static void generate_log_filename(void) static void generate_log_filename(void)
{ {
time_t now = time(NULL); time_t now = time(NULL);
...@@ -76,6 +135,7 @@ static void generate_config_content(void) ...@@ -76,6 +135,7 @@ static void generate_config_content(void)
int mylog_init() int mylog_init()
{ {
wait_for_network_time_before_log();
generate_log_filename(); generate_log_filename();
create_log_dir_if_not_exist(s_log_file); create_log_dir_if_not_exist(s_log_file);
......
...@@ -9,4 +9,4 @@ file perms = 600 ...@@ -9,4 +9,4 @@ file perms = 600
millisecond = "%d(%Y-%m-%d %H:%M:%S).%ms [%V] %m%n" millisecond = "%d(%Y-%m-%d %H:%M:%S).%ms [%V] %m%n"
[rules] [rules]
my_log.* "/home/orangepi/car/master/log/log_2026-07-20.log"; millisecond my_log.* "/home/orangepi/car/master/log/log_2026-07-28.log"; millisecond
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment