Skip to content

Instantly share code, notes, and snippets.

@grawity
Last active May 17, 2018 13:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grawity/419804f5dd5f418389312f4006dce0c2 to your computer and use it in GitHub Desktop.
Save grawity/419804f5dd5f418389312f4006dce0c2 to your computer and use it in GitHub Desktop.
PulseAudio 'System Events' volume knob
#if 0
pkg = libpulse
src = $(MAKEFILE_LIST)
app = $(basename $(src))
CFLAGS = $(shell pkg-config --cflags $(pkg)) -x c
LDFLAGS = $(shell pkg-config --libs $(pkg))
$(app): $(src)
define source
#endif
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <pulse/mainloop.h>
#include <pulse/ext-stream-restore.h>
#include <err.h>
void adjust_stream(pa_mainloop *loop, pa_context *ctx,
char *name, unsigned value, bool mute)
{
pa_volume_t vol;
pa_ext_stream_restore_info info;
pa_operation *o;
vol = (value * PA_VOLUME_NORM) / 100;
info = (pa_ext_stream_restore_info) {
.name = name,
.channel_map = {
.channels = 1,
.map = { PA_CHANNEL_POSITION_MONO },
},
.volume = {
.channels = 1,
.values = { mute ? PA_VOLUME_MUTED : vol },
},
.device = "",
.mute = mute,
};
//assert(pa_cvolume_compatible_with_channel_map(&info.volume, &info.channel_map));
o = pa_ext_stream_restore_write(ctx, PA_UPDATE_REPLACE, &info, 1,
true, NULL, NULL);
if (!o)
errx(1, "pa_ext_stream_restore_write failed");
pa_mainloop_iterate(loop, 1, NULL);
}
void try_connect(pa_mainloop *loop, pa_context *ctx) {
if (pa_context_connect(ctx, NULL, PA_CONTEXT_NOFAIL, NULL) < 0)
errx(1, "connection to PulseAudio failed");
for (;;) {
pa_mainloop_iterate(loop, 1, NULL);
switch (pa_context_get_state(ctx)) {
case PA_CONTEXT_READY:
return;
case PA_CONTEXT_FAILED:
errx(1, "handshake with PulseAudio failed");
return;
}
}
}
void pa_main(unsigned percent, bool muted) {
pa_mainloop *loop;
pa_context *ctx;
loop = pa_mainloop_new();
ctx = pa_context_new(pa_mainloop_get_api(loop), "knob");
try_connect(loop, ctx);
adjust_stream(loop, ctx, "sink-input-by-media-role:event", percent, muted);
pa_context_unref(ctx);
pa_mainloop_free(loop);
}
int main(int argc, char *argv[]) {
unsigned long percent = 0;
bool muted = false;
if (argc != 2)
errx(1, "missing volume level argument");
percent = strtoul(argv[1], NULL, 10);
pa_main(percent, muted);
return 0;
}
#if 0
endef
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment