Commit 46276716 authored by minus's avatar minus

Add callbacks to MIDI actions

parent f97aceaa
#include <glib.h>
#include "panelcontrol.h"
#include "alsa.h"
struct button_map_entry {
enum button button;
button_callback_fn callback;
void *userdata;
};
struct encoder_map_entry {
enum encoder encoder;
encoder_callback_fn callback;
void *userdata;
};
struct button_callbacks {
size_t len;
struct button_map_entry *items;
} button_callbacks = {0};
struct encoder_callbacks {
size_t len;
struct encoder_map_entry *items;
} encoder_callbacks = {0};
void button_callback_add(enum button button, button_callback_fn cb, void *userdata) {
button_callbacks.len++;
button_callbacks.items = realloc(button_callbacks.items,
sizeof(struct button_map_entry) * button_callbacks.len);
struct button_map_entry *entry = &button_callbacks.items[button_callbacks.len - 1];
entry->button = button;
entry->callback = cb;
entry->userdata = userdata;
}
void encoder_callback_add(enum encoder encoder, encoder_callback_fn cb, void *userdata) {
encoder_callbacks.len++;
encoder_callbacks.items = realloc(encoder_callbacks.items,
sizeof(struct encoder_map_entry) * encoder_callbacks.len);
struct encoder_map_entry *entry = &encoder_callbacks.items[encoder_callbacks.len - 1];
entry->encoder = encoder;
entry->callback = cb;
entry->userdata = userdata;
}
void midi_button_led(snd_seq_t *seq, int port, enum button button, enum button_led_state state) {
snd_seq_event_t ev;
snd_seq_ev_clear(&ev);
snd_seq_ev_set_source(&ev, port);
snd_seq_ev_set_subs(&ev);
snd_seq_ev_set_direct(&ev);
snd_seq_ev_set_noteon(&ev, 0, button, state);
snd_seq_event_output_direct(seq, &ev);
}
static gboolean on_alsa_readable(GIOChannel *source, GIOCondition condition, gpointer data) {
fprintf(stdout, "source=%p cond=%i data=%p\n", (void *)source, condition, data);
snd_seq_t *seq = (snd_seq_t *)data;
......@@ -19,12 +71,21 @@ static gboolean on_alsa_readable(GIOChannel *source, GIOCondition condition, gpo
switch (ev->type) {
case SND_SEQ_EVENT_NOTEON:
fprintf(stdout, "button %i: %i\n", ev->data.note.note, ev->data.note.velocity > 0);
snd_seq_ev_set_subs(ev);
snd_seq_ev_set_direct(ev);
snd_seq_event_output_direct(seq, ev);
for (size_t i = 0; i < button_callbacks.len; i++) {
struct button_map_entry *entry = &button_callbacks.items[i];
if (entry->button == ev->data.note.note) {
entry->callback(ev->data.note.note, ev->data.note.velocity, entry->userdata);
}
}
break;
case SND_SEQ_EVENT_CONTROLLER:
fprintf(stdout, "knob %i: %i\n", ev->data.control.param, ev->data.control.value);
for (size_t i = 0; i < encoder_callbacks.len; i++) {
struct encoder_map_entry *entry = &encoder_callbacks.items[i];
if (entry->encoder == ev->data.control.param) {
entry->callback(ev->data.control.param, ev->data.control.value, entry->userdata);
}
}
break;
}
snd_seq_free_event(ev);
......@@ -33,8 +94,6 @@ static gboolean on_alsa_readable(GIOChannel *source, GIOCondition condition, gpo
return TRUE;
}
static int port;
void alsa(int source, snd_seq_t **seq_ret, int *port_ret) {
// connect to ALSA seq
snd_seq_t *seq;
......
#include <alsa/asoundlib.h>
#include "panelcontrol.h"
typedef void (*button_callback_fn)(enum button button, enum button_direction direction, void *userdata);
typedef void (*encoder_callback_fn)(enum encoder encoder, int delta, void *userdata);
void button_callback_add(enum button button, button_callback_fn cb, void *userdata);
void encoder_callback_add(enum encoder encoder, encoder_callback_fn cb, void *userdata);
void midi_button_led(snd_seq_t *seq, int port, enum button button, enum button_led_state state);
void alsa(int source, snd_seq_t **seq_ret, int *port_ret);
......@@ -77,9 +77,11 @@ static void xpa_on_connect(pa_context *ctx, void *userdata) {
// 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 | 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, &sink_inputs));
// initialize watched sinks/etc by listing all
// the order is important: sinks must be known before
// sink inputs so latter can access former in callbacks
pa_operation_unref(pa_context_get_sink_info_list(ctx, &xpa_on_sink_info, &sinks));
pa_operation_unref(pa_context_get_sink_input_info_list(ctx, &xpa_on_sink_input_info, &sink_inputs));
}
}
......
......@@ -8,53 +8,11 @@
#include "pa.h"
#include "pa_siso_watch_list.h"
//void toggle_mute(enum button button, void *userdata) {
// const char *name = (const char *)userdata;
// //xpa_sink_inputs_apply_by_name(name, &xpa_sink_input_set_volume, volume);
//}
//
//typedef void (*button_action_fn)(enum button, void *);
//
//struct button_map_entry {
// enum button button;
// button_action_fn action;
// void *userdata;
//};
//
//static const struct button_map_entry button_map[] = {
// {.button = TOP1, .sink_input = NULL, .action = &toggle_mute, .userdata = "mpd pulse"},
//};
//
//
//typedef void (*encoder_action_fn)(enum button, void *);
//
//struct encoder_map_entry {
// enum encoder encoder;
// encoder_action_fn action;
// void *userdata;
//}
//
//static const struct encoder_map_entry encoder_map[] = {
// {.encoder = ENC1, .sink_input = NULL, .action = &change_volume},
//};
struct seq_port {
snd_seq_t *seq;
int port;
};
void midi_button_led(snd_seq_t *seq, int port, enum button button, enum button_led_state state) {
snd_seq_event_t ev;
snd_seq_ev_clear(&ev);
snd_seq_ev_set_source(&ev, port);
snd_seq_ev_set_subs(&ev);
snd_seq_ev_set_direct(&ev);
snd_seq_ev_set_noteon(&ev, 0, button, state);
snd_seq_event_output_direct(seq, &ev);
}
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);
......@@ -64,6 +22,14 @@ void show_mute_and_speakers(struct siso_watch *w) {
midi_button_led(sp->seq, sp->port, BOTTOM1, w->target == speakers ? BUTTON_LED_ON : BUTTON_LED_OFF);
}
void button_test(enum button button, enum button_direction direction, void *userdata) {
fprintf(stdout, "button pressed: %i dir=%i\n", button, direction);
}
void encoder_test(enum encoder encoder, int delta, void *userdata) {
fprintf(stdout, "encoder turned: %i delta=%i\n", encoder, delta);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: %s CLIENT_ID\n", argv[0]);
......@@ -71,6 +37,9 @@ int main(int argc, char *argv[]) {
}
int source = atoi(argv[1]);
// keep track of speakers sink PA index
siso_add_name(&sinks, "speakers");
struct seq_port sp;
alsa(source, &sp.seq, &sp.port);
......@@ -78,8 +47,9 @@ int main(int argc, char *argv[]) {
mpd->userdata = &sp;
mpd->volume_changed = show_mute_and_speakers;
// keep track of speakers sink PA index
siso_add_name(&sinks, "speakers");
button_callback_add(TOP1, button_test, NULL);
encoder_callback_add(ENC1, encoder_test, NULL);
pa();
......
......@@ -29,6 +29,11 @@ enum button_led_state {
BUTTON_LED_OFF = 0,
};
enum button_direction {
BUTTON_DOWN = 127,
BUTTON_UP = 0,
};
enum encoder {
ENC1 = 16,
ENC2 = 17,
......
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