From 67a34e769313bf7851c0710b6ed7486444453316 Mon Sep 17 00:00:00 2001 From: Albert Graef Date: Wed, 29 Aug 2018 14:52:20 +0200 Subject: [PATCH] Add a transposition flags for swapping offset and value in mod translations. --- midizap.c | 86 +++++++++++++++-------------- midizap.h | 3 ++ readconfig.c | 150 ++++++++++++++++++++++++++++----------------------- 3 files changed, 133 insertions(+), 106 deletions(-) diff --git a/midizap.c b/midizap.c index e71ce23..4534216 100644 --- a/midizap.c +++ b/midizap.c @@ -99,7 +99,8 @@ void send_midi(uint8_t portno, int status, int data, int step, int n_steps, int *steps, int incr, int index, int dir, - int mod, int mod_step, int mod_n_steps, int *mod_steps, int val, + int mod, int mod_step, int mod_n_steps, int *mod_steps, + int val, int swap, int recursive, int depth) { if (!jack_num_outputs) return; // MIDI output not enabled @@ -125,8 +126,9 @@ send_midi(uint8_t portno, int status, int data, } msg[2] = notevalue[chan][data]; } else if (mod) { - int d = msg[1] + datavals(val/mod, mod_step, mod_steps, mod_n_steps); - int v = datavals(val%mod, step, steps, n_steps); + int q = swap?val%mod:val/mod, r = swap?val/mod:val%mod; + int d = msg[1] + datavals(q, mod_step, mod_steps, mod_n_steps); + int v = datavals(r, step, steps, n_steps); if (d > 127 || d < 0) return; if (v > 127 || v < 0) return; msg[1] = d; @@ -163,8 +165,9 @@ send_midi(uint8_t portno, int status, int data, msg[2] = ccvalue[chan][data]; } } else if (mod) { - int d = msg[1] + datavals(val/mod, mod_step, mod_steps, mod_n_steps); - int v = datavals(val%mod, step, steps, n_steps); + int q = swap?val%mod:val/mod, r = swap?val/mod:val%mod; + int d = msg[1] + datavals(q, mod_step, mod_steps, mod_n_steps); + int v = datavals(r, step, steps, n_steps); if (d > 127 || d < 0) return; if (v > 127 || v < 0) return; msg[1] = d; @@ -192,8 +195,9 @@ send_midi(uint8_t portno, int status, int data, } msg[2] = kpvalue[chan][data]; } else if (mod) { - int d = msg[1] + datavals(val/mod, mod_step, mod_steps, mod_n_steps); - int v = datavals(val%mod, step, steps, n_steps); + int q = swap?val%mod:val/mod, r = swap?val/mod:val%mod; + int d = msg[1] + datavals(q, mod_step, mod_steps, mod_n_steps); + int v = datavals(r, step, steps, n_steps); if (d > 127 || d < 0) return; if (v > 127 || v < 0) return; msg[1] = d; @@ -221,7 +225,7 @@ send_midi(uint8_t portno, int status, int data, } msg[1] = cpvalue[chan]; } else if (mod) { - int v = datavals(val%mod, step, steps, n_steps); + int v = datavals(swap?val%mod:val/mod, step, steps, n_steps); if (v > 127 || v < 0) return; msg[1] = v; } else if (!index) { @@ -248,7 +252,7 @@ send_midi(uint8_t portno, int status, int data, } pbval = pbvalue[chan]; } else if (mod) { - int v = datavals(val%mod, step, steps, n_steps); + int v = datavals(swap?val%mod:val/mod, step, steps, n_steps); if (v > 8191 || v < -8192) return; pbval = 8192+v; } else if (!index) { @@ -266,7 +270,7 @@ send_midi(uint8_t portno, int status, int data, } case 0xc0: if (mod) { - int d = msg[1] + datavals(val/mod, mod_step, mod_steps, mod_n_steps); + int d = msg[1] + datavals(swap?val/mod:val%mod, mod_step, mod_steps, mod_n_steps); if (d > 127 || d < 0) return; msg[1] = d; } @@ -344,7 +348,8 @@ static stroke *find_note(translation *tr, int shift, static stroke *find_notes(translation *tr, int shift, int chan, int data, int index, int *step) { - return find_stroke_data(tr->notes[shift], chan, data, index, step, 0, 0, 0, 0, + return find_stroke_data(tr->notes[shift], chan, data, index, step, + 0, 0, 0, 0, tr->n_notes[shift]); } @@ -384,7 +389,8 @@ static stroke *find_kp(translation *tr, int shift, static stroke *find_kps(translation *tr, int shift, int chan, int data, int index, int *step) { - return find_stroke_data(tr->kps[shift], chan, data, index, step, 0, 0, 0, 0, + return find_stroke_data(tr->kps[shift], chan, data, index, step, + 0, 0, 0, 0, tr->n_kps[shift]); } @@ -400,7 +406,8 @@ static stroke *find_cp(translation *tr, int shift, static stroke *find_cps(translation *tr, int shift, int chan, int index, int *step) { - return find_stroke_data(tr->cps[shift], chan, 0, index, step, 0, 0, 0, 0, + return find_stroke_data(tr->cps[shift], chan, 0, index, step, + 0, 0, 0, 0, tr->n_cps[shift]); } @@ -524,27 +531,27 @@ static char *debug_key(translation *tr, char *name, } else (void)find_note(tr, shift, chan, data, 0, &mod, &step, &n_steps, &steps); } - if (!dir) - suffix = ""; - else + if (dir) suffix = (dir<0)?"-":"+"; + else + suffix = ""; if (dir && step != 1) sprintf(name, "%s%s%d[%d]-%d%s", prefix, note_name(data), note_octave(data), step, chan+1, suffix); else if (!dir && mod) if (step != 1) - sprintf(name, "%s%s%d[%d][%d]-%d", prefix, note_name(data), - note_octave(data), mod, step, chan+1); + sprintf(name, "%s%s%d[%d][%d]-%d%s", prefix, note_name(data), + note_octave(data), mod, step, chan+1, suffix); else if (n_steps) { sprintf(name, "%s%s%d[%d][", prefix, note_name(data), note_octave(data), mod); int l = strlen(name); for (int i = 0; i < n_steps; i++, (l = strlen(name))) sprintf(name+l, "%s%d", i?",":"", steps[i]); - sprintf(name+l, "]-%d", chan); + sprintf(name+l, "]-%d%s", chan+1, suffix); } else - sprintf(name, "%s%s%d[%d]-%d", prefix, note_name(data), - note_octave(data), mod, chan+1); + sprintf(name, "%s%s%d[%d]-%d%s", prefix, note_name(data), + note_octave(data), mod, chan+1, suffix); else sprintf(name, "%s%s%d-%d%s", prefix, note_name(data), note_octave(data), chan+1, suffix); @@ -559,27 +566,27 @@ static char *debug_key(translation *tr, char *name, } else (void)find_kp(tr, shift, chan, data, 0, &mod, &step, &n_steps, &steps); } - if (!dir) - suffix = ""; - else + if (dir) suffix = (dir<0)?"-":"+"; + else + suffix = ""; if (dir && step != 1) sprintf(name, "%sKP:%s%d[%d]-%d%s", prefix, note_name(data), note_octave(data), step, chan+1, suffix); else if (!dir && mod) if (step != 1) - sprintf(name, "%sKP:%s%d[%d][%d]-%d", prefix, note_name(data), - note_octave(data), mod, step, chan+1); + sprintf(name, "%sKP:%s%d[%d][%d]-%d%s", prefix, note_name(data), + note_octave(data), mod, step, chan+1, suffix); else if (n_steps) { sprintf(name, "%sKP:%s%d[%d][", prefix, note_name(data), note_octave(data), mod); int l = strlen(name); for (int i = 0; i < n_steps; i++, (l = strlen(name))) sprintf(name+l, "%s%d", i?",":"", steps[i]); - sprintf(name+l, "]-%d", chan); + sprintf(name+l, "]-%d%s", chan+1, suffix); } else - sprintf(name, "%sKP:%s%d[%d]-%d", prefix, note_name(data), - note_octave(data), mod, chan+1); + sprintf(name, "%sKP:%s%d[%d]-%d%s", prefix, note_name(data), + note_octave(data), mod, chan+1, suffix); else sprintf(name, "%sKP:%s%d-%d%s", prefix, note_name(data), note_octave(data), chan+1, suffix); @@ -594,25 +601,25 @@ static char *debug_key(translation *tr, char *name, } else (void)find_cc(tr, shift, chan, data, 0, &mod, &step, &n_steps, &steps); } - if (!dir) - suffix = ""; - else if (is_incr) + if (is_incr) suffix = (dir<0)?"<":">"; - else + else if (dir) suffix = (dir<0)?"-":"+"; + else + suffix = ""; if (dir && step != 1) sprintf(name, "%sCC%d[%d]-%d%s", prefix, data, step, chan+1, suffix); else if (!dir && mod) if (step != 1) - sprintf(name, "%sCC%d[%d][%d]-%d", prefix, data, mod, step, chan+1); + sprintf(name, "%sCC%d[%d][%d]-%d%s", prefix, data, mod, step, chan+1, suffix); else if (n_steps) { sprintf(name, "%sCC%d[%d][", prefix, data, mod); int l = strlen(name); for (int i = 0; i < n_steps; i++, (l = strlen(name))) sprintf(name+l, "%s%d", i?",":"", steps[i]); - sprintf(name+l, "]-%d", chan); + sprintf(name+l, "]-%d%s", chan+1, suffix); } else - sprintf(name, "%sCC%d[%d]-%d", prefix, data, mod, chan+1); + sprintf(name, "%sCC%d[%d]-%d%s", prefix, data, mod, chan+1, suffix); else sprintf(name, "%sCC%d-%d%s", prefix, data, chan+1, suffix); break; @@ -787,10 +794,11 @@ send_strokes(translation *tr, uint8_t portno, int status, int chan, else fprintf(stderr, "Error: $%s: recursion too deep\n", debug_key(tr, name, status, chan, data, dir)); - } else + } else { send_midi(portno, s->status, s->data, s->step, s->n_steps, s->steps, - s->incr, index, dir, - mod, step, n_steps, steps, data2, s->recursive, depth); + s->incr, index, dir, mod, + step, n_steps, steps, data2, s->swap, s->recursive, depth); + } } s = s->next; } diff --git a/midizap.h b/midizap.h index 19d38f5..4b2f3dc 100644 --- a/midizap.h +++ b/midizap.h @@ -59,6 +59,9 @@ typedef struct _stroke { // the incremental bit indicates an incremental control change (typically // used with endless rotary encoders) to be represented as a sign bit value uint8_t incr; + // the swap bit indicates that 1st and 2nd data byte are to be swapped in + // mod translations + uint8_t swap; // the recursive bit indicates a MIDI message which is to be translated // recursively uint8_t recursive; diff --git a/readconfig.c b/readconfig.c index 8d4ad26..1aa69a3 100644 --- a/readconfig.c +++ b/readconfig.c @@ -629,91 +629,99 @@ print_stroke(stroke *s, int mod, int step, int n_steps, int *steps, int val) } else { int status = s->status & 0xf0; int channel = (s->status & 0x0f) + 1; + char *suffix = s->swap?"'":s->incr?"~":""; if (s->recursive) printf("$"); switch (status) { case 0x90: if (mod) { - int d = s->data + datavals(val/mod, step, steps, n_steps); - int v = datavals(val%mod, s->step, s->steps, s->n_steps); - printf("%s%d[%d]-%d ", note_name(d), - note_octave(d), v, channel); + int q = s->swap?val%mod:val/mod, r = s->swap?val/mod:val%mod; + int d = s->data + datavals(q, step, steps, n_steps); + int v = datavals(r, s->step, s->steps, s->n_steps); + printf("%s%d[%d]-%d%s ", note_name(d), + note_octave(d), v, channel, suffix); } else if (s->steps) { printf("%s%d[", note_name(s->data), note_octave(s->data)); for (int i = 0; i < s->n_steps; i++) printf("%s%d", i?",":"", s->steps[i]); - printf("]-%d ", channel); + printf("]-%d%s ", channel, suffix); } else if (s->step) - printf("%s%d[%d]-%d ", note_name(s->data), - note_octave(s->data), s->step, channel); + printf("%s%d[%d]-%d%s ", note_name(s->data), + note_octave(s->data), s->step, channel, suffix); else - printf("%s%d-%d ", note_name(s->data), - note_octave(s->data), channel); + printf("%s%d-%d%s ", note_name(s->data), + note_octave(s->data), channel, suffix); break; case 0xa0: if (mod) { - int d = s->data + datavals(val/mod, step, steps, n_steps); - int v = datavals(val%mod, s->step, s->steps, s->n_steps); - printf("KP:%s%d[%d]-%d ", note_name(d), - note_octave(d), v, channel); + int q = s->swap?val%mod:val/mod, r = s->swap?val/mod:val%mod; + int d = s->data + datavals(q, step, steps, n_steps); + int v = datavals(r, s->step, s->steps, s->n_steps); + printf("KP:%s%d[%d]-%d%s ", note_name(d), + note_octave(d), v, channel, suffix); } else if (s->steps) { printf("KP:%s%d[", note_name(s->data), note_octave(s->data)); for (int i = 0; i < s->n_steps; i++) printf("%s%d", i?",":"", s->steps[i]); - printf("]-%d ", channel); + printf("]-%d%s ", channel, suffix); } else if (s->step) - printf("KP:%s%d[%d]-%d ", note_name(s->data), - note_octave(s->data), s->step, channel); + printf("KP:%s%d[%d]-%d%s ", note_name(s->data), + note_octave(s->data), s->step, channel, suffix); else - printf("KP:%s%d-%d ", note_name(s->data), - note_octave(s->data), channel); + printf("KP:%s%d-%d%s ", note_name(s->data), + note_octave(s->data), channel, suffix); break; case 0xb0: if (mod) { - int d = s->data + datavals(val/mod, step, steps, n_steps); - int v = datavals(val%mod, s->step, s->steps, s->n_steps); - printf("CC%d[%d]-%d ", d, v, channel); + int q = s->swap?val%mod:val/mod, r = s->swap?val/mod:val%mod; + int d = s->data + datavals(q, step, steps, n_steps); + int v = datavals(r, s->step, s->steps, s->n_steps); + printf("CC%d[%d]-%d%s ", d, v, channel, suffix); } else if (s->steps) { printf("CC%d[", s->data); for (int i = 0; i < s->n_steps; i++) printf("%s%d", i?",":"", s->steps[i]); - printf("]-%d ", channel); + printf("]-%d%s ", channel, suffix); } else if (s->step) - printf("CC%d[%d]-%d%s ", s->data, s->step, channel, s->incr?"~":""); + printf("CC%d[%d]-%d%s ", s->data, s->step, channel, suffix); else - printf("CC%d-%d%s ", s->data, channel, s->incr?"~":""); + printf("CC%d-%d%s ", s->data, channel, suffix); break; case 0xc0: - printf("PC%d-%d ", s->data, channel); + if (mod) { + int v = datavals(s->swap?val%mod:val/mod, s->step, s->steps, s->n_steps); + printf("PC%d-%d%s ", v, channel, suffix); + } else + printf("PC%d-%d%s ", s->data, channel, suffix); break; case 0xd0: if (mod) { - int v = datavals(val%mod, s->step, s->steps, s->n_steps); - printf("CP[%d]-%d ", v, channel); + int v = datavals(s->swap?val/mod:val%mod, s->step, s->steps, s->n_steps); + printf("CP[%d]-%d%s ", v, channel, suffix); } else if (s->steps) { printf("CP["); for (int i = 0; i < s->n_steps; i++) printf("%s%d", i?",":"", s->steps[i]); - printf("]-%d ", channel); + printf("]-%d%s ", channel, suffix); } else if (s->step) - printf("CP[%d]-%d ", s->step, channel); + printf("CP[%d]-%d%s ", s->step, channel, suffix); else - printf("CP-%d ", channel); + printf("CP-%d%s ", channel, suffix); break; case 0xe0: if (mod) { - int v = datavals(val%mod, s->step, s->steps, s->n_steps); - printf("PB[%d]-%d ", v, channel); + int v = datavals(s->swap?val/mod:val%mod, s->step, s->steps, s->n_steps); + printf("PB[%d]-%d%s ", v, channel, suffix); } else if (s->steps) { printf("PB["); for (int i = 0; i < s->n_steps; i++) printf("%s%d", i?",":"", s->steps[i]); - printf("]-%d ", channel); + printf("]-%d%s ", channel, suffix); } else if (s->step) - printf("PB[%d]-%d ", s->step, channel); + printf("PB[%d]-%d%s ", s->step, channel, suffix); else - printf("PB-%d ", channel); + printf("PB-%d%s ", channel, suffix); break; default: // this can't happen break; @@ -724,7 +732,8 @@ print_stroke(stroke *s, int mod, int step, int n_steps, int *steps, int val) void print_stroke_sequence(char *name, char *up_or_down, stroke *s, - int mod, int step, int n_steps, int *steps, int val) + int mod, int step, int n_steps, int *steps, + int val) { if (up_or_down && *up_or_down) printf("%s[%s]: ", name, up_or_down); @@ -761,11 +770,9 @@ append_stroke(KeySym sym, int press) { stroke *s = (stroke *)allocate(sizeof(stroke)); - s->next = NULL; + memset(s, 0, sizeof(stroke)); s->keysym = sym; s->press = press; - s->shift = 0; - s->status = s->data = s->step = s->incr = s->dirty = 0; if (*first_stroke) { last_stroke->next = s; } else { @@ -779,11 +786,8 @@ append_shift(void) { stroke *s = (stroke *)allocate(sizeof(stroke)); - s->next = NULL; + memset(s, 0, sizeof(stroke)); s->shift = 1; - s->keysym = 0; - s->press = 0; - s->status = s->data = s->step = s->incr = s->dirty = 0; if (*first_stroke) { last_stroke->next = s; } else { @@ -793,17 +797,15 @@ append_shift(void) } void -append_midi(int status, int data, int step, int n_steps, int *steps, int incr, - int recursive) +append_midi(int status, int data, int step, int n_steps, int *steps, + int swap, int incr, int recursive) { stroke *s = (stroke *)allocate(sizeof(stroke)); - s->next = NULL; - s->keysym = 0; - s->press = 0; - s->shift = 0; + memset(s, 0, sizeof(stroke)); s->status = status; s->data = data; + s->swap = swap; s->step = step; s->n_steps = n_steps; s->steps = stepsdup(n_steps, steps); @@ -1003,12 +1005,12 @@ static char *parse_steps(char *tok, char *p, int parse_midi(char *tok, char *s, int lhs, int mode, int *status, int *data, int *step, int *n_steps, int **steps, - int *incr, int *dir, int *mod) + int *incr, int *dir, int *mod, int *swap) { char *p = tok, *t; int n, m = -1, k = midi_channel; s[0] = 0; - while (*p && !isdigit(*p) && !strchr("+-=<>~[:", *p)) p++; + while (*p && !isdigit(*p) && !strchr("+-=<>~'[:", *p)) p++; if (p == tok || p-tok > 10) return 0; // no valid token // the token by itself strncpy(s, tok, p-tok); s[p-tok] = 0; @@ -1092,8 +1094,14 @@ parse_midi(char *tok, char *s, int lhs, int mode, return 0; } } - // incremental flag (messages with data only, not "ch" or "pc") - if (*p && strchr("+-=<>~", *p)) { + *incr = *dir = *swap = 0; + if (*p == '\'') { + // swap flag (only on rhs in mod translations) + if (lhs || mode < 2) return 0; + *swap = 1; + p++; + } else if (*p && strchr("+-=<>~", *p)) { + // incremental flag (messages with data only, not "ch" or "pc") if (strcmp(s, "ch") == 0) return 0; if (strcmp(s, "pc") == 0) return 0; // these are only permitted with "cc" @@ -1111,12 +1119,11 @@ parse_midi(char *tok, char *s, int lhs, int mode, if (*p != '~') return 0; else if (mode) - fprintf(stderr, "warning: incremental flag ignored in key mode: %s\n", tok); - *incr = 2; *dir = 0; + fprintf(stderr, "warning: incremental flag ignored: %s\n", tok); + else + *incr = 2; } p++; - } else { - *incr = *dir = 0; } // check for trailing garbage if (*p) return 0; @@ -1125,7 +1132,7 @@ parse_midi(char *tok, char *s, int lhs, int mode, if (lhs) return 0; // not permitted on lhs if (*step) return 0; // step size not permitted if (*n_steps) return 0; // steps not permitted - if (steps2 || n_steps2) return 0; // not permitted + if (*swap || steps2 || n_steps2) return 0; // not permitted // we return a bogus status of 0 here, along with the MIDI channel // in the data byte; also check that the MIDI channel is in the // proper range @@ -1202,7 +1209,7 @@ parse_midi(char *tok, char *s, int lhs, int mode, int start_translation(translation *tr, char *which_key) { - int k, status, data, step, n_steps, *steps, incr, dir, mod; + int k, status, data, step, n_steps, *steps, incr, dir, mod, swap; char buf[100]; //printf("start_translation(%s)\n", which_key); @@ -1219,7 +1226,7 @@ start_translation(translation *tr, char *which_key) modifier_count = 0; midi_channel = 0; k = *which_key == '^' || (is_anyshift = *which_key == '?'); - if (parse_midi(which_key+k, buf, 1, 0, &status, &data, &step, &n_steps, &steps, &incr, &dir, &mod)) { + if (parse_midi(which_key+k, buf, 1, 0, &status, &data, &step, &n_steps, &steps, &incr, &dir, &mod, &swap)) { int chan = status & 0x0f; mode = incr?0:mod?2:1; switch (status & 0xf0) { @@ -1497,7 +1504,9 @@ add_release(int all_keys) stroke *s = *press_first_stroke; while (s) { if (!s->keysym && !s->shift && s->dirty) { - append_midi(s->status, s->data, s->step, s->n_steps, s->steps, s->incr, s->recursive); + append_midi(s->status, s->data, + s->step, s->n_steps, s->steps, + s->swap, s->incr, s->recursive); s->dirty = 0; } s = s->next; @@ -1519,7 +1528,9 @@ add_release(int all_keys) } else if (s->shift) { append_shift(); } else { - append_midi(s->status, s->data, s->step, s->n_steps, s->steps, s->incr, s->recursive); + append_midi(s->status, s->data, + s->step, s->n_steps, s->steps, + s->swap, s->incr, s->recursive); } s = s->next; } @@ -1534,7 +1545,9 @@ add_release(int all_keys) } else if (s->shift) { append_shift(); } else { - append_midi(s->status, s->data, s->step, s->n_steps, s->steps, s->incr, s->recursive); + append_midi(s->status, s->data, + s->step, s->n_steps, s->steps, + s->swap, s->incr, s->recursive); } s = s->next; } @@ -1547,7 +1560,9 @@ add_release(int all_keys) } else if (s->shift) { append_shift(); } else { - append_midi(s->status, s->data, s->step, s->n_steps, s->steps, s->incr, s->recursive); + append_midi(s->status, s->data, + s->step, s->n_steps, s->steps, + s->swap, s->incr, s->recursive); } s = s->next; } @@ -1586,10 +1601,10 @@ add_string(char *str) void add_midi(char *tok) { - int status, data, step, n_steps, *steps, incr, dir = 0, mod = 0; + int status, data, step, n_steps, *steps, incr, dir = 0, mod = 0, swap = 0; int recursive = *tok == '$'; char buf[100]; - if (parse_midi(tok+recursive, buf, 0, mode, &status, &data, &step, &n_steps, &steps, &incr, &dir, &mod)) { + if (parse_midi(tok+recursive, buf, 0, mode, &status, &data, &step, &n_steps, &steps, &incr, &dir, &mod, &swap)) { if (status == 0) { // 'ch' token; this doesn't actually generate any output, it just sets // the default MIDI channel @@ -1598,7 +1613,8 @@ add_midi(char *tok) fprintf(stderr, "recursion not permitted: %s\n", tok); } else { if ((status & 0xf0) != 0xe0 || step != 0) - append_midi(status, data, step, n_steps, steps, incr!=0, recursive); + append_midi(status, data, step, n_steps, steps, + swap, incr!=0, recursive); else fprintf(stderr, "zero step size not permitted: %s\n", tok); }