Commit f97aceaa authored by minus's avatar minus

Make PA watches generic and use them for sinks

parent 982e8f97
project('panelcontrol', 'c',
version : '0.1',
default_options : ['warning_level=3', 'c_std=c11'])
add_global_arguments(['-Wno-unused'],
add_global_arguments(['-Wno-unused', '-D_POSIX_C_SOURCE=200809L'],
language: 'c')
pa = dependency('libpulse-mainloop-glib')
......@@ -9,7 +9,7 @@ alsa = dependency('alsa')
glib = dependency('glib-2.0')
executable('panelcontrol',
['panelcontrol.c', 'alsa.c', 'pa.c', 'pa_sink_input_watch_list.c'],
['panelcontrol.c', 'alsa.c', 'pa.c', 'pa_siso_watch_list.c'],
dependencies : [pa, alsa, glib],
install : true)
......
......@@ -4,10 +4,12 @@
#include "panelcontrol.h"
#include "pa.h"
#include "pa_sink_input_watch_list.h"
#include "pa_siso_watch_list.h"
static pa_glib_mainloop *xpa_main_loop;
struct siso_watch_list sink_inputs = {0};
struct siso_watch_list sinks = {0};
static void xpa_on_sink_input_info(pa_context *ctx,
const pa_sink_input_info *info, int eol, void *userdata) {
......@@ -15,10 +17,25 @@ static void xpa_on_sink_input_info(pa_context *ctx,
fprintf(stderr, "pa sink input: idx=%u name=%s volume=%u sink=%u mute=%i\n",
info->index, info->name, info->volume.values[0],
info->sink, info->mute);
struct sink_input_watch *w = sink_inputs_get(info->name);
struct siso_watch_list *wl = userdata;
struct siso_watch *w = siso_get(wl, info->name);
if (w) {
sink_input_watch_add_index(w, info->index);
sink_input_watch_update(w, info->sink, info->volume.values[0], info->mute != 0);
siso_watch_add_index(w, info->index);
siso_watch_update(w, info->sink, info->volume.values[0], info->mute != 0);
}
}
static void xpa_on_sink_info(pa_context *ctx,
const pa_sink_info *info, int eol, void *userdata) {
if (!info || info->volume.channels < 1) return;
fprintf(stderr, "pa sink: idx=%u name=%s volume=%u mute=%i\n",
info->index, info->name, info->volume.values[0],
info->mute);
struct siso_watch_list *wl = userdata;
struct siso_watch *w = siso_get(wl, info->name);
if (w) {
siso_watch_add_index(w, info->index);
siso_watch_update(w, -1, info->volume.values[0], info->mute != 0);
}
}
......@@ -26,28 +43,43 @@ static void xpa_on_subscribe(pa_context *ctx,
pa_subscription_event_type_t type, uint32_t idx, void *userdata) {
int etype = type & PA_SUBSCRIPTION_EVENT_TYPE_MASK;
const char *type_str = etype == PA_SUBSCRIPTION_EVENT_NEW ? "new" :
const char *event_str = etype == PA_SUBSCRIPTION_EVENT_NEW ? "new" :
etype == PA_SUBSCRIPTION_EVENT_CHANGE ? "changed" :
etype == PA_SUBSCRIPTION_EVENT_REMOVE ? "removed" : "???";
if (etype == PA_SUBSCRIPTION_EVENT_REMOVE) {
sink_inputs_remove_index(idx);
} else {
pa_operation *op = pa_context_get_sink_input_info(ctx, idx,
&xpa_on_sink_input_info, NULL);
pa_operation_unref(op);
const char *type_str = NULL;
struct siso_watch_list *wl = NULL;
pa_sink_info_cb_t cb = NULL;
if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
if (etype == PA_SUBSCRIPTION_EVENT_REMOVE) {
siso_remove_index(&sink_inputs, idx);
} else {
pa_operation *op = pa_context_get_sink_input_info(ctx, idx,
&xpa_on_sink_input_info, &sink_inputs);
pa_operation_unref(op);
}
} else if ((type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
if (etype == PA_SUBSCRIPTION_EVENT_REMOVE) {
siso_remove_index(&sinks, idx);
} else {
pa_operation *op = pa_context_get_sink_info_by_index(ctx, idx,
&xpa_on_sink_info, &sinks);
pa_operation_unref(op);
}
}
fprintf(stderr, "pa subscribe: idx=%u %s\n", idx, type_str);
fprintf(stderr, "pa subscribe: idx=%u %s %s\n", idx, type_str, event_str);
}
static void xpa_on_connect(pa_context *ctx, void *userdata) {
if (pa_context_get_state(ctx) == PA_CONTEXT_READY) {
// subscribe to PA sink input changes (volume, output, mute, new source)
pa_context_set_subscribe_callback(ctx, &xpa_on_subscribe, NULL);
pa_operation_unref(pa_context_subscribe(ctx, PA_SUBSCRIPTION_MASK_SINK_INPUT, NULL, NULL));
pa_operation_unref(pa_context_subscribe(ctx, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SINK_INPUT, NULL, NULL));
// initialize watched sink inputs by listing all
pa_operation_unref(pa_context_get_sink_input_info_list(ctx, &xpa_on_sink_input_info, NULL));
pa_operation_unref(pa_context_get_sink_input_info_list(ctx, &xpa_on_sink_input_info, &sink_inputs));
pa_operation_unref(pa_context_get_sink_info_list(ctx, &xpa_on_sink_info, &sinks));
}
}
......
extern struct siso_watch_list sink_inputs;
extern struct siso_watch_list sinks;
void pa();
#include <pulse/pulseaudio.h>
#include <stdbool.h>
struct sink_input_watch {
const char *name;
uint32_t sink;
pa_volume_t volume;
bool mute;
struct indices_list {
size_t len;
uint32_t *items;
} indices;
void (*volume_changed)(struct sink_input_watch *);
void *userdata;
};
void sink_input_watch_add_index(struct sink_input_watch *w, uint32_t pa_index);
void sink_input_watch_remove_index(struct sink_input_watch *w, uint32_t pa_index);
void sink_input_watch_update(struct sink_input_watch *w, uint32_t sink_index, pa_volume_t volume, bool mute);
struct sink_input_watch *sink_inputs_add_sink(const char* sink_name);
struct sink_input_watch *sink_inputs_get(const char *sink_name);
void sink_inputs_remove_index(uint32_t pa_index);
#include <string.h>
#include "pa_sink_input_watch_list.h"
#include "pa_siso_watch_list.h"
static struct sink_input_watch_list {
size_t len;
struct sink_input_watch *items;
} sink_inputs = {0};
void sink_input_watch_add_index(struct sink_input_watch *w, uint32_t pa_index) {
void siso_watch_add_index(struct siso_watch *w, uint32_t pa_index) {
for (size_t i = 0; i < w->indices.len;) {
if (w->indices.items[i] == pa_index) {
return;
......@@ -19,7 +14,7 @@ void sink_input_watch_add_index(struct sink_input_watch *w, uint32_t pa_index) {
w->indices.items[w->indices.len - 1] = pa_index;
}
void sink_input_watch_remove_index(struct sink_input_watch *w, uint32_t pa_index) {
void siso_watch_remove_index(struct siso_watch *w, uint32_t pa_index) {
if (w->indices.len == 0) return;
for (size_t i = 0; i < w->indices.len;) {
......@@ -35,8 +30,8 @@ void sink_input_watch_remove_index(struct sink_input_watch *w, uint32_t pa_index
}
}
void sink_input_watch_update(struct sink_input_watch *w, uint32_t sink_index, pa_volume_t volume, bool mute) {
w->sink = sink_index;
void siso_watch_update(struct siso_watch *w, uint32_t target_index, pa_volume_t volume, bool mute) {
w->target = target_index;
w->volume = volume;
w->mute = mute;
if (w->volume_changed) {
......@@ -44,13 +39,18 @@ void sink_input_watch_update(struct sink_input_watch *w, uint32_t sink_index, pa
}
}
struct sink_input_watch *sink_inputs_add_sink(const char* sink_name) {
sink_inputs.len++;
sink_inputs.items = realloc(sink_inputs.items,
sizeof(struct sink_input_watch) * sink_inputs.len);
struct sink_input_watch *item = &sink_inputs.items[sink_inputs.len - 1];
item->name = strdup(sink_name);
item->sink = -1;
uint32_t siso_watch_get_first_or_default(struct siso_watch *w, uint32_t default_) {
if (!w || w->indices.len == 0) return default_;
return w->indices.items[0];
}
struct siso_watch *siso_add_name(struct siso_watch_list *wl, const char* name) {
wl->len++;
wl->items = realloc(wl->items,
sizeof(struct siso_watch) * wl->len);
struct siso_watch *item = &wl->items[wl->len - 1];
item->name = strdup(name);
item->target = -1;
item->volume = PA_VOLUME_MUTED;
item->mute = true;
item->indices.len = 0;
......@@ -61,17 +61,17 @@ struct sink_input_watch *sink_inputs_add_sink(const char* sink_name) {
return item;
}
struct sink_input_watch *sink_inputs_get(const char *sink_name) {
for (size_t i = 0; i < sink_inputs.len; i++) {
if (strcmp(sink_inputs.items[i].name, sink_name) == 0) {
return &sink_inputs.items[i];
struct siso_watch *siso_get(struct siso_watch_list *wl, const char *name) {
for (size_t i = 0; i < wl->len; i++) {
if (strcmp(wl->items[i].name, name) == 0) {
return &wl->items[i];
}
}
return NULL;
}
void sink_inputs_remove_index(uint32_t pa_index) {
for (size_t i = 0; i < sink_inputs.len; i++) {
sink_input_watch_remove_index(&sink_inputs.items[i], pa_index);
void siso_remove_index(struct siso_watch_list *wl, uint32_t pa_index) {
for (size_t i = 0; i < wl->len; i++) {
siso_watch_remove_index(&wl->items[i], pa_index);
}
}
#include <pulse/pulseaudio.h>
#include <stdbool.h>
// siso (sink source) watch lists help keeping track of the indices of
// PulseAudio Sink/Source/Sink Input/Source Output indices by name.
struct siso_watch {
const char *name;
uint32_t target; // sink in case of watching a sink input
pa_volume_t volume;
bool mute;
struct indices_list {
size_t len;
uint32_t *items;
} indices;
void (*volume_changed)(struct siso_watch *);
void *userdata;
};
struct siso_watch_list {
size_t len;
struct siso_watch *items;
};
void siso_watch_add_index(struct siso_watch *w, uint32_t pa_index);
void siso_watch_remove_index(struct siso_watch *w, uint32_t pa_index);
void siso_watch_update(struct siso_watch *w, uint32_t target_index, pa_volume_t volume, bool mute);
uint32_t siso_watch_get_first_or_default(struct siso_watch *w, uint32_t default_);
struct siso_watch *siso_add_name(struct siso_watch_list *wl, const char* name);
struct siso_watch *siso_get(struct siso_watch_list *wl, const char *name);
void siso_remove_index(struct siso_watch_list *wl, uint32_t pa_index);
......@@ -6,7 +6,7 @@
#include "panelcontrol.h"
#include "alsa.h"
#include "pa.h"
#include "pa_sink_input_watch_list.h"
#include "pa_siso_watch_list.h"
//void toggle_mute(enum button button, void *userdata) {
......@@ -55,14 +55,13 @@ void midi_button_led(snd_seq_t *seq, int port, enum button button, enum button_l
snd_seq_event_output_direct(seq, &ev);
}
void show_mute_and_speakers(struct sink_input_watch *w) {
void show_mute_and_speakers(struct siso_watch *w) {
struct seq_port *sp = w->userdata;
midi_button_led(sp->seq, sp->port, TOP1, w->mute ? BUTTON_LED_ON : BUTTON_LED_OFF);
uint32_t speakers = 3;
uint32_t headphones = 4;
uint32_t speakers = siso_watch_get_first_or_default(siso_get(&sinks, "speakers"), -1);
midi_button_led(sp->seq, sp->port, BOTTOM1, w->sink == speakers ? BUTTON_LED_ON : BUTTON_LED_OFF);
midi_button_led(sp->seq, sp->port, BOTTOM1, w->target == speakers ? BUTTON_LED_ON : BUTTON_LED_OFF);
}
int main(int argc, char *argv[]) {
......@@ -75,10 +74,13 @@ int main(int argc, char *argv[]) {
struct seq_port sp;
alsa(source, &sp.seq, &sp.port);
struct sink_input_watch *mpd = sink_inputs_add_sink("mpd pulse");
struct siso_watch *mpd = siso_add_name(&sink_inputs, "mpd pulse");
mpd->userdata = &sp;
mpd->volume_changed = show_mute_and_speakers;
// keep track of speakers sink PA index
siso_add_name(&sinks, "speakers");
pa();
// create PA watch object for sink name "mpd pulse"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment