Date:2011-11-24 06:51:10 (7 years 9 months ago)
Author:Werner Almesberger
Commit:2d50444b1b1b66984839a46da533f46a4f4c67cb
Message:midi2osc: added channel and control number mapping

Files: midi2osc/README (1 diff)
midi2osc/midi2osc.c (5 diffs)

Change Details

midi2osc/README
1919- in the "Connections" window, drag a connection from each MIDI device
2020  you want to connect to midi2osc
2121- MIDI events will now show up in the MIDI settings dialog, etc.
22
23midi2osc can also remap MIDI controls. The syntax is
24
25c<chan>[.<control>]=c<chan>[.<control>]
26
27where <chan> is a channel number and <control> is the optional control
28number. For example,
29
30./midi2osc c8.1=c0.1 c8.2=c0.2 c9.1=c0.3 c9.2=c0.4 c0.7=c0.5 c7.7=c0.6 m1
31
32would map the joysticks and two faders of a Faderfox LV3 to the
33controls 1 through 6 on channel 0, and send the OSC messages to
34a host called "m1".
midi2osc/midi2osc.c
2424static int debug = 0;
2525
2626
27static struct map {
28    int chan_in, ctrl_in;
29    int chan_out, ctrl_out;
30    struct map *next;
31} *mappings = NULL;
32
33
34static void add(int chan_in, int ctrl_in, int chan_out, int ctrl_out)
35{
36    struct map *new;
37
38    new = malloc(sizeof(struct map));
39    new->chan_in = chan_in;
40    new->ctrl_in = ctrl_in;
41    new->chan_out = chan_out;
42    new->ctrl_out = ctrl_out;
43    new->next = mappings;
44    mappings = new;
45}
46
47
48static void add_mapping(const char *s)
49{
50    unsigned chan_in, ctrl_in, chan_out, ctrl_out;
51
52    if (sscanf(s, "c%u.%u=c%u.%u",
53        &chan_in, &ctrl_in, &chan_out, &ctrl_out) == 4)
54        add(chan_in, ctrl_in, chan_out, ctrl_out);
55    else if (sscanf(s, "c%u.%u=c%u", &chan_in, &ctrl_in, &chan_out) == 3)
56        add(chan_in, ctrl_in, chan_out, -1);
57    else if (sscanf(s, "c%u=c%u.%u", &chan_in, &chan_out, &ctrl_out) == 3)
58        add(chan_in, -1, chan_out, ctrl_out);
59    else if (sscanf(s, "c%u=c%u", &chan_in, &chan_out) == 2)
60        add(chan_in, -1, chan_out, -1);
61    else {
62        fprintf(stderr, "unrecognized mapping syntax\n");
63        exit(1);
64    }
65}
66
67
68static void map(uint8_t *chan, uint8_t *ctrl)
69{
70    const struct map *m;
71
72    for (m = mappings; m; m = m->next)
73        if ((m->chan_in == -1 || m->chan_in == *chan) &&
74            (m->ctrl_in == -1 || m->ctrl_in == *ctrl)) {
75            if (m->chan_out != -1)
76                *chan = m->chan_out;
77            if (m->ctrl_out != -1)
78                *ctrl = m->ctrl_out;
79            return;
80        }
81}
82
83
2784static void forward(snd_seq_t *midi, lo_address osc)
2885{
2986    snd_seq_event_t *ev;
3087    uint8_t msg[4] = { 0, };
88    uint8_t chan, ctrl;
3189
3290    while (snd_seq_event_input(midi, &ev)) {
3391        switch (ev->type) {
...... 
3795            msg[3] = ev->data.note.velocity;
3896            break;
3997        case SND_SEQ_EVENT_CONTROLLER:
40            msg[1] = 0xb0 | ev->data.control.channel;
41            msg[2] = ev->data.control.param;
98            chan = ev->data.control.channel;
99            ctrl = ev->data.control.param;
100            map(&chan, &ctrl);
42101            msg[3] = ev->data.control.value;
43102            if (debug)
44                fprintf(stderr, "CC(%u) %u %u\n",
45                    ev->data.control.channel, msg[2], msg[3]);
103                fprintf(stderr, "c%u.%u(%u) -> c%u.%u\n",
104                    ev->data.control.channel,
105                    ev->data.control.param, msg[3],
106                    chan, ctrl);
107            msg[1] = 0xb0 | chan;
108            msg[2] = ctrl;
46109            break;
47110        case SND_SEQ_EVENT_PITCHBEND:
48111            msg[1] = 0xe0 | ev->data.control.channel;
...... 
64127static void usage(const char *name)
65128{
66129    fprintf(stderr,
67"usage: %s hostname [-d] [port]\n\n"
130"usage: %s hostname [-d] [mapping ...] [port]\n\n"
131" mappings are of the form c<chan>[.<control>]=c<chan>[.<control>]\n\n"
68132" -d debug mode: print all MIDI messages\n",
69133    name);
70134    exit(1);
...... 
76140    const char *port = "4444"; /* Milkymist One OSC port */
77141    lo_address osc;
78142    snd_seq_t *midi;
79    int c;
80
143    int c, arg;
81144
82145    while ((c = getopt(argc, argv, "d")) != EOF)
83146        switch (c) {
...... 
88151            usage(*argv);
89152        }
90153
91    switch (argc-optind) {
154    for (arg = optind; arg != argc; arg++) {
155        if (!strchr(argv[arg], '='))
156            break;
157        add_mapping(argv[arg]);
158    }
159    switch (argc-arg) {
92160    case 1:
93161        break;
94162    case 2:
95        port = argv[optind+1];
163        port = argv[arg+1];
96164        break;
97165    default:
98166        usage(*argv);
99167    }
100168
101    osc = lo_address_new(argv[optind], port);
169    osc = lo_address_new(argv[arg], port);
102170    if (!osc) {
103        fprintf(stderr, "invalid address %s %s\n", argv[optind], port);
171        fprintf(stderr, "invalid address %s %s\n", argv[arg], port);
104172        exit(1);
105173    }
106174

Archive Download the corresponding diff file

Branches:
master



interactive