123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- #include "pulse-listener.h"
- #include <pulse/pulseaudio.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <signal.h>
- #include <limits.h>
- #define ERROR(...) fprintf(stderr, "error: " __VA_ARGS__)
- #ifdef __OpenBSD__
- #define SIGMAX (SIGUSR2 - 1)
- #define SIGMIN (SIGUSR1 - 1)
- #else
- #define SIGMAX SIGRTMAX
- #define SIGMIN SIGRTMIN
- #endif
- static void sink_info_callback(pa_context *ctx, const pa_sink_info *info,
- int eol, pthread_t *main_thread) {
- pthread_kill(*main_thread, SIGMIN + 1);
- }
- static void server_info_callback(pa_context *ctx, const pa_server_info *info,
- pthread_t *main_thread) {
- pa_operation *op = pa_context_get_sink_info_by_name(
- ctx,
- info->default_sink_name,
- (pa_sink_info_cb_t) sink_info_callback,
- main_thread);
- pa_operation_unref(op);
- }
- static void subscribe_callback(pa_context *ctx,
- pa_subscription_event_type_t type, uint32_t idx,
- pthread_t *main_thread) {
- if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
- pa_operation *op = pa_context_get_sink_info_by_index(ctx,
- idx,
- (pa_sink_info_cb_t) sink_info_callback,
- main_thread);
- pa_operation_unref(op);
- }
- }
- static void state_callback(pa_context *ctx, pthread_t *main_thread) {
- 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,
- main_thread);
- pa_operation_unref(op);
- pa_context_set_subscribe_callback(ctx,
- (pa_context_subscribe_cb_t) subscribe_callback,
- main_thread);
- op = pa_context_subscribe(ctx, PA_SUBSCRIPTION_MASK_SINK, NULL, NULL);
- pa_operation_unref(op);
- break;
- case PA_CONTEXT_FAILED:
- pthread_kill(*main_thread, SIGMIN + 1);
- break;
- default:
- break;
- }
- }
- static void cleanup(void *data_to_free[2]) {
- pa_context_unref(data_to_free[1]);
- pa_mainloop_free(data_to_free[0]);
- }
- void pulse_listener_main(pthread_t *main_thread) {
- pthread_setcanceltype(PTHREAD_CANCEL_DISABLE, NULL);
- pa_mainloop *mainloop = pa_mainloop_new();
- if (!mainloop) {
- ERROR("could not create pulse mainloop\n");
- return;
- }
- pa_mainloop_api *api = pa_mainloop_get_api(mainloop);
- if (!api) {
- ERROR("could not create pulse mainloop api\n");
- return;
- }
- pa_context *context = pa_context_new(api, "dwmblocks-listener");
- if (!context) {
- ERROR("could not create pulse context\n");
- return;
- }
- pa_context_set_state_callback(context,
- (pa_context_notify_cb_t)&state_callback,
- main_thread);
- if (pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0) {
- ERROR("could not connect to pulse\n");
- return;
- }
- void *data_to_free[2] = { mainloop, context };
- pthread_cleanup_push((void(*)(void *)) cleanup, data_to_free);
- pthread_setcanceltype(PTHREAD_CANCEL_ENABLE, NULL);
- pa_mainloop_run(mainloop, NULL);
- pthread_cleanup_pop(1);
- }
|