Source

lefty / src / lefty.c

Full commit
#include <stdio.h>

#include <jack/jack.h>
#include <jack/midiport.h>

jack_port_t *input_port;
jack_port_t *output_port;

/*
 * This value keeps the keyboard symmetrical around middle D.
 */
#define MAX_NOTE 124

static unsigned char reverse_note(unsigned char original) {
  if (original > MAX_NOTE) {
    return 0;
  }
  return (unsigned char) (MAX_NOTE - original);
}

/*
 * Callback function.
 */
static int process(jack_nframes_t nframes, void *arg) {
  void *in_port_buf = jack_port_get_buffer(input_port, nframes);
  void *out_port_buf = jack_port_get_buffer(output_port, nframes);
  jack_nframes_t event_count = jack_midi_get_event_count(in_port_buf);
  jack_midi_event_t evt;
  int i;

  if (event_count <= 0) {
    return 0;
  }
  jack_midi_clear_buffer(out_port_buf);

  for (i = 0; i != event_count; i++) {
    jack_midi_event_get(&evt, in_port_buf, i);
    unsigned char event_type = *(evt.buffer) & 0xf0;
    if (event_type == 0x90 || event_type == 0x80) {
      // Note on or note off.  Alter the pitch in place.
      evt.buffer[1] = reverse_note(evt.buffer[1]);
    }
    
    jack_midi_event_write(out_port_buf, evt.time, evt.buffer, evt.size);
  }
  return 0;
}


static void on_shutdown(void *arg) {
  exit(1);
}

int main(int argc, char **argv) {
  jack_client_t *client;

  if ((client = jack_client_open("lefty", JackNullOption, NULL)) == 0) {
    fprintf(stderr, "jack server not running?\n");
    return 1;
  }

  jack_set_process_callback(client, process, 0);
  jack_on_shutdown(client, on_shutdown, 0);
  input_port = jack_port_register(client, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
  output_port = jack_port_register(client, "midi_out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
  if (jack_activate(client)) {
    fprintf(stderr, "cannot activate client\n");
    return 1;
  }
  while(1) {
    sleep(1);
  }
  jack_client_close(client);
  return 0;
}