summaryrefslogtreecommitdiff
path: root/mixer.c
diff options
context:
space:
mode:
authorAndre Noll <maan@tuebingen.mpg.de>2026-10-26 22:03:22 +0100
committerAndre Noll <maan@tuebingen.mpg.de>2026-10-26 22:03:22 +0100
commitb4ad90d96ccdda29627f09fe0ee3cc3de716294b (patch)
tree46f26dd23ece106307a9ec862d5de488d967b756 /mixer.c
parent6a870fb2d464045cbc64d55e7c4bf1d88155063a (diff)
parented2248c9c56358e896965ad6310abe11bbdb309f (diff)
Merge topic branch t/mixer into pupu
para_mixer improvements ----------------------- Link para_mixer with audioc_common.o to make it single threaded. * t/mixer: Make para_mixer single-threaded. mixer: Introduce die(). crypt: use {con,de}structor to init/shutdown the library. client: Use a named enumeration for the client status. Introduce struct client_config to hide context from public API. mixer: Link with audioc_common.o Move recv_buffer() and recv_bin_buffer() from net.c to fd.c. mixer: Rename client_cmd() -> run_client_cmd(). mixer: Rename audioc_cmd() -> run_audioc_cmd().
Diffstat (limited to 'mixer.c')
-rw-r--r--mixer.c164
1 files changed, 88 insertions, 76 deletions
diff --git a/mixer.c b/mixer.c
index 7c11c640..81674130 100644
--- a/mixer.c
+++ b/mixer.c
@@ -24,11 +24,14 @@
#include "mixer.lsg.h"
#include "para.h"
+#include "audioc.h"
#include "lsu.h"
#include "fd.h"
#include "string.h"
#include "mix.h"
#include "error.h"
+#include "sideband.h"
+#include "client.h"
DEFINE_PARA_ERRLIST;
@@ -59,6 +62,12 @@ typedef int (*mixer_subcommand_handler_t)(const struct mixer *);
#define EXPORT_CMD(_cmd) const mixer_subcommand_handler_t \
lsg_mixer_com_ ## _cmd ## _user_data = &com_ ## _cmd;
+
+#define die(f,...) { \
+ para_log(LL_EMERG, "%s: " f, __func__, ## __VA_ARGS__); \
+ exit(EXIT_FAILURE); \
+ }
+
static int loglevel;
static __printf_2_3 void date_log(int ll, const char *fmt, ...)
{
@@ -202,80 +211,83 @@ static int com_fade(const struct mixer *m)
}
EXPORT_CMD(fade);
-static void run(const char *exe, const char *cmd)
+static void run_client_cmd_argv(int argc, char **argv)
{
- int ret, status, fds[3] = {0, 0, 0};
- pid_t pid;
- char *cmdline = make_message("%s %s", exe, cmd);
+ char *result = NULL;
+ int ret = client_run(argc, argv, &result);
- PARA_INFO_LOG("%s\n", cmdline);
- ret = xexec(&pid, cmdline, fds);
- free(cmdline);
- if (ret < 0) {
- PARA_ERROR_LOG("%s\n", para_strerror(-ret));
- goto fail;
- }
- do
- ret = waitpid(pid, &status, 0);
- while (ret == -1 && errno == EINTR);
- if (ret < 0) {
- PARA_ERROR_LOG("%s\n", strerror(errno));
- goto fail;
- }
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- goto fail;
- return;
-fail:
- PARA_EMERG_LOG("command \"%s\" failed\n", cmd);
- exit(EXIT_FAILURE);
+ PARA_INFO_LOG("cmd: %s\n", argv[0]);
+ if (ret < 0)
+ die("client_run(%s): %s\n", argv[0], para_strerror(-ret));
+ if (result && *result)
+ PARA_INFO_LOG("result: %s\n", result);
+ free(result);
}
-static char *get_status_item(const char *status_item_name)
+static void run_client_cmd(char *cmd)
{
- pid_t pid;
- int ret, fds[3] = {0, 1, 0};
- char *buf, *p, *item = NULL, *cmdline;
-
- cmdline = make_message("para_audioc -- stat --one-shot %s",
- status_item_name);
- ret = xexec(&pid, cmdline, fds);
- free(cmdline);
- if (ret < 0) {
- PARA_ERROR_LOG("%s\n", para_strerror(-ret));
- return para_strdup(NULL);
- }
- buf = alloc(100);
- ret = read(fds[1], buf, 99);
- if (ret < 0) {
- PARA_ERROR_LOG("%s\n", strerror(errno));
- goto free_buf;
+ char *argv[] = {cmd};
+ run_client_cmd_argv(1, argv);
+}
+
+static char *get_status_item(char *status_item_name)
+{
+ char *argv[] = {"stat", "--one-shot", status_item_name};
+ int argc = ARRAY_SIZE(argv), ret, fd;
+ char *p;
+ struct iovec iov;
+ struct sb_buffer sbb;
+ struct sb_context *ctx;
+
+ ret = connect_audiod(OPT_STRING_VAL(PARA_MIXER, SOCKET), argc, argv);
+ if (ret < 0)
+ die("connect_audiod stat %s: %s\n", status_item_name,
+ para_strerror(-ret));
+ fd = ret;
+ ctx = sb_new_recv(100, NULL, NULL);
+ for (;;) {
+ sb_get_recv_buffer(ctx, &iov);
+ ret = recv_bin_buffer(fd, iov.iov_base, iov.iov_len);
+ if (ret < 0)
+ die("recv_bin_buffer: %s\n", para_strerror(-ret));
+ if (ret == 0)
+ die("unexpected eof\n");
+ ret = sb_received(ctx, ret, &sbb);
+ if (ret < 0)
+ die("sb_received: %s\n", para_strerror(-ret));
+ if (ret > 0)
+ break;
}
- buf[ret] = '\0';
- p = strrchr(buf, '\n');
+
+ p = strrchr(sbb.iov.iov_base, '\n');
if (!p)
- goto free_buf;
+ goto parse_error;
*p = '\0';
- p = strchr(buf, ':');
+ p = strchr(sbb.iov.iov_base, ':');
if (!p || p[1] == '\0')
- goto free_buf;
- item = para_strdup(p + 2);
-free_buf:
- free(buf);
- close(fds[1]);
- do
- ret = waitpid(pid, NULL, 0);
- while (ret == -1 && errno == EINTR);
- return item? item : para_strdup(NULL);
+ goto parse_error;
+ p = para_strdup(p + 2);
+ free(sbb.iov.iov_base);
+ return p;
+parse_error:
+ die("parse error for item %s, buf=%s\n", status_item_name,
+ (char *)sbb.iov.iov_base);
}
-static void client_cmd(const char *cmd)
+static void run_audioc_cmd(const char *cmd)
{
- run("para_client", cmd);
-}
+ char **argv;
+ int argc, ret;
-static void audioc_cmd(const char *cmd)
-{
- run("para_audioc", cmd);
+ ret = create_argv(cmd, " ", &argv);
+ if (ret < 0)
+ die("create_argv %s: %s\n", cmd, para_strerror(-ret));
+ argc = ret;
+ ret = connect_audiod(OPT_STRING_VAL(PARA_MIXER, SOCKET), argc, argv);
+ free_argv(argv);
+ if (ret < 0)
+ die("connect_audiod %s: %s\n", cmd, para_strerror(-ret));
+ close(ret);
}
static int set_initial_volume(const struct mixer *m, struct mixer_handle *h)
@@ -321,7 +333,7 @@ static int change_mop(const char *mop, const struct mixer *m,
struct mixer_handle *h)
{
int ret;
- char *current_mop, *status, *cmd;
+ char *current_mop, *status;
static bool initial_volume_set, playing;
if (!mop || !*mop)
@@ -331,6 +343,7 @@ static int change_mop(const char *mop, const struct mixer *m,
PARA_INFO_LOG("afs_mode: %s, status: %s\n", current_mop, status);
playing = !strcmp(status, "playing");
if (strcmp(current_mop, mop)) {
+ char *argv[2] = {"select"};
if (playing) {
uint32_t old_vol;
ret = m->get(h);
@@ -340,19 +353,19 @@ static int change_mop(const char *mop, const struct mixer *m,
ret = fade(m, h, 0, 3, false);
if (ret < 0)
goto free_status;
- audioc_cmd("off");
- client_cmd("stop");
+ run_audioc_cmd("off");
+ run_client_cmd("stop");
playing = false;
- audioc_cmd("on");
+ run_audioc_cmd("on");
ret = m->set(h, old_vol);
if (ret < 0)
goto free_status;
} else if (!strcmp(status, "paused"))
- client_cmd("next");
+ run_client_cmd("next");
PARA_NOTICE_LOG("switching to %s\n", mop);
- cmd = make_message("select %s", mop);
- client_cmd(cmd);
- free(cmd);
+ argv[1] = para_strdup(mop);
+ run_client_cmd_argv(2, argv);
+ free(argv[1]);
}
if (!initial_volume_set) {
initial_volume_set = true;
@@ -361,7 +374,7 @@ static int change_mop(const char *mop, const struct mixer *m,
goto free_status;
}
if (!playing)
- client_cmd("play");
+ run_client_cmd("play");
ret = 1;
free_status:
free(status);
@@ -425,7 +438,7 @@ static int com_sleep(const struct mixer *m)
ret = change_mop(initial_mood, m, h);
if (ret < 0)
goto close_mixer;
- audioc_cmd("on");
+ run_audioc_cmd("on");
if (ret > 0) /* playing initial mood */
sleep(OPT_UINT32_VAL(SLEEP, INITIAL_DELAY));
ret = change_mop(fo_mood, m, h);
@@ -438,7 +451,7 @@ static int com_sleep(const struct mixer *m)
if (ret < 0)
goto close_mixer;
if (ret == 0) /* no sleep mood */
- client_cmd("stop");
+ run_client_cmd("stop");
time(&t1);
if (wake_time_epoch > t1 + fit)
sleep(wake_time_epoch - t1 - fit);
@@ -467,10 +480,10 @@ static int com_snooze(const struct mixer *m)
ret = fade(m, h, sovol, sotime, true);
if (ret < 0)
goto close_mixer;
- client_cmd("pause");
+ run_client_cmd("pause");
PARA_NOTICE_LOG("%" PRIu32 " seconds snooze time...\n", stime);
sleep(stime);
- client_cmd("play");
+ run_client_cmd("play");
ret = fade(m, h, sivol, sitime, true);
close_mixer:
m->close(h);
@@ -654,6 +667,5 @@ fail:
if (errctx)
PARA_ERROR_LOG("%s\n", errctx);
free(errctx);
- PARA_EMERG_LOG("%s\n", para_strerror(-ret));
- return EXIT_FAILURE;
+ die("%s\n", para_strerror(-ret));
}