Werner's Miscellanea
Sign in or create your account | Project List | Help
Werner's Miscellanea Commit Details
Date: | 2011-11-27 14:56:40 (12 years 4 months ago) |
---|---|
Author: | Werner Almesberger |
Commit: | af0c0ab5c8fdf09df3b120a584e934c1f5614e0c |
Message: | midi2osc: added channel wildcard and overriding the value |
Files: |
midi2osc/README (2 diffs) midi2osc/midi2osc.c (9 diffs) |
Change Details
midi2osc/README | ||
---|---|---|
22 | 22 | |
23 | 23 | midi2osc can also remap MIDI controls. The syntax is |
24 | 24 | |
25 | c<chan>[.<control>]=c<chan>[.<control>] | |
25 | c[<chan>][.<control>]=c<chan>[.<control>[=<value>]] | |
26 | 26 | |
27 | 27 | where <chan> is a channel number and <control> is the optional control |
28 | 28 | number. For example, |
... | ... | |
32 | 32 | would map the joysticks and two faders of a Faderfox LV3 to the |
33 | 33 | controls 1 through 6 on channel 0, and send the OSC messages to |
34 | 34 | a host called "m1". |
35 | ||
36 | If <value> is given, that value will be assigned for any control | |
37 | message that matches the input pattern, irrespective of the input | |
38 | value. |
midi2osc/midi2osc.c | ||
---|---|---|
27 | 27 | static struct map { |
28 | 28 | int chan_in, ctrl_in; |
29 | 29 | int chan_out, ctrl_out; |
30 | int value; | |
30 | 31 | struct map *next; |
31 | 32 | } *mappings = NULL; |
32 | 33 | |
33 | 34 | |
34 | static void add(int chan_in, int ctrl_in, int chan_out, int ctrl_out) | |
35 | static void add(int chan_in, int ctrl_in, int chan_out, int ctrl_out, | |
36 | int value) | |
35 | 37 | { |
36 | 38 | struct map *new; |
37 | 39 | |
... | ... | |
40 | 42 | new->ctrl_in = ctrl_in; |
41 | 43 | new->chan_out = chan_out; |
42 | 44 | new->ctrl_out = ctrl_out; |
45 | new->value = value; | |
43 | 46 | new->next = mappings; |
44 | 47 | mappings = new; |
45 | 48 | } |
... | ... | |
47 | 50 | |
48 | 51 | static void add_mapping(const char *s) |
49 | 52 | { |
50 | unsigned chan_in, ctrl_in, chan_out, ctrl_out; | |
53 | unsigned chan_in, ctrl_in, chan_out, ctrl_out, value; | |
51 | 54 | |
52 | if (sscanf(s, "c%u.%u=c%u.%u", | |
55 | if (sscanf(s, "c%u.%u=c%u.%u=%u", | |
56 | &chan_in, &ctrl_in, &chan_out, &ctrl_out, &value) == 5) | |
57 | add(chan_in, ctrl_in, chan_out, ctrl_out, value); | |
58 | else if (sscanf(s, "c%u.%u=c%u.%u", | |
53 | 59 | &chan_in, &ctrl_in, &chan_out, &ctrl_out) == 4) |
54 | add(chan_in, ctrl_in, chan_out, ctrl_out); | |
60 | add(chan_in, ctrl_in, chan_out, ctrl_out, -1); | |
55 | 61 | 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); | |
62 | add(chan_in, ctrl_in, chan_out, -1, -1); | |
57 | 63 | 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); | |
64 | add(chan_in, -1, chan_out, ctrl_out, -1); | |
65 | else if (sscanf(s, "c.%u=c%u.%u", &ctrl_in, &chan_out, &ctrl_out) == 3) | |
66 | add(-1, ctrl_in, chan_out, ctrl_out, -1); | |
59 | 67 | else if (sscanf(s, "c%u=c%u", &chan_in, &chan_out) == 2) |
60 | add(chan_in, -1, chan_out, -1); | |
68 | add(chan_in, -1, chan_out, -1, -1); | |
61 | 69 | else { |
62 | 70 | fprintf(stderr, "unrecognized mapping syntax\n"); |
63 | 71 | exit(1); |
... | ... | |
65 | 73 | } |
66 | 74 | |
67 | 75 | |
68 | static void map(uint8_t *chan, uint8_t *ctrl) | |
76 | static void map(uint8_t *chan, uint8_t *ctrl, uint8_t *value) | |
69 | 77 | { |
70 | 78 | const struct map *m; |
71 | 79 | |
... | ... | |
76 | 84 | *chan = m->chan_out; |
77 | 85 | if (m->ctrl_out != -1) |
78 | 86 | *ctrl = m->ctrl_out; |
87 | if (m->value != -1) | |
88 | *value = m->value; | |
79 | 89 | return; |
80 | 90 | } |
81 | 91 | } |
... | ... | |
85 | 95 | { |
86 | 96 | snd_seq_event_t *ev; |
87 | 97 | uint8_t msg[4] = { 0, }; |
88 | uint8_t chan, ctrl; | |
98 | uint8_t chan, ctrl, value; | |
89 | 99 | |
90 | 100 | while (snd_seq_event_input(midi, &ev)) { |
91 | 101 | switch (ev->type) { |
... | ... | |
97 | 107 | case SND_SEQ_EVENT_CONTROLLER: |
98 | 108 | chan = ev->data.control.channel; |
99 | 109 | ctrl = ev->data.control.param; |
100 | map(&chan, &ctrl); | |
101 | msg[3] = ev->data.control.value; | |
110 | value = ev->data.control.value; | |
111 | map(&chan, &ctrl, &value); | |
102 | 112 | if (debug) |
103 | fprintf(stderr, "c%u.%u(%u) -> c%u.%u\n", | |
113 | fprintf(stderr, "c%u.%u=%u -> c%u.%u=%u\n", | |
104 | 114 | ev->data.control.channel, |
105 | ev->data.control.param, msg[3], | |
106 | chan, ctrl); | |
115 | ev->data.control.param, | |
116 | ev->data.control.value, | |
117 | chan, ctrl, value); | |
107 | 118 | msg[1] = 0xb0 | chan; |
108 | 119 | msg[2] = ctrl; |
120 | msg[3] = value; | |
109 | 121 | break; |
110 | 122 | case SND_SEQ_EVENT_PITCHBEND: |
111 | 123 | msg[1] = 0xe0 | ev->data.control.channel; |
... | ... | |
114 | 126 | break; |
115 | 127 | default: |
116 | 128 | /* Flickernoise currently doesn't support any others */ |
129 | if (debug) | |
130 | fprintf(stderr, "unrecognized MIDI event\n"); | |
117 | 131 | snd_seq_free_event(ev); |
118 | 132 | continue; |
119 | 133 | } |
... | ... | |
128 | 142 | { |
129 | 143 | fprintf(stderr, |
130 | 144 | "usage: %s hostname [-d] [mapping ...] [port]\n\n" |
131 | " mappings are of the form c<chan>[.<control>]=c<chan>[.<control>]\n\n" | |
145 | " mappings are of the form\n" | |
146 | " c[<chan>][.<control>]=c<chan>[.<control>[=<value>]]\n\n" | |
132 | 147 | " -d debug mode: print all MIDI messages\n", |
133 | 148 | name); |
134 | 149 | exit(1); |
Branches:
master