/* * x1k2-midi-osc.c * * (c) 2023 Thomas White * * X1K2-midi-osc is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * X1K2-midi-osc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with X1K2-midi-osc. If not, see . * */ #include #include #include #include #include #include int fine_buttons[] = {52, 53, 54, 55, 13, 14}; int fine_vals[] = {0, 0, 0, 0, 0, 0}; int fine_encoders[] = {1, 2, 3, 4, 101, 102}; int num_fine = 6; int buttons[] = {48, 49, 50, 51, 44, 45, 46, 47, 40, 41, 42, 43, 36, 37, 38, 39, 32, 33, 34, 35, 28, 29, 30, 31, 24, 25, 26, 27, 12, 15}; int button_numbers[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 101, 102}; int num_buttons = 34; static void show_help(const char *s) { 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 MIDI device name.\n"); } 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 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); } struct led_callback_data { int red; int orange; int green; snd_rawmidi_t *midi_out; }; static int led_handler(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *vp) { struct led_callback_data *cb = vp; if ( strcmp("red", &argv[0]->s) == 0 ) { send_note_on(cb->midi_out, cb->red); } else if ( strcmp("orange", &argv[0]->s) == 0 ) { send_note_on(cb->midi_out, cb->orange); } else if ( strcmp("green", &argv[0]->s) == 0 ) { send_note_on(cb->midi_out, cb->green); } else if ( strcmp("off", &argv[0]->s) == 0 ) { /* Usually, turning off any one of the colours turns off the * LED, regardless of the current colour. However, the bottom * 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); } send_note_off(cb->midi_out, cb->red); } else { fprintf(stderr, "Unrecognised LED mode '%s'\n", &argv[0]->s); } return 1; } static void add_led(lo_server osc_server, snd_rawmidi_t *midi_out, int led, int red, int orange, int green) { char tmp[256]; struct led_callback_data *cb; cb = malloc(sizeof(struct led_callback_data)); if ( cb == NULL ) return; cb->midi_out = midi_out; cb->red = red; cb->orange = orange; cb->green = green; snprintf(tmp, 255, "/x1k2/leds/%i", led); lo_server_add_method(osc_server, tmp, "s", led_handler, cb); } static void handle_note_off(int note, int vel, lo_address osc_send_addr) { int i; for ( i=0; i 0 ); memmove(midi_buf, midi_buf+total_proc, 4096-total_proc); midi_buf_pos -= total_proc; } } } } while ( 1 ); snd_rawmidi_drain(midi_in); snd_rawmidi_close(midi_in); snd_rawmidi_drain(midi_out); snd_rawmidi_close(midi_out); return 0; }