#include "pulse.h" #include "../signal.h" #include #include #include #include #include #include #include #include static void run_loop(struct pulse * p) { p->run_loop = true; while(p->run_loop && signal_running) { pa_mainloop_iterate(p->ml, 1, NULL); } } static void stop_loop(struct pulse * p) { p->run_loop = false; } static void server_info_cb(pa_context * ctx, const pa_server_info * info, void * ud) { struct pulse * p = (struct pulse *) ud; size_t s = strlen(info->default_sink_name); p->default_sink = malloc(s + 1); memset(p->default_sink, '\0', s + 1); strncpy(p->default_sink, info->default_sink_name, s); stop_loop(p); } static void state_cb(pa_context * ctx, void * ud) { pa_context_state_t state = pa_context_get_state(ctx); struct pulse * p = (struct pulse *) ud; switch(state) { case PA_CONTEXT_READY: pa_context_get_server_info(p->ctx, server_info_cb, p); break; case PA_CONTEXT_FAILED: case PA_CONTEXT_TERMINATED: stop_loop(p); break; default: break; } } struct pulse * pulse_new() { struct pulse * p = malloc(sizeof(struct pulse)); memset(p->value, '\0', PULSE_VALUE_SIZE); p->default_sink = NULL; p->run_loop = false; p->ml = pa_mainloop_new(); p->ctx = pa_context_new(pa_mainloop_get_api(p->ml), NULL); pa_context_set_state_callback(p->ctx, state_cb, p); pa_context_connect(p->ctx, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); run_loop(p); return p; } void pulse_free(struct pulse * p) { if(p->default_sink != NULL) free(p->default_sink); if(p->ctx->proplist) { pa_proplist_free(p->ctx->proplist); } pa_context_disconnect(p->ctx); pa_context_unref(p->ctx); pa_mainloop_free(p->ml); free(p); } static void sink_info_cb(pa_context * ctx, const pa_sink_info * info, int eol, void * ud) { struct pulse * p = (struct pulse *) ud; pa_volume_t vol, norm; if(eol > 0) { stop_loop(p); } else { if(info->mute) { strncpy(p->value, "M", PULSE_VALUE_SIZE); } else { vol = pa_cvolume_avg(&info->volume); vol -= PA_VOLUME_MUTED; norm = PA_VOLUME_NORM - PA_VOLUME_MUTED; vol = round((100.0f / norm) * vol); snprintf(p->value, PULSE_VALUE_SIZE, "%d%%", vol); } } } void pulse_update(struct pulse * p) { pa_operation * op; if(p->default_sink != NULL) { op = pa_context_get_sink_info_by_name(p->ctx, p->default_sink, sink_info_cb, p); pa_operation_unref(op); run_loop(p); } }