Added dwmblocks-pulse-listener.c

This commit is contained in:
Alexander Rosenberg 2023-02-23 09:22:54 -08:00
parent 81dcef14c4
commit e18e6ac3a9
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730
5 changed files with 141 additions and 67 deletions

55
.gitignore vendored
View File

@ -1,56 +1,3 @@
# Custom blocks file
blocks.h
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
dwmblocks
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
dwmblocks-pulse-listener

View File

@ -2,32 +2,38 @@ PREFIX := /usr/local
CC := cc
CFLAGS := -pedantic -Wall -Wno-deprecated-declarations -Os
LDFLAGS := -lX11
PULSEFLAGS := -lpulse
# FreeBSD (uncomment)
#LDFLAGS += -L/usr/local/lib -I/usr/local/include
# # OpenBSD (uncomment)
#LDFLAGS += -L/usr/X11R6/lib -I/usr/X11R6/include
all: options dwmblocks
all: options dwmblocks dwmblocks-pulse-listener
options:
@echo dwmblocks build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "PULSEFLAGS = ${PULSEFLAGS}"
dwmblocks: dwmblocks.c blocks.def.h blocks.h
${CC} -o dwmblocks dwmblocks.c ${CFLAGS} ${LDFLAGS}
dwmblocks-pulse-listener: dwmblocks-pulse-listener.c
${CC} -o dwmblocks-pulse-listener dwmblocks-pulse-listener.c ${CFLAGS} ${PULSEFLAGS}
blocks.h:
cp blocks.def.h $@
clean:
rm -f *.o *.gch dwmblocks
rm -f *.o *.gch dwmblocks dwmblocks-pulse-listener
install: dwmblocks
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f dwmblocks ${DESTDIR}${PREFIX}/bin
cp -f dwmblocks-pulse-listener ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/dwmblocks
install -m0755 scripts/* ${DESTDIR}${PREFIX}/bin

View File

@ -4,7 +4,7 @@
static const Block blocks[] = {
/*Icon*/ /*Command*/ /*Update Interval*/ /*Update Signal*/
{"", "dwmblocks-battery", SECONDS(10), 0},
{"", "dwmblocks-volume", 125, 0},
{"", "dwmblocks-volume", 0, 1},
{"", "date +'%a %b %d'", SECONDS(30), 0},
{"", "date +'%R'", SECONDS(2), 0},
{"", "dwmblocks-network", SECONDS(5), 0},

121
dwmblocks-pulse-listener.c Normal file
View File

@ -0,0 +1,121 @@
#include <pulse/pulseaudio.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/signal.h>
#include <limits.h>
#define ERROR(...) fprintf(stderr, "error: " __VA_ARGS__)
typedef struct {
size_t pid;
unsigned int signum;
} TargetData;
static void sink_info_callback(pa_context *ctx, const pa_sink_info *info,
int eol, TargetData *target) {
if (info) {
kill(target->pid, target->signum);
}
}
static void server_info_callback(pa_context *ctx, const pa_server_info *info,
TargetData *target) {
pa_operation *op = pa_context_get_sink_info_by_name(
ctx,
info->default_sink_name,
(pa_sink_info_cb_t) sink_info_callback,
target);
pa_operation_unref(op);
}
static void subscribe_callback(pa_context *ctx,
pa_subscription_event_type_t type, uint32_t idx,
TargetData *target) {
unsigned int facility = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
pa_operation *op = NULL;
switch (facility) {
case PA_SUBSCRIPTION_EVENT_SINK:
op = pa_context_get_sink_info_by_index(ctx,
idx,
(pa_sink_info_cb_t) sink_info_callback,
target);
break;
}
if (op) {
pa_operation_unref(op);
}
}
static void state_callback(pa_context *ctx, TargetData *target) {
pa_operation *op;
switch (pa_context_get_state(ctx)) {
case PA_CONTEXT_READY:
op = pa_context_get_server_info(ctx,
(pa_server_info_cb_t) server_info_callback,
target);
pa_operation_unref(op);
pa_context_set_subscribe_callback(ctx,
(pa_context_subscribe_cb_t) subscribe_callback,
target);
op = pa_context_subscribe(ctx, PA_SUBSCRIPTION_MASK_SINK, NULL, NULL);
pa_operation_unref(op);
break;
case PA_CONTEXT_FAILED:
kill(target->pid, target->signum);
break;
default:
break;
}
}
int main(int argc, const char **argv) {
if (argc < 2) {
ERROR("no pid\n");
return 1;
}
char *endptr = NULL;
unsigned int signum = SIGRTMIN + 1;
if (argc >= 3 && argv[1][0] == '-') {
const char *signumstr = argv[1] + 1;
unsigned long num = strtoul(signumstr, &endptr, 10);
if (num > (SIGRTMAX - SIGRTMIN) + 1) {
ERROR("signal out of range: %lu\n", num);
return 1;
}
signum = SIGRTMIN + num;
++argv;
}
endptr = NULL;
errno = 0;
unsigned long pid = strtoul(argv[1], &endptr, 10);
if (argv[1][0] == '-' || errno == ERANGE) {
ERROR("pid out of range: \"%s\"\n", argv[1]);
return 1;
}
pa_mainloop *mainloop = pa_mainloop_new();
if (!mainloop) {
ERROR("could not create pulse mainloop\n");
return 1;
}
pa_mainloop_api *api = pa_mainloop_get_api(mainloop);
if (!api) {
ERROR("could not create pulse mainloop api\n");
return 1;
}
pa_context *context = pa_context_new(api, "dwmblocks-listener");
if (!context) {
ERROR("could not create pulse context\n");
return 1;
}
TargetData target = { pid, signum };
pa_context_set_state_callback( context,
(pa_context_notify_cb_t)&state_callback,
&target);
if (pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
ERROR("could not connect to pulse");
return 1;
}
pa_mainloop_run(mainloop, NULL);
return 0;
}

View File

@ -64,7 +64,7 @@ void getcmd(const Block *block, char *output) {
return;
}
int i = strlen(block->icon);
fgets(output+i, CMDLENGTH-i-delimLen, cmdf);
fgets(output + i, CMDLENGTH - i - delimLen, cmdf);
i = strlen(output);
if (i == 0) {
//return if block and command output are both empty
@ -72,9 +72,9 @@ void getcmd(const Block *block, char *output) {
return;
}
//only chop off newline if one is present at the end
i = output[i-1] == '\n' ? i-1 : i;
i = output[i - 1] == '\n' ? i - 1 : i;
if (delim[0] != '\0') {
strncpy(output+i, delim, delimLen);
strncpy(output + i, delim, delimLen);
} else {
output[i++] = '\0';
}
@ -83,7 +83,7 @@ void getcmd(const Block *block, char *output) {
void getcmds(int time) {
const Block* current;
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
for (unsigned int i = 0; i < LENGTH(blocks); ++i) {
current = blocks + i;
if ((current->interval != 0 && time % current->interval == 0) || time == -1) {
getcmd(current,statusbar[i]);
@ -93,7 +93,7 @@ void getcmds(int time) {
void getsigcmds(unsigned int signal) {
const Block *current;
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
for (unsigned int i = 0; i < LENGTH(blocks); ++i) {
current = blocks + i;
if (current->signal == signal) {
getcmd(current,statusbar[i]);
@ -116,14 +116,14 @@ void sighandler(int signum) {
void setupsignals() {
#ifndef __OpenBSD__
/* initialize all real time signals with dummy handler */
for (int i = SIGRTMIN; i <= SIGRTMAX; i++) {
for (int i = SIGRTMIN; i <= SIGRTMAX; ++i) {
signal(i, dummysighandler);
}
#endif
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
for (unsigned int i = 0; i < LENGTH(blocks); ++i) {
if (blocks[i].signal > 0) {
signal(SIGMINUS+blocks[i].signal, sighandler);
signal(SIGMINUS + blocks[i].signal, sighandler);
}
}
@ -132,7 +132,7 @@ void setupsignals() {
int getstatus(char *str, char *last) {
strcpy(last, str);
str[0] = '\0';
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
for (unsigned int i = 0; i < LENGTH(blocks); ++i) {
strcat(str, statusbar[i]);
}
str[strlen(str)-strlen(delim)] = '\0';
@ -160,7 +160,7 @@ int gcd(int n1, int n2) {
void statusloop() {
setupsignals();
unsigned int interval = -1;
for (int i = 0; i < LENGTH(blocks); i++){
for (int i = 0; i < LENGTH(blocks); ++i){
if (blocks[i].interval){
interval = gcd(blocks[i].interval, interval);
}