commit c9b5e794e4a1455fe3ead85670b45c65e72fe873 from: Caleb Stein date: Sat May 30 10:37:05 2026 UTC move volume to its own process commit - 23a90cf95d6b733db64c1c4adb136018997a8fd1 commit + c9b5e794e4a1455fe3ead85670b45c65e72fe873 blob - 29ccceaafc5b3c6e989b5075ad1ed8015cf05366 blob + d88a1e429c79a4fe86b55d0d4e52d4e20b54f6c6 --- include/statbar.h +++ include/statbar.h @@ -3,6 +3,7 @@ #include #include +#include /* Glyphs */ #define MAIL "\ueb1c" @@ -19,6 +20,8 @@ #define WIFI "\uf1eb" #define ETHERNET "\uef09" +extern void close_display(void); + /* FS */ extern bool weather_loc_valid; extern bool mail_path_valid; @@ -42,12 +45,9 @@ extern void normalize_clock_interval(const struct time extern pid_t start_privileged_battery_process(int *pipe_fd, const struct timespec *timeout); /* Volume */ -extern char volume_string[11]; +#define VOLUME_STRING_SIZE 11 -extern bool init_volume(int *nfds); -extern void fill_sndio_pfds(struct pollfd *pfd); -extern void process_volume_events(struct pollfd *pfd, bool *hdl_open); -extern void close_volume(void); +extern pid_t start_volume_process(int *pipe_fd); /* CPU Temp */ extern char cputemp_string[14]; blob - 79d1a8a4d4213e3eceb6f2590ccf1ff3f90901df blob + 4f7843bb78a4141565fd3bba8b1d66807067d887 --- modules/volume.c +++ modules/volume.c @@ -1,94 +1,158 @@ +#include #include +#include #include #include +#include +#include #include #include "statbar.h" -char volume_string[11]; - static struct sioctl_hdl *hdl; +static volatile sig_atomic_t should_quit = 0; +static unsigned int ctl_addr = -1; -void +static void onval(void *arg, unsigned int addr, unsigned int val) { - char vglyph[5]; + char *vglyph; - (void)arg; - (void)addr; + if (ctl_addr != addr) return; if (val == 0) - (void)strcpy(vglyph, VOLMUTE); + vglyph = VOLMUTE; else if (val < 128) - (void)strcpy(vglyph, VOLLOW); + vglyph = VOLLOW; else - (void)strcpy(vglyph, VOL); + vglyph = VOL; - (void)snprintf(volume_string, 11, "%s %3d%%", vglyph, val * 100 / 255); + (void)dprintf(*(int *)arg, "%s %3d%%", vglyph, val * 100 / 255); } -void +static void ondesc(void *arg, struct sioctl_desc *desc, int val) { - static bool did_init = false; - char vglyph[5]; + char *vglyph; - (void)arg; - if (val == 0) - (void)strcpy(vglyph, VOLMUTE); + vglyph = VOLMUTE; else if (val < 128) - (void)strcpy(vglyph, VOLLOW); + vglyph = VOLLOW; else - (void)strcpy(vglyph, VOL); + vglyph = VOL; - if (!did_init && desc != NULL && strcmp(desc->func, "level") == 0) + if (ctl_addr == -1 && + desc != NULL && + strcmp(desc->func, "level") == 0 && + strcmp(desc->node0.name, "output") == 0) { - (void)snprintf(volume_string, 11, "%s %3d%%", vglyph, val * 100 / 255); - did_init = true; + (void)dprintf(*(int *)arg, "%s %3d%%", vglyph, val * 100 / 255); + ctl_addr = desc->addr; } } -bool -init_volume(int *nfds) +static int +init_volume(int *nfds, void *fd) { hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); if (hdl == NULL) { (void)puts("Could not open sndio"); - (void)strcpy(volume_string, UNKNOWN); - return false; + return -1; } - *nfds += sioctl_nfds(hdl); - (void)sioctl_ondesc(hdl, ondesc, NULL); - (void)sioctl_onval(hdl, onval, NULL); + *nfds = sioctl_nfds(hdl); + (void)sioctl_ondesc(hdl, ondesc, fd); + (void)sioctl_onval(hdl, onval, fd); return true; } -void -fill_sndio_pfds(struct pollfd *pfd) +static void +signal_handler(int sig) { - sioctl_pollfd(hdl, pfd, POLLIN); + if (sig == SIGTERM || sig == SIGINT) should_quit = 1; } -void -process_volume_events(struct pollfd *pfd, bool *hdl_open) +pid_t +start_volume_process(int *pipe_fd) { + pid_t pid; + int vol_pipe[2]; + int nfds; + struct pollfd *pfd; + + if (pipe(vol_pipe) == -1) + { + perror("pipe"); + + return -1; + } + *pipe_fd = vol_pipe[0]; + + pid = fork(); + if (pid) + { + if (pid == -1) (void)close(vol_pipe[0]); + (void)close(vol_pipe[1]); + + return pid; + } + + if (pledge("stdio inet unix rpath", NULL) == -1) + { + perror("pledge"); + (void)close(vol_pipe[0]); + (void)close(vol_pipe[1]); + + _exit(1); + } + if (init_volume(&nfds, &vol_pipe[1]) == -1) _exit(1); + (void)close(vol_pipe[0]); + (void)puts("Volume process started"); + + (void)signal(SIGTERM, signal_handler); + (void)signal(SIGINT, signal_handler); + + pfd = malloc(nfds * sizeof(struct pollfd)); + if (pfd == NULL) + { + perror("malloc"); + + _exit(1); + } + (void)sioctl_pollfd(hdl, pfd, POLLIN); + + if (pledge("stdio", NULL) == -1) + { + perror("pledge"); + free(pfd); + (void)close(vol_pipe[1]); + + _exit(1); + } + while(!should_quit) + { + if (poll(pfd, nfds, INFTIM) > 0) + { if (sioctl_revents(hdl, pfd) & POLLHUP) { (void)puts("Lost connection to sndio\n"); - sioctl_close(hdl); - *hdl_open = false; + + break; } -} + } -void -close_volume(void) -{ - sioctl_close(hdl); + if (getppid() == 1) break; + } + (void)puts("Closing volume process"); + (void)sioctl_close(hdl); + free(pfd); + (void)close(vol_pipe[1]); + + _exit(0); } blob - 780d00cd6185f0ea59de3b2b64c6eb90502fe37a blob + bb91908b4fbb21965cc9bcb2462655c446c8c6e0 --- src/main.c +++ src/main.c @@ -1,6 +1,5 @@ #include #include -#include #include #include @@ -18,6 +17,7 @@ #include "statbar.h" #define MAX_STATBAR_LEN 128 +#define NFDS 5 enum clocks_e { @@ -77,14 +77,11 @@ main(int argc, char *argv[]) char statbar_text[MAX_STATBAR_LEN]; bool dirty = true; int batt_fd; + int vol_fd; int weather_pipe[2]; pid_t batt_pid; + pid_t vol_pid; unsigned char cmd; - struct pollfd *cmd_pfd = NULL; - struct pollfd *batt_pfd = NULL; - struct pollfd *network_pfd = NULL; - struct pollfd *weather_pfd = NULL; - bool hdl_open = false; bool network_open = false; struct timespec now; struct timespec clocks[CLOCKS_COUNT]; @@ -95,24 +92,21 @@ main(int argc, char *argv[]) struct timespec cputemp_interval = { .tv_sec = 2 }; struct timespec fanspeed_interval = { .tv_sec = 3 }; struct timespec weather_interval = { .tv_sec = 1800 }; - struct pollfd *pfd; + struct pollfd pfd[NFDS]; + struct pollfd *cmd_pfd = &pfd[0]; + struct pollfd *batt_pfd = &pfd[1]; + struct pollfd *vol_pfd = &pfd[2]; + struct pollfd *network_pfd = &pfd[3]; + struct pollfd *weather_pfd = &pfd[4]; char battery_string[BATTERY_STRING_SIZE]; - int nfds = 2; /* Start with 2 to guarantee space for the network socket and cmd interface */ + char volume_string[VOLUME_STRING_SIZE]; int i; + ssize_t n; (void)setvbuf(stdout, NULL, _IOLBF, 0); - - display = XOpenDisplay(NULL); - if (display == NULL) - { - (void)puts("Failed to get display"); - - return 1; - } install_signal_handlers(); statbar_text[0] = '\0'; - root = DefaultRootWindow(display); (void)puts("Welcome to statbar"); /* Init components */ @@ -123,51 +117,51 @@ main(int argc, char *argv[]) timespecadd(&now, &cputemp_interval, &clocks[CPUTEMP_CLOCK]); timespecadd(&now, &fanspeed_interval, &clocks[FANSPEED_CLOCK]); timespecadd(&now, &weather_interval, &clocks[WEATHER_CLOCK]); - if (pipe(weather_pipe) != 0) - { - perror("pipe"); - weather_loc_valid = false; - } get_clock(); batt_pid = start_privileged_battery_process(&batt_fd, &battery_interval); - hdl_open = init_volume(&nfds); + vol_pid = start_volume_process(&vol_fd); get_cputemp(); get_fanspeed(); get_initial_network_state(); - if (weather_loc_valid) nfds++; - if (batt_pid > 0) nfds++; - pfd = malloc(nfds * sizeof(struct pollfd)); - if (pfd == NULL) + if (pipe(weather_pipe) != 0) { - perror("malloc"); - goto cleanup; + perror("pipe"); + weather_loc_valid = false; } - cmd_pfd = &pfd[nfds - 1]; + cmd_pfd->fd = open_command_interface(); cmd_pfd->events = POLLIN; - network_pfd = &pfd[nfds - 2]; - network_open = init_network_socket(&network_pfd->fd); - network_pfd->events = POLLIN; + if (batt_pid > 0) + { + batt_pfd->fd = batt_fd; + batt_pfd->events = POLLIN; + } + if (vol_pid > 0) + { + vol_pfd->fd = vol_fd; + vol_pfd->events = POLLIN; + } if (weather_loc_valid) { - weather_pfd = &pfd[nfds - 3]; weather_pfd->fd = weather_pipe[0]; weather_pfd->events = POLLIN; get_weather(weather_pipe[1]); } - if (batt_pid > 0) - { - batt_pfd = &pfd[nfds - (weather_loc_valid ? 4 : 3)]; - batt_pfd->fd = batt_fd; - batt_pfd->events = POLLIN; - } if (mail_path_valid) mail_path_valid = get_mail(); - fill_sndio_pfds(pfd); - if (pledge("stdio rpath cpath inet proc exec route audio", NULL) == -1) + display = XOpenDisplay(NULL); + if (display == NULL) { + (void)puts("Failed to get display"); + + return -1; + } + root = DefaultRootWindow(display); + + if (pledge("stdio rpath cpath inet proc exec route", NULL) == -1) + { perror("pledge"); goto cleanup; @@ -206,10 +200,8 @@ main(int argc, char *argv[]) timespecsub(next_event, &now, &next_interval); } - if (ppoll(pfd, nfds, &next_interval, NULL) > 0) + if (ppoll(pfd, NFDS, &next_interval, NULL) > 0) { - if (hdl_open) - process_volume_events(pfd, &hdl_open); if (cmd_pfd->revents & POLLIN) { (void)read(cmd_pfd->fd, &cmd, 1); @@ -235,7 +227,15 @@ main(int argc, char *argv[]) } } if (batt_pfd->revents & POLLIN) - (void)read(batt_pfd->fd, battery_string, BATTERY_STRING_SIZE); + { + n = read(batt_pfd->fd, battery_string, BATTERY_STRING_SIZE - 1); + if (n > 0) battery_string[n] = '\0'; + } + if (vol_pfd->revents & POLLIN) + { + n = read(vol_pfd->fd, volume_string, VOLUME_STRING_SIZE - 1); + if (n > 0) volume_string[n] = '\0'; + } if (network_pfd->revents & POLLIN) read_network_socket(network_pfd->fd); if (weather_pfd && (weather_pfd->revents & POLLIN)) @@ -298,7 +298,7 @@ main(int argc, char *argv[]) if (dirty) { - (void)snprintf(statbar_text, MAX_STATBAR_LEN, "%s%s| %s | %s | %s | %s | %s | %s", + (void)snprintf(statbar_text, MAX_STATBAR_LEN - 1, "%s%s| %s | %s | %s | %s | %s | %s", mail_string, network_string, weather_string, @@ -307,8 +307,8 @@ main(int argc, char *argv[]) volume_string, battery_string, clock_string); - XStoreName(display, root, statbar_text); - XFlush(display); + (void)XStoreName(display, root, statbar_text); + (void)XFlush(display); dirty = false; } } @@ -316,7 +316,7 @@ main(int argc, char *argv[]) cleanup: (void)puts("Closing statbar"); if (batt_pid > 0) (void)kill(batt_pid, SIGTERM); - if (hdl_open) close_volume(); + if (batt_pid > 0) (void)kill(vol_pid, SIGTERM); if (network_open) (void)close(network_pfd->fd); if (weather_loc_valid) close_weather(); if (mail_path_valid) close_mail(); @@ -328,7 +328,6 @@ cleanup: (void)close(weather_pipe[1]); } close_command_interface(); - free(pfd); return 0; }