summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2023-06-15 21:07:07 +0200
committerThomas White <taw@physics.org>2023-06-18 13:11:37 +0200
commit2d57ab93a1550226d33619ef4ec1c3684cc2372a (patch)
treea729d8319c75f233fd1f64557c3b9528aac96a88
parent2a5fd01abe66c89a0f74a1a6571619bfd6c49f7d (diff)
Implement high-level interface
-rw-r--r--x1k2-midi-osc.c412
1 files changed, 284 insertions, 128 deletions
diff --git a/x1k2-midi-osc.c b/x1k2-midi-osc.c
index e5809ab..535654b 100644
--- a/x1k2-midi-osc.c
+++ b/x1k2-midi-osc.c
@@ -35,6 +35,7 @@ struct faderpot
int physical_value;
int physical_value_known;
int enabled;
+ int congruent;
int pickup_value;
int has_button_and_led;
int button;
@@ -49,7 +50,6 @@ struct encoder
{
int id;
int cc_val;
- int enabled;
int fine_button;
int fine_active;
int has_led;
@@ -78,6 +78,38 @@ int n_encoders = 6;
int n_faders = 4;
int n_potentiometers = 12;
+snd_rawmidi_t *midi_out;
+
+
+static void send_note_on(snd_rawmidi_t *midi_out, int note)
+{
+ unsigned char sbuf[3];
+ ssize_t r;
+ sbuf[0] = 0x9e;
+ sbuf[1] = note;
+ sbuf[2] = 127;
+ r = snd_rawmidi_write(midi_out, sbuf, 3);
+ if ( r != 3 ) {
+ printf("snd_rawmidi_write said %li\n", r);
+ }
+ usleep(1000);
+}
+
+
+static void send_note_off(snd_rawmidi_t *midi_out, int note)
+{
+ unsigned char sbuf[3];
+ ssize_t r;
+ sbuf[0] = 0x8e;
+ sbuf[1] = note;
+ sbuf[2] = 0;
+ r = snd_rawmidi_write(midi_out, sbuf, 3);
+ if ( r != 3 ) {
+ printf("snd_rawmidi_write said %li\n", r);
+ }
+ usleep(1000);
+}
+
static void init_fader(struct faderpot *fad, int id, int cc_val)
{
@@ -87,7 +119,7 @@ static void init_fader(struct faderpot *fad, int id, int cc_val)
fad->physical_value_known = 0;
fad->pickup_value = 0;
fad->has_button_and_led = 0;
- fad->enabled = 0;
+ fad->enabled = 1;
fad->type = "faders";
}
@@ -100,6 +132,7 @@ static void init_potentiometer(struct faderpot *fad, int id, int cc_val,
fad->physical_value = 0;
fad->physical_value_known = 0;
fad->pickup_value = 0;
+ fad->congruent = 0;
fad->has_button_and_led = 1;
fad->button = button;
fad->led_red = button;
@@ -110,18 +143,128 @@ static void init_potentiometer(struct faderpot *fad, int id, int cc_val,
}
+static void faderpot_note_on(struct faderpot *fad)
+{
+ /* Ignored for now */
+}
+
+
+static void faderpot_note_off(struct faderpot *fad)
+{
+ /* Ignored for now */
+}
+
+
+static int in_range(int a, int val1, int val2)
+{
+ return ((a>=val1) && (a<=val2)) || ((a>=val2) && (a<=val1));
+}
+
+
+static void pot_set_led(struct faderpot *fad)
+{
+ if ( fad->has_button_and_led ) {
+ if ( fad->enabled ) {
+ if ( fad->congruent ) {
+ send_note_on(midi_out, fad->led_green);
+ } else {
+ send_note_on(midi_out, fad->led_orange);
+ }
+ } else {
+ send_note_off(midi_out, fad->led_green);
+ }
+ }
+}
+
+
+static void faderpot_cc(struct faderpot *fad, int val, lo_address osc_send_addr)
+{
+ if ( !fad->congruent ) {
+ int inr = in_range(fad->pickup_value, fad->physical_value, val);
+ if ( fad->physical_value_known && inr ) {
+ fad->congruent = 1;
+ }
+ }
+
+ if ( fad->enabled ) {
+
+ pot_set_led(fad);
+
+ if ( fad->congruent ) {
+ char tmp[64];
+ snprintf(tmp, 64, "/x1k2/%s/%i/value-change", fad->type, fad->id);
+ lo_send(osc_send_addr, tmp, "i", val);
+ printf("sending %s = %i\n", tmp, val);
+ }
+
+ }
+
+ fad->physical_value = val;
+ fad->physical_value_known = 1;
+}
+
+
+static int pot_set_pickup_handler(const char *path, const char *types,
+ lo_arg **argv, int argc,
+ lo_message msg, void *vp)
+{
+ struct faderpot *fad = vp;
+
+ fad->pickup_value = argv[0]->i;
+
+ if ( fad->physical_value_known
+ && (fad->pickup_value == fad->physical_value) )
+ {
+ fad->congruent = 1;
+ } else {
+ fad->congruent = 0;
+ }
+
+ pot_set_led(fad);
+
+ return 1;
+}
+
+
+static int pot_enable_handler(const char *path, const char *types,
+ lo_arg **argv, int argc,
+ lo_message msg, void *vp)
+{
+ struct faderpot *fad = vp;
+ fad->enabled = 1;
+ pot_set_led(fad);
+ return 1;
+}
+
+
+static int pot_disable_handler(const char *path, const char *types,
+ lo_arg **argv, int argc,
+ lo_message msg, void *vp)
+{
+ struct faderpot *fad = vp;
+
+ fad->enabled = 0;
+
+ if ( fad->has_button_and_led ) {
+ send_note_off(midi_out, fad->led_green);
+ }
+
+ return 1;
+}
+
+
static void add_faderpot_methods(struct faderpot *fad, lo_server osc_server)
{
char tmp[256];
- snprintf(tmp, 255, "/x1k2/%s/%i/set-pickup-value", fad->type, fad->id);
+ snprintf(tmp, 255, "/x1k2/%s/%i/set-pickup", fad->type, fad->id);
lo_server_add_method(osc_server, tmp, "i", pot_set_pickup_handler, fad);
snprintf(tmp, 255, "/x1k2/%s/%i/enable", fad->type, fad->id);
lo_server_add_method(osc_server, tmp, "", pot_enable_handler, fad);
snprintf(tmp, 255, "/x1k2/%s/%i/disable", fad->type, fad->id);
- lo_server_add_method(osc_server, tmp, "", pot_enable_handler, fad);
+ lo_server_add_method(osc_server, tmp, "", pot_disable_handler, fad);
}
@@ -150,105 +293,108 @@ static void init_encoder(struct encoder *enc, int id, int cc_val,
}
-static void add_encoder_methods(struct encoder *enc, lo_server osc_server)
+static int enc_set_led_handler(const char *path, const char *types,
+ lo_arg **argv, int argc,
+ lo_message msg, void *vp)
{
- char tmp[256];
- snprintf(tmp, 255, "/x1k2/encoders/%i/set-led", enc->id);
- lo_server_add_method(osc_server, tmp, "s", enc_set_led_handler, enc);
-}
+ struct encoder *enc = vp;
+ if ( strcmp("red", &argv[0]->s) == 0 ) {
+ send_note_on(midi_out, enc->led_red);
+ } else if ( strcmp("orange", &argv[0]->s) == 0 ) {
+ send_note_on(midi_out, enc->led_orange);
+ } else if ( strcmp("green", &argv[0]->s) == 0 ) {
+ send_note_on(midi_out, enc->led_green);
+ } else if ( strcmp("off", &argv[0]->s) == 0 ) {
+ send_note_off(midi_out, enc->led_red);
+ } else {
+ fprintf(stderr, "Unrecognised LED mode '%s'\n", &argv[0]->s);
+ }
+ return 1;
+}
-static void init_button_full(struct button *but, const char *name, int note,
- int r, int o, int g)
+static void encoder_note_on(struct encoder *enc)
{
- but->name = name;
- but->note = note;
- but->led_red = r;
- but->led_orange = o;
- but->led_green = g;
+ enc->fine_active = 1;
}
-static void init_button(struct button *but, const char *name, int note)
+static void encoder_note_off(struct encoder *enc)
{
- init_button_full(but, name, note, note, note+36, note+72);
+ enc->fine_active = 0;
}
-static void add_button_methods(struct button *but, lo_server osc_server)
+static void encoder_cc(struct encoder *enc, int val, lo_address osc_send_addr)
{
char tmp[256];
- snprintf(tmp, 255, "/x1k2/buttons/%s/set-led", but->name);
- lo_server_add_method(osc_server, tmp, "s", button_set_led_handler, but);
+ const char *v;
+
+ if ( val == 1 ) {
+ v = "inc";
+ } else if ( val == 127 ) {
+ v = "dec";
+ } else {
+ fprintf(stderr, "Invalid encoder value %i\n", val);
+ return;
+ }
+
+ snprintf(tmp, 255, "/x1k2/encoders/%i/%s%s",
+ enc->id, v, enc->fine_active ? "-fine" : "");
+ lo_send(osc_send_addr, tmp, "");
}
-static void show_help(const char *s)
+static void add_encoder_methods(struct encoder *enc, lo_server osc_server)
{
- printf("Syntax: %s [-h] [-d /dev/snd/midiXXXX]\n\n", s);
- printf("MIDI to OSC interface for A&H Xone:K2\n"
- "\n"
- " -h, --help Display this help message.\n"
- " -d, --device <dev> MIDI device name.\n");
+ char tmp[256];
+ snprintf(tmp, 255, "/x1k2/encoders/%i/set-led", enc->id);
+ lo_server_add_method(osc_server, tmp, "s", enc_set_led_handler, enc);
}
-static void error_callback(int num, const char *msg, const char *path)
+static void init_button_full(struct button *but, const char *name, int note,
+ int r, int o, int g)
{
- fprintf(stderr, "liblo error %i (%s) for path %s\n", num, msg, path);
+ but->name = name;
+ but->note = note;
+ but->led_red = r;
+ but->led_orange = o;
+ but->led_green = g;
}
-static void send_note_on(snd_rawmidi_t *midi_out, int note)
+static void init_button(struct button *but, const char *name, int note)
{
- unsigned char sbuf[3];
- ssize_t r;
- sbuf[0] = 0x9e;
- sbuf[1] = note;
- sbuf[2] = 127;
- r = snd_rawmidi_write(midi_out, sbuf, 3);
- if ( r != 3 ) {
- printf("snd_rawmidi_write said %li\n", r);
- }
- usleep(1000);
+ init_button_full(but, name, note, note, note+36, note+72);
}
-static void send_note_off(snd_rawmidi_t *midi_out, int note)
+static void button_note_off(struct button *but, lo_address osc_send_addr)
{
- unsigned char sbuf[3];
- ssize_t r;
- sbuf[0] = 0x8e;
- sbuf[1] = note;
- sbuf[2] = 0;
- r = snd_rawmidi_write(midi_out, sbuf, 3);
- if ( r != 3 ) {
- printf("snd_rawmidi_write said %li\n", r);
- }
- usleep(1000);
}
-struct led_callback_data
+static void button_note_on(struct button *but, lo_address osc_send_addr)
{
- int red;
- int orange;
- int green;
- snd_rawmidi_t *midi_out;
-};
+ char tmp[256];
+ snprintf(tmp, 255, "/x1k2/buttons/%s/press", but->name);
+ lo_send(osc_send_addr, tmp, "");
+}
-static int led_handler(const char *path, const char *types, lo_arg **argv,
- int argc, lo_message msg, void *vp)
+static int button_set_led_handler(const char *path, const char *types,
+ lo_arg **argv, int argc,
+ lo_message msg, void *vp)
{
- struct led_callback_data *cb = vp;
+ struct button *but = vp;
if ( strcmp("red", &argv[0]->s) == 0 ) {
- send_note_on(cb->midi_out, cb->red);
+ send_note_on(midi_out, but->led_red);
} else if ( strcmp("orange", &argv[0]->s) == 0 ) {
- send_note_on(cb->midi_out, cb->orange);
+ send_note_on(midi_out, but->led_orange);
} else if ( strcmp("green", &argv[0]->s) == 0 ) {
- send_note_on(cb->midi_out, cb->green);
+ send_note_on(midi_out, but->led_green);
} else if ( strcmp("off", &argv[0]->s) == 0 ) {
/* Usually, turning off any one of the colours turns off the
@@ -256,10 +402,10 @@ static int led_handler(const char *path, const char *types, lo_arg **argv,
* left button's LED is weird, I think because it's
* also the "layer" button. It can only be switched off
* from the same colour. So, we force it to be red. */
- if ( cb->red == 12 ) {
- send_note_on(cb->midi_out, cb->red);
+ if ( but->led_red == 12 ) {
+ send_note_on(midi_out, but->led_red);
}
- send_note_off(cb->midi_out, cb->red);
+ send_note_off(midi_out, but->led_red);
} else {
fprintf(stderr, "Unrecognised LED mode '%s'\n", &argv[0]->s);
}
@@ -268,103 +414,114 @@ static int led_handler(const char *path, const char *types, lo_arg **argv,
}
-static int pot_set_pickup_handler(const char *path, const char *types, lo_arg **argv,
- int argc, lo_message msg, void *vp)
+static void add_button_methods(struct button *but, lo_server osc_server)
{
- return 1;
+ char tmp[256];
+ snprintf(tmp, 255, "/x1k2/buttons/%s/set-led", but->name);
+ lo_server_add_method(osc_server, tmp, "s", button_set_led_handler, but);
}
-static void handle_note_off(int note, int vel, lo_address osc_send_addr)
+static void show_help(const char *s)
{
- int i;
+ printf("Syntax: %s [-h] [-d /dev/snd/midiXXXX]\n\n", s);
+ printf("MIDI to OSC interface for A&H Xone:K2\n"
+ "\n"
+ " -h, --help Display this help message.\n"
+ " -d, --device <dev> MIDI device name.\n");
+}
- for ( i=0; i<num_fine; i++ ) {
- if ( note == fine_buttons[i] ) {
- fine_vals[i] = 0;
- }
- }
+
+static void error_callback(int num, const char *msg, const char *path)
+{
+ fprintf(stderr, "liblo error %i (%s) for path %s\n", num, msg, path);
}
-static void handle_note(int note, int vel, lo_address osc_send_addr)
+static void handle_note_off(int note, int vel, lo_address osc_send_addr)
{
int i;
- for ( i=0; i<num_buttons; i++ ) {
- if ( note == buttons[i] ) {
- char tmp[256];
- snprintf(tmp, 255, "/x1k2/buttons/%i",
- button_numbers[i]);
- lo_send(osc_send_addr, tmp, "");
- printf("sending %s\n", tmp);
+ for ( i=0; i<n_potentiometers; i++ ) {
+ if ( note == potentiometers[i].button ) {
+ faderpot_note_off(&potentiometers[i]);
+ return;
}
}
- for ( i=0; i<num_fine; i++ ) {
- if ( note == fine_buttons[i] ) {
- fine_vals[i] = 1;
+ for ( i=0; i<n_encoders; i++ ) {
+ if ( note == encoders[i].fine_button ) {
+ encoder_note_off(&encoders[i]);
+ return;
}
}
+
+ for ( i=0; i<n_buttons; i++ ) {
+ if ( note == buttons[i].note ) {
+ button_note_off(&buttons[i], osc_send_addr);
+ return;
+ }
+ }
+
+ fprintf(stderr, "Unrecognised note %i\n", note);
}
-static void handle_encoder(int enc, int val, lo_address osc_send_addr)
+static void handle_note(int note, int vel, lo_address osc_send_addr)
{
- char tmp[32];
- const char *v;
int i;
- const char *fine = "";
- if ( val == 1 ) {
- v = "inc";
- } else if ( val == 127 ) {
- v = "dec";
- } else {
- fprintf(stderr, "Invalid encoder value %i\n", val);
- return;
+ for ( i=0; i<n_potentiometers; i++ ) {
+ if ( note == potentiometers[i].button ) {
+ faderpot_note_on(&potentiometers[i]);
+ return;
+ }
}
- for ( i=0; i<num_fine; i++ ) {
- if ( enc == fine_encoders[i] ) {
- if ( fine_vals[i] ) {
- fine = "-fine";
- }
+ for ( i=0; i<n_encoders; i++ ) {
+ if ( note == encoders[i].fine_button ) {
+ encoder_note_on(&encoders[i]);
+ return;
}
}
- snprintf(tmp, 32, "/x1k2/encoders/%i/%s%s", enc, v, fine);
- printf("sending %s\n", tmp);
- lo_send(osc_send_addr, tmp, "");
+ for ( i=0; i<n_buttons; i++ ) {
+ if ( note == buttons[i].note ) {
+ button_note_on(&buttons[i], osc_send_addr);
+ return;
+ }
+ }
+
+ fprintf(stderr, "Unrecognised note %i\n", note);
}
static void handle_cc(int cc, int val, lo_address osc_send_addr)
{
- char tmp[32];
- const char *type;
- int num;
+ int i;
- if ( cc < 4 ) {
- handle_encoder(cc+1, val, osc_send_addr);
- return;
- } else if ( cc<=15 ) {
- type = "potentiometers";
- num = cc+1;
- } else if ( cc<=19 ) {
- type = "faders";
- num = cc-15;
- } else if ( cc<=21 ) {
- handle_encoder(cc+81, val, osc_send_addr);
- return;
- } else {
- fprintf(stderr, "CC %i unrecognised!\n", cc);
- return;
+ for ( i=0; i<n_faders; i++ ) {
+ if ( cc == faders[i].cc_val ) {
+ faderpot_cc(&faders[i], val, osc_send_addr);
+ return;
+ }
+ }
+
+ for ( i=0; i<n_potentiometers; i++ ) {
+ if ( cc == potentiometers[i].cc_val ) {
+ faderpot_cc(&potentiometers[i], val, osc_send_addr);
+ return;
+ }
+ }
+
+ for ( i=0; i<n_encoders; i++ ) {
+ if ( cc == encoders[i].cc_val) {
+ encoder_cc(&encoders[i], val, osc_send_addr);
+ return;
+ }
}
- snprintf(tmp, 32, "/x1k2/%s/%i", type, num);
- printf("sending %s = %i\n", tmp, val);
- lo_send(osc_send_addr, tmp, "i", val);
+ fprintf(stderr, "Unrecognised CC %i\n", cc);
}
@@ -409,7 +566,6 @@ int main(int argc, char *argv[])
int c, r, i;
char *dev = NULL;
snd_rawmidi_t *midi_in;
- snd_rawmidi_t *midi_out;
lo_server osc_server;
lo_address osc_send_addr;
int lo_fd;