From 832e98266ce9d564f9bbc3803c6c55a41f091000 Mon Sep 17 00:00:00 2001 From: Albert Graef Date: Tue, 28 Aug 2018 10:14:55 +0200 Subject: [PATCH] For consistency, treat notes like the other messages having a parameter value, so that they can be used in data translations. --- midizap.c | 141 ++++++++++++++++++++++++++++++++++++++++++--------- midizap.h | 9 ++-- readconfig.c | 33 ++++++++++-- 3 files changed, 151 insertions(+), 32 deletions(-) diff --git a/midizap.c b/midizap.c index e8a25be..ad2a3a2 100644 --- a/midizap.c +++ b/midizap.c @@ -60,6 +60,7 @@ send_key(KeySym key, int press) } // cached controller and pitch bend values +static int16_t notevalue[16][128]; static int16_t ccvalue[16][128]; static int16_t kpvalue[16][128]; static int16_t cpvalue[16]; @@ -104,7 +105,22 @@ send_midi(uint8_t portno, int status, int data, msg[1] = data; switch (status & 0xf0) { case 0x90: - if (mod) { + if (dir) { + // increment (dir==1) or decrement (dir==-1) the current value, + // clamping it to the 0..127 data byte range + if (!step) step = 1; + dir *= step; + if (dir > 0) { + if (notevalue[chan][data] >= 127) return; + notevalue[chan][data] += dir; + if (notevalue[chan][data] > 127) notevalue[chan][data] = 127; + } else { + if (notevalue[chan][data] == 0) return; + notevalue[chan][data] += dir; + if (notevalue[chan][data] < 0) notevalue[chan][data] = 0; + } + 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); if (d > 127 || d < 0) return; @@ -318,6 +334,13 @@ static stroke *find_note(translation *tr, int shift, tr->n_note[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, + tr->n_notes[shift]); +} + static stroke *find_pc(translation *tr, int shift, int chan, int data, int index) { @@ -398,7 +421,10 @@ fetch_stroke(translation *tr, uint8_t portno, int status, int chan, int data, if (tr && tr->portno == portno) { switch (status) { case 0x90: - return find_note(tr, shift, chan, data, index, mod, step, n_steps, steps); + if (dir) + return find_notes(tr, shift, chan, data, dir>0, step); + else + return find_note(tr, shift, chan, data, index, mod, step, n_steps, steps); case 0xc0: return find_pc(tr, shift, chan, data, index); case 0xb0: @@ -484,8 +510,21 @@ static char *debug_key(translation *tr, char *name, switch (status) { case 0x90: { int mod = 0, step, n_steps, *steps; - (void)find_note(tr, shift, chan, data, 0, &mod, &step, &n_steps, &steps); - if (mod) + if (tr) { + if (dir) { + step = 1; + (void)find_notes(tr, shift, chan, data, dir>0, &step); + } else + (void)find_note(tr, shift, chan, data, 0, &mod, &step, &n_steps, &steps); + } + if (!dir) + suffix = ""; + else + suffix = (dir<0)?"-":"+"; + 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); @@ -500,8 +539,8 @@ static char *debug_key(translation *tr, char *name, sprintf(name, "%s%s%d[%d]-%d", prefix, note_name(data), note_octave(data), mod, chan+1); else - sprintf(name, "%s%s%d-%d", prefix, note_name(data), - note_octave(data), chan+1); + sprintf(name, "%s%s%d-%d%s", prefix, note_name(data), + note_octave(data), chan+1, suffix); break; } case 0xa0: { @@ -841,6 +880,7 @@ get_focused_window_translation() return last_window_translation; } +static int8_t innotevalue[2][16][128]; static int8_t inccvalue[2][16][128]; static int8_t inkpvalue[2][16][128]; static int8_t incpvalue[2][16]; @@ -857,12 +897,50 @@ static int16_t inpbvalue[2][16] = static int keydown_tracker = 0; -static uint8_t notedown[2][16][128]; +static uint8_t innotedown[2][16][128]; static uint8_t inccdown[2][16][128]; static uint8_t inpbdown[2][16]; static uint8_t inkpdown[2][16][128]; static uint8_t incpdown[2][16]; +int +check_notes(translation *tr, uint8_t portno, int chan, int data) +{ + if (tr && tr->portno == portno && + (find_notes(tr, shift, chan, data, 0, 0) || + find_notes(tr, shift, chan, data, 1, 0))) + return 1; + tr = default_midi_translation[portno]; + if (tr && tr->portno == portno && + (find_notes(tr, shift, chan, data, 0, 0) || + find_notes(tr, shift, chan, data, 1, 0))) + return 1; + tr = default_translation; + if (tr && tr->portno == portno && + (find_notes(tr, shift, chan, data, 0, 0) || + find_notes(tr, shift, chan, data, 1, 0))) + return 1; + return 0; +} + +int +get_note_step(translation *tr, uint8_t portno, int chan, int data, int dir) +{ + int step; + if (tr && tr->portno == portno && + find_notes(tr, shift, chan, data, dir>0, &step)) + return step; + tr = default_midi_translation[portno]; + if (tr && tr->portno == portno && + find_notes(tr, shift, chan, data, dir>0, &step)) + return step; + tr = default_translation; + if (tr && tr->portno == portno && + find_notes(tr, shift, chan, data, dir>0, &step)) + return step; + return 1; +} + int get_note_mod(translation *tr, uint8_t portno, int chan, int data) { @@ -1147,23 +1225,6 @@ handle_event(uint8_t *msg, uint8_t portno) send_strokes(tr, portno, status, chan, msg[1], 0, 1, 0); end_debug(); break; - case 0x90: - start_debug(); - if (get_note_mod(tr, portno, chan, msg[1])) - send_strokes(tr, portno, status, chan, msg[1], msg[2], 0, 0); - else if (msg[2]) { - if (!keydown_tracker || !notedown[portno][chan][msg[1]]) { - send_strokes(tr, portno, status, chan, msg[1], msg[2], 0, 0); - notedown[portno][chan][msg[1]] = 1; - } - } else { - if (!keydown_tracker || notedown[portno][chan][msg[1]]) { - send_strokes(tr, portno, status, chan, msg[1], msg[2], 1, 0); - notedown[portno][chan][msg[1]] = 0; - } - } - end_debug(); - break; case 0xb0: start_debug(); if (get_cc_mod(tr, portno, chan, msg[1])) @@ -1227,6 +1288,38 @@ handle_event(uint8_t *msg, uint8_t portno) } end_debug(); break; + case 0x90: + start_debug(); + if (get_note_mod(tr, portno, chan, msg[1])) + send_strokes(tr, portno, status, chan, msg[1], msg[2], 0, 0); + else if (msg[2]) { + if (!keydown_tracker || !innotedown[portno][chan][msg[1]]) { + send_strokes(tr, portno, status, chan, msg[1], msg[2], 0, 0); + innotedown[portno][chan][msg[1]] = 1; + } + } else { + if (!keydown_tracker || innotedown[portno][chan][msg[1]]) { + send_strokes(tr, portno, status, chan, msg[1], msg[2], 1, 0); + innotedown[portno][chan][msg[1]] = 0; + } + } + debug_count = 0; + if (check_notes(tr, portno, chan, msg[1]) && + innotevalue[portno][chan][msg[1]] != msg[2]) { + int dir = innotevalue[portno][chan][msg[1]] > msg[2] ? -1 : 1; + int step = get_note_step(tr, portno, chan, msg[1], dir); + if (step) { + while (innotevalue[portno][chan][msg[1]] != msg[2]) { + int d = abs(innotevalue[portno][chan][msg[1]] - msg[2]); + if (d > step) d = step; + if (d < step) break; + send_strokes(tr, portno, status, chan, msg[1], 0, 0, dir); + innotevalue[portno][chan][msg[1]] += dir*d; + } + } + } + end_debug(); + break; case 0xa0: start_debug(); if (get_kp_mod(tr, portno, chan, msg[1])) diff --git a/midizap.h b/midizap.h index 105eefe..49ab04a 100644 --- a/midizap.h +++ b/midizap.h @@ -85,6 +85,7 @@ typedef struct _translation { uint8_t portno; // these are indexed by shift status stroke_data *note[2]; + stroke_data *notes[2]; stroke_data *pc[2]; stroke_data *cc[2]; stroke_data *ccs[2]; @@ -95,10 +96,10 @@ typedef struct _translation { stroke_data *cp[2]; stroke_data *cps[2]; // actual and allocated sizes (can be at most 16*128) - uint16_t n_note[2], n_pc[2], n_cc[2], n_ccs[2], n_pb[2], n_pbs[2], - n_kp[2], n_kps[2], n_cp[2], n_cps[2]; - uint16_t a_note[2], a_pc[2], a_cc[2], a_ccs[2], a_pb[2], a_pbs[2], - a_kp[2], a_kps[2], a_cp[2], a_cps[2]; + uint16_t n_note[2], n_notes[2], n_pc[2], n_cc[2], n_ccs[2], + n_pb[2], n_pbs[2], n_kp[2], n_kps[2], n_cp[2], n_cps[2]; + uint16_t a_note[2], a_notes[2], a_pc[2], a_cc[2], a_ccs[2], + a_pb[2], a_pbs[2], a_kp[2], a_kps[2], a_cp[2], a_cps[2]; } translation; extern void reload_callback(void); diff --git a/readconfig.c b/readconfig.c index 566c0b0..56e50e0 100644 --- a/readconfig.c +++ b/readconfig.c @@ -296,6 +296,14 @@ static stroke **find_note(translation *tr, int shift, &tr->n_note[shift], &tr->a_note[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, + &tr->n_notes[shift], &tr->a_notes[shift]); +} + static stroke **find_pc(translation *tr, int shift, int chan, int data, int index) { @@ -1034,10 +1042,10 @@ parse_midi(char *tok, char *s, int lhs, int mode, return 0; } } - // incremental flag ("cc", "pb", "cp" and "kp" only) + // incremental flag (messages with data only, not "ch" or "pc") if (*p && strchr("+-=<>~", *p)) { - if (strcmp(s, "pb") && strcmp(s, "cc") && - strcmp(s, "cp") && strcmp(s, "kp")) return 0; + if (strcmp(s, "ch") == 0) return 0; + if (strcmp(s, "pc") == 0) return 0; // these are only permitted with "cc" if (strchr("<>~", *p) && strcmp(s, "cc")) return 0; if (lhs) { @@ -1166,7 +1174,24 @@ start_translation(translation *tr, char *which_key) mode = incr?0:mod?2:1; switch (status & 0xf0) { case 0x90: - if (mod) { + if (incr) { + // note (step up, down) + if (step <= 0) { + fprintf(stderr, "zero or negative step size not permitted here: [%s]%s\n", current_translation, which_key); + return 1; + } + first_stroke = find_notes(tr, k, chan, data, dir>0, step); + if (is_anyshift) { + alt_press_stroke = find_notes(tr, 0, chan, data, dir>0, step); + } + if (!dir) { + is_bidirectional = 1; + release_first_stroke = find_notes(tr, k, chan, data, 1, step); + if (is_anyshift) { + alt_release_stroke = find_notes(tr, 0, chan, data, 1, step); + } + } + } else if (mod) { // note mod first_stroke = find_note(tr, k, chan, data, 0, mod, step, n_steps, steps);