#include #include #include #include #include #include #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) < 0) { ERROR("terget process died\n"); exit(1); } } 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: if (kill(target->pid, target->signum) < 0) { ERROR("terget process died\n"); exit(1); } 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; }