Special mod translations in key mode (experimental).
parent
40cd0abe66
commit
46d15aa3d2
|
@ -173,6 +173,25 @@ A#5 D#7
|
|||
B5 E7
|
||||
C6 F7
|
||||
|
||||
# meter feedback
|
||||
|
||||
# The Mackie protocol packs all 8 channel meters into a single channel
|
||||
# pressure message which we need to transform into the corresponding
|
||||
# note messages for the LEDs. Note that we only use the upper 5x8 part
|
||||
# of the grid here, in order not to clobber the 3 rows at the bottom
|
||||
# with the rec/solo/mute buttons. This means that the meters, which
|
||||
# actually have 8 different values, have to be squashed into 5 LEDs per
|
||||
# channel.
|
||||
|
||||
?CP[16] C2[0,1] G#2[0,0,0,1] E3[0,0,0,0,0,5] C4[0,0,0,0,0,0,0,5] G#4[0,0,0,0,0,0,0,0,3]
|
||||
|
||||
# Here's an alternative decoding, which creates horizontal meters
|
||||
# covering the full range, with the first channel on top. Note,
|
||||
# however, that this ranges across the entire 8x8 grid and will thus
|
||||
# clobber the rec/solo/mute controls!
|
||||
|
||||
#?CP[16][-8] G#4[0,1] A4[0,0,1] A#4[0,0,0,1] B4[0,0,0,0,1] C5[0,0,0,0,0,5] C#5[0,0,0,0,0,0,5] D5[0,0,0,0,0,0,0,5] D#5[0,0,0,0,0,0,0,0,3]
|
||||
|
||||
# no feedback for faders (faders aren't motorized)
|
||||
|
||||
# NOTE: Feedback for rec/solo/mute/select also needs to be recognized in shift
|
||||
|
|
424
midizap.c
424
midizap.c
|
@ -77,8 +77,25 @@ static int dataval(int val, int min, int max)
|
|||
return val;
|
||||
}
|
||||
|
||||
static int datavals(int val, int step, int *steps, int n_steps)
|
||||
{
|
||||
if (val < 0)
|
||||
return -datavals(-val, step, steps, n_steps);
|
||||
else if (val < n_steps)
|
||||
return steps[val];
|
||||
else if (n_steps)
|
||||
return steps[n_steps-1];
|
||||
else if (step)
|
||||
return step*val;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
send_midi(uint8_t portno, int status, int data, int step, int incr, int index, int dir)
|
||||
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)
|
||||
{
|
||||
if (!jack_num_outputs) return; // MIDI output not enabled
|
||||
uint8_t msg[3];
|
||||
|
@ -87,7 +104,14 @@ send_midi(uint8_t portno, int status, int data, int step, int incr, int index, i
|
|||
msg[1] = data;
|
||||
switch (status & 0xf0) {
|
||||
case 0x90:
|
||||
if (!index) {
|
||||
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;
|
||||
if (v > 127 || v < 0) return;
|
||||
msg[1] = d;
|
||||
msg[2] = v;
|
||||
} else if (!index) {
|
||||
msg[2] = dataval(step, 0, 127);
|
||||
} else {
|
||||
msg[2] = 0;
|
||||
|
@ -118,6 +142,13 @@ send_midi(uint8_t portno, int status, int data, int step, int incr, int index, i
|
|||
}
|
||||
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);
|
||||
if (d > 127 || d < 0) return;
|
||||
if (v > 127 || v < 0) return;
|
||||
msg[1] = d;
|
||||
msg[2] = v;
|
||||
} else if (!index) {
|
||||
msg[2] = dataval(step, 0, 127);
|
||||
} else {
|
||||
|
@ -140,6 +171,13 @@ send_midi(uint8_t portno, int status, int data, int step, int incr, int index, i
|
|||
if (kpvalue[chan][data] < 0) kpvalue[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;
|
||||
if (v > 127 || v < 0) return;
|
||||
msg[1] = d;
|
||||
msg[2] = v;
|
||||
} else if (!index) {
|
||||
msg[2] = dataval(step, 0, 127);
|
||||
} else {
|
||||
|
@ -162,6 +200,10 @@ send_midi(uint8_t portno, int status, int data, int step, int incr, int index, i
|
|||
if (cpvalue[chan] < 0) cpvalue[chan] = 0;
|
||||
}
|
||||
msg[1] = cpvalue[chan];
|
||||
} else if (mod) {
|
||||
int v = datavals(val%mod, step, steps, n_steps);
|
||||
if (v > 127 || v < 0) return;
|
||||
msg[1] = v;
|
||||
} else if (!index) {
|
||||
msg[1] = dataval(step, 0, 127);
|
||||
} else {
|
||||
|
@ -185,6 +227,10 @@ send_midi(uint8_t portno, int status, int data, int step, int incr, int index, i
|
|||
if (pbvalue[chan] < 0) pbvalue[chan] = 0;
|
||||
}
|
||||
pbval = pbvalue[chan];
|
||||
} else if (mod) {
|
||||
int v = datavals(val%mod, step, steps, n_steps);
|
||||
if (v > 8191 || v < -8192) return;
|
||||
pbval = 8192+v;
|
||||
} else if (!index) {
|
||||
pbval = 8192+dataval(step, -8192, 8191);
|
||||
} else {
|
||||
|
@ -219,7 +265,8 @@ static int stroke_data_cmp(const void *a, const void *b)
|
|||
|
||||
static stroke *find_stroke_data(stroke_data *sd,
|
||||
int chan, int data, int index,
|
||||
int *step, int *incr,
|
||||
int *step, int *n_steps, int **steps,
|
||||
int *incr, int *mod,
|
||||
uint16_t n)
|
||||
{
|
||||
if (n < 16) {
|
||||
|
@ -230,7 +277,10 @@ static stroke *find_stroke_data(stroke_data *sd,
|
|||
for (i = 0; i < n; i++) {
|
||||
if (sd[i].chan == chan && sd[i].data == data) {
|
||||
if (step) *step = sd[i].step[index];
|
||||
if (n_steps) *n_steps = sd[i].n_steps[index];
|
||||
if (steps) *steps = sd[i].steps[index];
|
||||
if (incr) *incr = sd[i].is_incr;
|
||||
if (mod) *mod = sd[i].mod;
|
||||
return sd[i].s[index];
|
||||
} else if (sd[i].chan > chan ||
|
||||
(sd[i].chan == chan && sd[i].data > data))
|
||||
|
@ -244,7 +294,10 @@ static stroke *find_stroke_data(stroke_data *sd,
|
|||
ret = bsearch(&key, sd, n, sizeof(stroke_data), stroke_data_cmp);
|
||||
if (ret) {
|
||||
if (step) *step = ret->step[index];
|
||||
if (n_steps) *n_steps = ret->n_steps[index];
|
||||
if (steps) *steps = ret->steps[index];
|
||||
if (incr) *incr = ret->is_incr;
|
||||
if (mod) *mod = ret->mod;
|
||||
return ret->s[index];
|
||||
} else
|
||||
return NULL;
|
||||
|
@ -252,105 +305,117 @@ static stroke *find_stroke_data(stroke_data *sd,
|
|||
}
|
||||
|
||||
static stroke *find_note(translation *tr, int shift,
|
||||
int chan, int data, int index)
|
||||
int chan, int data, int index, int *mod,
|
||||
int *step, int *n_steps, int **steps)
|
||||
{
|
||||
return find_stroke_data(tr->note[shift], chan, data, index, 0, 0,
|
||||
return find_stroke_data(tr->note[shift], chan, data, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
tr->n_note[shift]);
|
||||
}
|
||||
|
||||
static stroke *find_pc(translation *tr, int shift,
|
||||
int chan, int data, int index)
|
||||
{
|
||||
return find_stroke_data(tr->pc[shift], chan, data, index, 0, 0,
|
||||
return find_stroke_data(tr->pc[shift], chan, data, index, 0, 0, 0, 0, 0,
|
||||
tr->n_pc[shift]);
|
||||
}
|
||||
|
||||
static stroke *find_cc(translation *tr, int shift,
|
||||
int chan, int data, int index)
|
||||
int chan, int data, int index, int *mod,
|
||||
int *step, int *n_steps, int **steps)
|
||||
{
|
||||
return find_stroke_data(tr->cc[shift], chan, data, index, 0, 0,
|
||||
return find_stroke_data(tr->cc[shift], chan, data, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
tr->n_cc[shift]);
|
||||
}
|
||||
|
||||
static stroke *find_ccs(translation *tr, int shift,
|
||||
int chan, int data, int index, int *step, int *incr)
|
||||
{
|
||||
return find_stroke_data(tr->ccs[shift], chan, data, index, step, incr,
|
||||
return find_stroke_data(tr->ccs[shift], chan, data, index, step, 0, 0,
|
||||
incr, 0,
|
||||
tr->n_ccs[shift]);
|
||||
}
|
||||
|
||||
static stroke *find_kp(translation *tr, int shift,
|
||||
int chan, int data, int index)
|
||||
int chan, int data, int index, int *mod,
|
||||
int *step, int *n_steps, int **steps)
|
||||
{
|
||||
return find_stroke_data(tr->kp[shift], chan, data, index, 0, 0,
|
||||
return find_stroke_data(tr->kp[shift], chan, data, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
tr->n_kp[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,
|
||||
return find_stroke_data(tr->kps[shift], chan, data, index, step, 0, 0, 0, 0,
|
||||
tr->n_kps[shift]);
|
||||
}
|
||||
|
||||
static stroke *find_cp(translation *tr, int shift,
|
||||
int chan, int index)
|
||||
int chan, int index, int *mod,
|
||||
int *step, int *n_steps, int **steps)
|
||||
{
|
||||
return find_stroke_data(tr->cp[shift], chan, 0, index, 0, 0,
|
||||
return find_stroke_data(tr->cp[shift], chan, 0, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
tr->n_cp[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,
|
||||
return find_stroke_data(tr->cps[shift], chan, 0, index, step, 0, 0, 0, 0,
|
||||
tr->n_cps[shift]);
|
||||
}
|
||||
|
||||
static stroke *find_pb(translation *tr, int shift,
|
||||
int chan, int index)
|
||||
int chan, int index, int *mod,
|
||||
int *step, int *n_steps, int **steps)
|
||||
{
|
||||
return find_stroke_data(tr->pb[shift], chan, 0, index, 0, 0,
|
||||
return find_stroke_data(tr->pb[shift], chan, 0, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
tr->n_pb[shift]);
|
||||
}
|
||||
|
||||
static stroke *find_pbs(translation *tr, int shift,
|
||||
int chan, int index, int *step)
|
||||
{
|
||||
return find_stroke_data(tr->pbs[shift], chan, 0, index, step, 0,
|
||||
return find_stroke_data(tr->pbs[shift], chan, 0, index, step, 0, 0, 0, 0,
|
||||
tr->n_pbs[shift]);
|
||||
}
|
||||
|
||||
stroke *
|
||||
fetch_stroke(translation *tr, uint8_t portno, int status, int chan, int data,
|
||||
int index, int dir, int *step, int *incr)
|
||||
int index, int dir, int *step, int *n_steps, int **steps,
|
||||
int *incr, int *mod)
|
||||
{
|
||||
if (tr && tr->portno == portno) {
|
||||
switch (status) {
|
||||
case 0x90:
|
||||
return find_note(tr, shift, chan, data, index);
|
||||
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:
|
||||
if (dir)
|
||||
return find_ccs(tr, shift, chan, data, dir>0, step, incr);
|
||||
else
|
||||
return find_cc(tr, shift, chan, data, index);
|
||||
return find_cc(tr, shift, chan, data, index, mod, step, n_steps, steps);
|
||||
case 0xa0:
|
||||
if (dir)
|
||||
return find_kps(tr, shift, chan, data, dir>0, step);
|
||||
else
|
||||
return find_kp(tr, shift, chan, data, index);
|
||||
return find_kp(tr, shift, chan, data, index, mod, step, n_steps, steps);
|
||||
case 0xd0:
|
||||
if (dir)
|
||||
return find_cps(tr, shift, chan, dir>0, step);
|
||||
else
|
||||
return find_cp(tr, shift, chan, index);
|
||||
return find_cp(tr, shift, chan, index, mod, step, n_steps, steps);
|
||||
case 0xe0:
|
||||
if (dir)
|
||||
return find_pbs(tr, shift, chan, dir>0, step);
|
||||
else
|
||||
return find_pb(tr, shift, chan, index);
|
||||
return find_pb(tr, shift, chan, index, mod, step, n_steps, steps);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -389,35 +454,95 @@ static void debug_section(translation *tr)
|
|||
}
|
||||
}
|
||||
|
||||
static char *note_name(int n)
|
||||
{
|
||||
static char *note_names[] = { "C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#", "A", "Bb", "B" };
|
||||
if (n < 0 && n%12)
|
||||
return note_names[12+n%12];
|
||||
else
|
||||
return note_names[n%12];
|
||||
}
|
||||
|
||||
static int note_octave(int n)
|
||||
{
|
||||
if (n < 0 && n%12)
|
||||
return n/12-1 + midi_octave;
|
||||
else
|
||||
return n/12 + midi_octave;
|
||||
}
|
||||
|
||||
static char *debug_key(translation *tr, char *name,
|
||||
int status, int chan, int data, int dir)
|
||||
{
|
||||
static char *note_names[] = { "C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#", "A", "Bb", "B" };
|
||||
char *prefix = shift?"^":"", *suffix = "";
|
||||
strcpy(name, "??");
|
||||
switch (status) {
|
||||
case 0x90:
|
||||
sprintf(name, "%s%s%d-%d", prefix, note_names[data % 12],
|
||||
data / 12 + midi_octave, chan+1);
|
||||
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 (step != 1)
|
||||
sprintf(name, "%s%s%d[%d][%d]-%d", prefix, note_name(data),
|
||||
note_octave(data), mod, step, chan+1);
|
||||
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);
|
||||
} else
|
||||
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);
|
||||
break;
|
||||
}
|
||||
case 0xa0: {
|
||||
int step = 1;
|
||||
if (tr) (void)find_kps(tr, shift, chan, data, dir>0, &step);
|
||||
int step = 0, n_steps = 0, *steps = 0, mod = 0;
|
||||
if (tr) {
|
||||
if (dir) {
|
||||
step = 1;
|
||||
(void)find_kps(tr, shift, chan, data, dir>0, &step);
|
||||
} else
|
||||
(void)find_kp(tr, shift, chan, data, 0, &mod, &step, &n_steps, &steps);
|
||||
}
|
||||
if (!dir)
|
||||
suffix = "";
|
||||
else
|
||||
suffix = (dir<0)?"-":"+";
|
||||
if (dir && step != 1)
|
||||
sprintf(name, "%sKP:%s%d[%d]-%d%s", prefix, note_names[data % 12],
|
||||
data / 12 + midi_octave, step, chan+1, suffix);
|
||||
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);
|
||||
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);
|
||||
} else
|
||||
sprintf(name, "%sKP:%s%d[%d]-%d", prefix, note_name(data),
|
||||
note_octave(data), mod, chan+1);
|
||||
else
|
||||
sprintf(name, "%sKP:%s%d-%d%s", prefix, note_names[data % 12],
|
||||
data / 12 + midi_octave, chan+1, suffix);
|
||||
sprintf(name, "%sKP:%s%d-%d%s", prefix, note_name(data),
|
||||
note_octave(data), chan+1, suffix);
|
||||
break;
|
||||
}
|
||||
case 0xb0: {
|
||||
int step = 1, is_incr = 0;
|
||||
if (tr) (void)find_ccs(tr, shift, chan, data, dir>0, &step, &is_incr);
|
||||
int step = 0, n_steps = 0, *steps = 0, mod = 0, is_incr = 0;
|
||||
if (tr) {
|
||||
if (dir) {
|
||||
step = 1;
|
||||
(void)find_ccs(tr, shift, chan, data, dir>0, &step, &is_incr);
|
||||
} else
|
||||
(void)find_cc(tr, shift, chan, data, 0, &mod, &step, &n_steps, &steps);
|
||||
}
|
||||
if (!dir)
|
||||
suffix = "";
|
||||
else if (is_incr)
|
||||
|
@ -426,6 +551,17 @@ static char *debug_key(translation *tr, char *name,
|
|||
suffix = (dir<0)?"-":"+";
|
||||
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);
|
||||
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);
|
||||
} else
|
||||
sprintf(name, "%sCC%d[%d]-%d", prefix, data, mod, chan+1);
|
||||
else
|
||||
sprintf(name, "%sCC%d-%d%s", prefix, data, chan+1, suffix);
|
||||
break;
|
||||
|
@ -434,14 +570,31 @@ static char *debug_key(translation *tr, char *name,
|
|||
sprintf(name, "%sPC%d-%d", prefix, data, chan+1);
|
||||
break;
|
||||
case 0xd0: {
|
||||
int step = 1;
|
||||
if (tr) (void)find_cps(tr, shift, chan, dir>0, &step);
|
||||
int step = 0, n_steps = 0, *steps = 0, mod = 0;
|
||||
if (tr) {
|
||||
if (dir) {
|
||||
step = 1;
|
||||
(void)find_cps(tr, shift, chan, dir>0, &step);
|
||||
} else
|
||||
(void)find_cp(tr, shift, chan, 0, &mod, &step, &n_steps, &steps);
|
||||
}
|
||||
if (!dir)
|
||||
suffix = "";
|
||||
else
|
||||
suffix = (dir<0)?"-":"+";
|
||||
if (dir && step != 1)
|
||||
if (dir && step != 1)
|
||||
sprintf(name, "%sCP[%d]-%d%s", prefix, step, chan+1, suffix);
|
||||
else if (!dir && mod)
|
||||
if (step != 1)
|
||||
sprintf(name, "%sCP[%d][%d]-%d", prefix, mod, step, chan+1);
|
||||
else if (n_steps) {
|
||||
sprintf(name, "%sCP[%d][", prefix, 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);
|
||||
} else
|
||||
sprintf(name, "%sCP[%d]-%d", prefix, mod, chan+1);
|
||||
else
|
||||
sprintf(name, "%sCP-%d%s", prefix, chan+1, suffix);
|
||||
break;
|
||||
|
@ -509,26 +662,26 @@ static void end_debug()
|
|||
}
|
||||
|
||||
void
|
||||
send_strokes(translation *tr, uint8_t portno, int status, int chan, int data,
|
||||
int index, int dir)
|
||||
send_strokes(translation *tr, uint8_t portno, int status, int chan,
|
||||
int data, int data2, int index, int dir)
|
||||
{
|
||||
int nkeys = 0, step = 0, is_incr = 0;
|
||||
int nkeys = 0, step = 0, n_steps = 0, *steps = 0, is_incr = 0, mod = 0;
|
||||
stroke *s = fetch_stroke(tr, portno, status, chan, data, index, dir,
|
||||
&step, &is_incr);
|
||||
&step, &n_steps, &steps, &is_incr, &mod);
|
||||
// If there's no press/release translation, check whether we have got at
|
||||
// least the corresponding release/press translation, in order to prevent
|
||||
// spurious error messages if either the press or release translation just
|
||||
// happens to be empty.
|
||||
int chk = s ||
|
||||
(!dir && fetch_stroke(tr, portno, status, chan, data, !index, dir, 0, 0));
|
||||
(!dir && fetch_stroke(tr, portno, status, chan, data, !index, dir, 0, 0, 0, 0, 0));
|
||||
|
||||
if (!s && jack_num_outputs) {
|
||||
// fall back to default MIDI translation
|
||||
tr = default_midi_translation[portno];
|
||||
s = fetch_stroke(tr, portno, status, chan, data, index, dir,
|
||||
&step, &is_incr);
|
||||
&step, &n_steps, &steps, &is_incr, &mod);
|
||||
chk = chk || s ||
|
||||
(!dir && fetch_stroke(tr, portno, status, chan, data, !index, dir, 0, 0));
|
||||
(!dir && fetch_stroke(tr, portno, status, chan, data, !index, dir, 0, 0, 0, 0, 0));
|
||||
// Ignore all MIDI input on the second port if no translation was found in
|
||||
// the [MIDI2] section (or the section is missing altogether).
|
||||
if (portno && !s) return;
|
||||
|
@ -538,9 +691,9 @@ send_strokes(translation *tr, uint8_t portno, int status, int chan, int data,
|
|||
// fall back to the default translation
|
||||
tr = default_translation;
|
||||
s = fetch_stroke(tr, portno, status, chan, data, index, dir,
|
||||
&step, &is_incr);
|
||||
&step, &n_steps, &steps, &is_incr, &mod);
|
||||
chk = chk || s ||
|
||||
(!dir && fetch_stroke(tr, portno, status, chan, data, !index, dir, 0, 0));
|
||||
(!dir && fetch_stroke(tr, portno, status, chan, data, !index, dir, 0, 0, 0, 0, 0));
|
||||
}
|
||||
|
||||
if (debug_regex) {
|
||||
|
@ -561,7 +714,8 @@ send_strokes(translation *tr, uint8_t portno, int status, int chan, int data,
|
|||
if (s && debug_keys) {
|
||||
char name[100];
|
||||
print_stroke_sequence(debug_key(tr, name, status, chan, data, dir),
|
||||
dir?"":index?"U":"D", s);
|
||||
(dir||mod)?"":index?"U":"D", s,
|
||||
mod, step, n_steps, steps, data2);
|
||||
}
|
||||
while (s) {
|
||||
if (s->keysym) {
|
||||
|
@ -571,7 +725,9 @@ send_strokes(translation *tr, uint8_t portno, int status, int chan, int data,
|
|||
// toggle shift status
|
||||
shift = !shift;
|
||||
} else {
|
||||
send_midi(portno, s->status, s->data, s->step, s->incr, index, dir);
|
||||
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 = s->next;
|
||||
}
|
||||
|
@ -702,6 +858,24 @@ static uint8_t inpbdown[2][16];
|
|||
static uint8_t inkpdown[2][16][128];
|
||||
static uint8_t incpdown[2][16];
|
||||
|
||||
int
|
||||
get_note_mod(translation *tr, uint8_t portno, int chan, int data)
|
||||
{
|
||||
int mod;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_note(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_midi_translation[portno];
|
||||
if (tr && tr->portno == portno &&
|
||||
find_note(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_translation;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_note(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
check_incr(translation *tr, uint8_t portno, int chan, int data)
|
||||
{
|
||||
|
@ -761,6 +935,24 @@ get_cc_step(translation *tr, uint8_t portno, int chan, int data, int dir)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
get_cc_mod(translation *tr, uint8_t portno, int chan, int data)
|
||||
{
|
||||
int mod;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_cc(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_midi_translation[portno];
|
||||
if (tr && tr->portno == portno &&
|
||||
find_cc(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_translation;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_cc(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
check_kps(translation *tr, uint8_t portno, int chan, int data)
|
||||
{
|
||||
|
@ -799,6 +991,24 @@ get_kp_step(translation *tr, uint8_t portno, int chan, int data, int dir)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
get_kp_mod(translation *tr, uint8_t portno, int chan, int data)
|
||||
{
|
||||
int mod;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_kp(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_midi_translation[portno];
|
||||
if (tr && tr->portno == portno &&
|
||||
find_kp(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_translation;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_kp(tr, shift, chan, data, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
check_cps(translation *tr, uint8_t portno, int chan)
|
||||
{
|
||||
|
@ -837,6 +1047,24 @@ get_cp_step(translation *tr, uint8_t portno, int chan, int dir)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
get_cp_mod(translation *tr, uint8_t portno, int chan)
|
||||
{
|
||||
int mod;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_cp(tr, shift, chan, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_midi_translation[portno];
|
||||
if (tr && tr->portno == portno &&
|
||||
find_cp(tr, shift, chan, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_translation;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_cp(tr, shift, chan, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
check_pbs(translation *tr, uint8_t portno, int chan)
|
||||
{
|
||||
|
@ -875,6 +1103,24 @@ get_pb_step(translation *tr, uint8_t portno, int chan, int dir)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
get_pb_mod(translation *tr, uint8_t portno, int chan)
|
||||
{
|
||||
int mod;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_pb(tr, shift, chan, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_midi_translation[portno];
|
||||
if (tr && tr->portno == portno &&
|
||||
find_pb(tr, shift, chan, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
tr = default_translation;
|
||||
if (tr && tr->portno == portno &&
|
||||
find_pb(tr, shift, chan, 0, &mod, 0, 0, 0))
|
||||
return mod;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
handle_event(uint8_t *msg, uint8_t portno)
|
||||
{
|
||||
|
@ -892,20 +1138,22 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
switch (status) {
|
||||
case 0xc0:
|
||||
start_debug();
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 0);
|
||||
send_strokes(tr, portno, status, chan, msg[1], 1, 0);
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 0, 0);
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 1, 0);
|
||||
end_debug();
|
||||
break;
|
||||
case 0x90:
|
||||
start_debug();
|
||||
if (msg[2]) {
|
||||
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], 0, 0);
|
||||
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], 1, 0);
|
||||
send_strokes(tr, portno, status, chan, msg[1], msg[2], 1, 0);
|
||||
notedown[portno][chan][msg[1]] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -913,14 +1161,16 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
break;
|
||||
case 0xb0:
|
||||
start_debug();
|
||||
if (msg[2]) {
|
||||
if (get_cc_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 || !inccdown[portno][chan][msg[1]]) {
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 0);
|
||||
send_strokes(tr, portno, status, chan, msg[1], msg[2], 0, 0);
|
||||
inccdown[portno][chan][msg[1]] = 1;
|
||||
}
|
||||
} else {
|
||||
if (!keydown_tracker || inccdown[portno][chan][msg[1]]) {
|
||||
send_strokes(tr, portno, status, chan, msg[1], 1, 0);
|
||||
send_strokes(tr, portno, status, chan, msg[1], msg[2], 1, 0);
|
||||
inccdown[portno][chan][msg[1]] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -942,7 +1192,7 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
if (step) {
|
||||
int d = msg[2]/step;
|
||||
while (d) {
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 1);
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 0, 1);
|
||||
d--;
|
||||
}
|
||||
}
|
||||
|
@ -951,7 +1201,7 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
if (step) {
|
||||
int d = (msg[2]-64)/step;
|
||||
while (d) {
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, -1);
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 0, -1);
|
||||
d--;
|
||||
}
|
||||
}
|
||||
|
@ -965,7 +1215,7 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
int d = abs(inccvalue[portno][chan][msg[1]] - msg[2]);
|
||||
if (d > step) d = step;
|
||||
if (d < step) break;
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, dir);
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 0, dir);
|
||||
inccvalue[portno][chan][msg[1]] += dir*d;
|
||||
}
|
||||
}
|
||||
|
@ -974,14 +1224,16 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
break;
|
||||
case 0xa0:
|
||||
start_debug();
|
||||
if (msg[2]) {
|
||||
if (get_kp_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 || !inkpdown[portno][chan][msg[1]]) {
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 0);
|
||||
send_strokes(tr, portno, status, chan, msg[1], msg[2], 0, 0);
|
||||
inkpdown[portno][chan][msg[1]] = 1;
|
||||
}
|
||||
} else {
|
||||
if (!keydown_tracker || inkpdown[portno][chan][msg[1]]) {
|
||||
send_strokes(tr, portno, status, chan, msg[1], 1, 0);
|
||||
send_strokes(tr, portno, status, chan, msg[1], msg[2], 1, 0);
|
||||
inkpdown[portno][chan][msg[1]] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -995,7 +1247,7 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
int d = abs(inkpvalue[portno][chan][msg[1]] - msg[2]);
|
||||
if (d > step) d = step;
|
||||
if (d < step) break;
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, dir);
|
||||
send_strokes(tr, portno, status, chan, msg[1], 0, 0, dir);
|
||||
inkpvalue[portno][chan][msg[1]] += dir*d;
|
||||
}
|
||||
}
|
||||
|
@ -1004,14 +1256,16 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
break;
|
||||
case 0xd0:
|
||||
start_debug();
|
||||
if (msg[1]) {
|
||||
if (get_cp_mod(tr, portno, chan))
|
||||
send_strokes(tr, portno, status, chan, 0, msg[1], 0, 0);
|
||||
else if (msg[1]) {
|
||||
if (!keydown_tracker || !incpdown[portno][chan]) {
|
||||
send_strokes(tr, portno, status, chan, 0, 0, 0);
|
||||
send_strokes(tr, portno, status, chan, 0, 0, 0, 0);
|
||||
incpdown[portno][chan] = 1;
|
||||
}
|
||||
} else {
|
||||
if (!keydown_tracker || incpdown[portno][chan]) {
|
||||
send_strokes(tr, portno, status, chan, 0, 1, 0);
|
||||
send_strokes(tr, portno, status, chan, 0, 0, 1, 0);
|
||||
incpdown[portno][chan] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1025,7 +1279,7 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
int d = abs(incpvalue[portno][chan] - msg[1]);
|
||||
if (d > step) d = step;
|
||||
if (d < step) break;
|
||||
send_strokes(tr, portno, status, chan, 0, 0, dir);
|
||||
send_strokes(tr, portno, status, chan, 0, 0, 0, dir);
|
||||
incpvalue[portno][chan] += dir*d;
|
||||
}
|
||||
}
|
||||
|
@ -1036,14 +1290,16 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
int bend = ((msg[2] << 7) | msg[1]) - 8192;
|
||||
start_debug();
|
||||
//fprintf(stderr, "pb %d\n", bend);
|
||||
if (bend) {
|
||||
if (get_pb_mod(tr, portno, chan))
|
||||
send_strokes(tr, portno, status, chan, 0, bend, 0, 0);
|
||||
else if (bend) {
|
||||
if (!keydown_tracker || !inpbdown[portno][chan]) {
|
||||
send_strokes(tr, portno, status, chan, 0, 0, 0);
|
||||
send_strokes(tr, portno, status, chan, 0, 0, 0, 0);
|
||||
inpbdown[portno][chan] = 1;
|
||||
}
|
||||
} else {
|
||||
if (!keydown_tracker || inpbdown[portno][chan]) {
|
||||
send_strokes(tr, portno, status, chan, 0, 1, 0);
|
||||
send_strokes(tr, portno, status, chan, 0, 0, 1, 0);
|
||||
inpbdown[portno][chan] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1056,7 +1312,7 @@ handle_event(uint8_t *msg, uint8_t portno)
|
|||
int d = abs(inpbvalue[portno][chan] - 8192 - bend);
|
||||
if (d > step) d = step;
|
||||
if (d < step) break;
|
||||
send_strokes(tr, portno, status, chan, 0, 0, dir);
|
||||
send_strokes(tr, portno, status, chan, 0, 0, 0, dir);
|
||||
inpbvalue[portno][chan] += dir*d;
|
||||
}
|
||||
}
|
||||
|
@ -1146,11 +1402,13 @@ static char *absolute_path(char *name)
|
|||
#define CONF_FREQ 1
|
||||
#define MAX_COUNT (1000000/CONF_FREQ/POLL_INTERVAL)
|
||||
|
||||
#include <time.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
uint8_t msg[3];
|
||||
int opt, count = 0;
|
||||
int opt;
|
||||
|
||||
// Start recording the command line to be passed to Jack session management.
|
||||
add_command(argv[0]);
|
||||
|
@ -1260,6 +1518,7 @@ main(int argc, char **argv)
|
|||
int do_flush = debug_regex || debug_strokes || debug_keys || debug_midi ||
|
||||
debug_jack;
|
||||
signal(SIGINT, quitter);
|
||||
time_t t0 = time(0);
|
||||
while (!quit) {
|
||||
uint8_t portno;
|
||||
if (jack_quit) {
|
||||
|
@ -1270,16 +1529,19 @@ main(int argc, char **argv)
|
|||
}
|
||||
while (pop_midi(&seq, msg, &portno)) {
|
||||
handle_event(msg, portno);
|
||||
count = 0;
|
||||
time_t t = time(0);
|
||||
if (t > t0) {
|
||||
// Check whether to reload the config file every sec.
|
||||
if (read_config_file()) last_focused_window = 0;
|
||||
t0 = t;
|
||||
}
|
||||
}
|
||||
usleep(POLL_INTERVAL);
|
||||
if (++count >= MAX_COUNT) {
|
||||
// Check whether to reload the config file if we haven't seen any MIDI
|
||||
// input in a while. Note that if the file *is* reloaded, then we also
|
||||
// need to reset last_focused_window here, so that the translations of
|
||||
// the focused window are recomputed the next time we handle an event.
|
||||
time_t t = time(0);
|
||||
if (t > t0) {
|
||||
// Check again when polling.
|
||||
if (read_config_file()) last_focused_window = 0;
|
||||
count = 0;
|
||||
t0 = t;
|
||||
}
|
||||
// Make sure that debugging output gets flushed every once in a while (may
|
||||
// be buffered when midizap is running inside a QjackCtl session).
|
||||
|
|
12
midizap.h
12
midizap.h
|
@ -54,6 +54,8 @@ typedef struct _stroke {
|
|||
// keysym == shift == 0 => MIDI event
|
||||
int status, data; // status and, if applicable, first data byte
|
||||
int step; // step size (1, 127 or 8191 by default, depending on status)
|
||||
// discrete steps (for special "modulus" translations only)
|
||||
int n_steps, *steps;
|
||||
// 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;
|
||||
|
@ -67,10 +69,12 @@ typedef struct _stroke_data {
|
|||
uint8_t chan, data;
|
||||
// stroke data, indexed by press/release or up/down index
|
||||
stroke *s[2];
|
||||
// step size (CP, KP, CC and PB only)
|
||||
int step[2];
|
||||
// step size
|
||||
int step[2], n_steps[2], *steps[2];
|
||||
// incr flag (CC only)
|
||||
uint8_t is_incr;
|
||||
// modulus
|
||||
uint8_t mod;
|
||||
} stroke_data;
|
||||
|
||||
typedef struct _translation {
|
||||
|
@ -100,7 +104,9 @@ typedef struct _translation {
|
|||
extern void reload_callback(void);
|
||||
extern int read_config_file(void);
|
||||
extern translation *get_translation(char *win_title, char *win_class);
|
||||
extern void print_stroke_sequence(char *name, char *up_or_down, stroke *s);
|
||||
extern void print_stroke_sequence(char *name, char *up_or_down, stroke *s,
|
||||
int mod, int step, int n_steps, int *steps,
|
||||
int val);
|
||||
extern translation *default_translation, *default_midi_translation[2];
|
||||
extern int debug_regex, debug_strokes, debug_keys, debug_midi;
|
||||
extern int default_debug_regex, default_debug_strokes, default_debug_keys,
|
||||
|
|
461
readconfig.c
461
readconfig.c
|
@ -201,6 +201,7 @@ free_strokes(stroke *s)
|
|||
stroke *next;
|
||||
while (s != NULL) {
|
||||
next = s->next;
|
||||
if (s->steps) free(s->steps);
|
||||
free(s);
|
||||
s = next;
|
||||
}
|
||||
|
@ -234,13 +235,27 @@ static void free_stroke_data(stroke_data *sd, uint16_t n)
|
|||
for (i = 0; i < n; i++) {
|
||||
free_strokes(sd[i].s[0]);
|
||||
free_strokes(sd[i].s[1]);
|
||||
if (sd[i].steps[0]) free(sd[i].steps[0]);
|
||||
if (sd[i].steps[1]) free(sd[i].steps[1]);
|
||||
}
|
||||
free(sd);
|
||||
}
|
||||
|
||||
|
||||
static int *stepsdup(int n_steps, int *steps)
|
||||
{
|
||||
if (n_steps) {
|
||||
int *ret = malloc(n_steps*sizeof(int));
|
||||
memcpy(ret, steps, n_steps*sizeof(int));
|
||||
return ret;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static stroke **find_stroke_data(stroke_data **sd,
|
||||
int chan, int data, int index,
|
||||
int step, int incr,
|
||||
int step, int n_steps, int *steps,
|
||||
int incr, int mod,
|
||||
uint16_t *n, uint16_t *a)
|
||||
{
|
||||
uint16_t i;
|
||||
|
@ -248,7 +263,10 @@ static stroke **find_stroke_data(stroke_data **sd,
|
|||
if ((*sd)[i].chan == chan && (*sd)[i].data == data) {
|
||||
// existing entry
|
||||
(*sd)[i].step[index] = step;
|
||||
(*sd)[i].n_steps[index] = n_steps;
|
||||
(*sd)[i].steps[index] = stepsdup(n_steps, steps);
|
||||
(*sd)[i].is_incr = incr;
|
||||
(*sd)[i].mod = mod;
|
||||
return &(*sd)[i].s[index];
|
||||
}
|
||||
}
|
||||
|
@ -262,77 +280,91 @@ static stroke **find_stroke_data(stroke_data **sd,
|
|||
(*sd)[*n].chan = chan;
|
||||
(*sd)[*n].data = data;
|
||||
(*sd)[*n].step[index] = step;
|
||||
(*sd)[*n].n_steps[index] = n_steps;
|
||||
(*sd)[*n].steps[index] = stepsdup(n_steps, steps);
|
||||
(*sd)[*n].is_incr = incr;
|
||||
(*sd)[*n].mod = mod;
|
||||
return &(*sd)[(*n)++].s[index];
|
||||
}
|
||||
|
||||
static stroke **find_note(translation *tr, int shift,
|
||||
int chan, int data, int index)
|
||||
int chan, int data, int index, int mod,
|
||||
int step, int n_steps, int *steps)
|
||||
{
|
||||
return find_stroke_data(&tr->note[shift], chan, data, index, 0, 0,
|
||||
return find_stroke_data(&tr->note[shift], chan, data, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
&tr->n_note[shift], &tr->a_note[shift]);
|
||||
}
|
||||
|
||||
static stroke **find_pc(translation *tr, int shift,
|
||||
int chan, int data, int index)
|
||||
int chan, int data, int index)
|
||||
{
|
||||
return find_stroke_data(&tr->pc[shift], chan, data, index, 0, 0,
|
||||
return find_stroke_data(&tr->pc[shift], chan, data, index, 0, 0, 0, 0, 0,
|
||||
&tr->n_pc[shift], &tr->a_pc[shift]);
|
||||
}
|
||||
|
||||
static stroke **find_cc(translation *tr, int shift,
|
||||
int chan, int data, int index)
|
||||
int chan, int data, int index, int mod,
|
||||
int step, int n_steps, int *steps)
|
||||
{
|
||||
return find_stroke_data(&tr->cc[shift], chan, data, index, 0, 0,
|
||||
return find_stroke_data(&tr->cc[shift], chan, data, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
&tr->n_cc[shift], &tr->a_cc[shift]);
|
||||
}
|
||||
|
||||
static stroke **find_ccs(translation *tr, int shift,
|
||||
int chan, int data, int index, int step, int incr)
|
||||
{
|
||||
return find_stroke_data(&tr->ccs[shift], chan, data, index, step, incr,
|
||||
return find_stroke_data(&tr->ccs[shift], chan, data, index, step, 0, 0,
|
||||
incr, 0,
|
||||
&tr->n_ccs[shift], &tr->a_ccs[shift]);
|
||||
}
|
||||
|
||||
static stroke **find_kp(translation *tr, int shift,
|
||||
int chan, int data, int index)
|
||||
int chan, int data, int index, int mod,
|
||||
int step, int n_steps, int *steps)
|
||||
{
|
||||
return find_stroke_data(&tr->kp[shift], chan, data, index, 0, 0,
|
||||
return find_stroke_data(&tr->kp[shift], chan, data, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
&tr->n_kp[shift], &tr->a_kp[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,
|
||||
return find_stroke_data(&tr->kps[shift], chan, data, index, step, 0, 0, 0, 0,
|
||||
&tr->n_kps[shift], &tr->a_kps[shift]);
|
||||
}
|
||||
|
||||
static stroke **find_cp(translation *tr, int shift,
|
||||
int chan, int index)
|
||||
int chan, int index, int mod,
|
||||
int step, int n_steps, int *steps)
|
||||
{
|
||||
return find_stroke_data(&tr->cp[shift], chan, 0, index, 0, 0,
|
||||
return find_stroke_data(&tr->cp[shift], chan, 0, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
&tr->n_cp[shift], &tr->a_cp[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,
|
||||
return find_stroke_data(&tr->cps[shift], chan, 0, index, step, 0, 0, 0, 0,
|
||||
&tr->n_cps[shift], &tr->a_cps[shift]);
|
||||
}
|
||||
|
||||
static stroke **find_pb(translation *tr, int shift,
|
||||
int chan, int index)
|
||||
int chan, int index, int mod,
|
||||
int step, int n_steps, int *steps)
|
||||
{
|
||||
return find_stroke_data(&tr->pb[shift], chan, 0, index, 0, 0,
|
||||
return find_stroke_data(&tr->pb[shift], chan, 0, index,
|
||||
step, n_steps, steps, 0, mod,
|
||||
&tr->n_pb[shift], &tr->a_pb[shift]);
|
||||
}
|
||||
|
||||
static stroke **find_pbs(translation *tr, int shift,
|
||||
int chan, int index, int step)
|
||||
{
|
||||
return find_stroke_data(&tr->pbs[shift], chan, 0, index, step, 0,
|
||||
return find_stroke_data(&tr->pbs[shift], chan, 0, index, step, 0, 0, 0, 0,
|
||||
&tr->n_pbs[shift], &tr->a_pbs[shift]);
|
||||
}
|
||||
|
||||
|
@ -495,10 +527,39 @@ KeySym_to_string(KeySym ks)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static char *note_names[] = { "C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#", "A", "Bb", "B" };
|
||||
static char *note_name(int n)
|
||||
{
|
||||
static char *note_names[] = { "C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#", "A", "Bb", "B" };
|
||||
if (n < 0 && n%12)
|
||||
return note_names[12+n%12];
|
||||
else
|
||||
return note_names[n%12];
|
||||
}
|
||||
|
||||
static int note_octave(int n)
|
||||
{
|
||||
if (n < 0 && n%12)
|
||||
return n/12-1 + midi_octave;
|
||||
else
|
||||
return n/12 + midi_octave;
|
||||
}
|
||||
|
||||
static int datavals(int val, int step, int *steps, int n_steps)
|
||||
{
|
||||
if (val < 0)
|
||||
return -datavals(-val, step, steps, n_steps);
|
||||
else if (val < n_steps)
|
||||
return steps[val];
|
||||
else if (n_steps)
|
||||
return steps[n_steps-1];
|
||||
else if (step)
|
||||
return step*val;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
print_stroke(stroke *s)
|
||||
print_stroke(stroke *s, int mod, int step, int n_steps, int *steps, int val)
|
||||
{
|
||||
char *str;
|
||||
|
||||
|
@ -517,23 +578,54 @@ print_stroke(stroke *s)
|
|||
int channel = (s->status & 0x0f) + 1;
|
||||
switch (status) {
|
||||
case 0x90:
|
||||
if (s->step)
|
||||
printf("%s%d[%d]-%d ", note_names[s->data % 12],
|
||||
s->data / 12 + midi_octave, s->step, channel);
|
||||
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);
|
||||
} 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);
|
||||
} else if (s->step)
|
||||
printf("%s%d[%d]-%d ", note_name(s->data),
|
||||
note_octave(s->data), s->step, channel);
|
||||
else
|
||||
printf("%s%d-%d ", note_names[s->data % 12],
|
||||
s->data / 12 + midi_octave, channel);
|
||||
printf("%s%d-%d ", note_name(s->data),
|
||||
note_octave(s->data), channel);
|
||||
break;
|
||||
case 0xa0:
|
||||
if (s->step)
|
||||
printf("KP:%s%d[%d]-%d ", note_names[s->data % 12],
|
||||
s->data / 12 + midi_octave, s->step, channel);
|
||||
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);
|
||||
} 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);
|
||||
} else if (s->step)
|
||||
printf("KP:%s%d[%d]-%d ", note_name(s->data),
|
||||
note_octave(s->data), s->step, channel);
|
||||
else
|
||||
printf("KP:%s%d-%d ", note_names[s->data % 12],
|
||||
s->data / 12 + midi_octave, channel);
|
||||
printf("KP:%s%d-%d ", note_name(s->data),
|
||||
note_octave(s->data), channel);
|
||||
break;
|
||||
case 0xb0:
|
||||
if (s->step)
|
||||
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);
|
||||
} 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);
|
||||
} else if (s->step)
|
||||
printf("CC%d[%d]-%d%s ", s->data, s->step, channel, s->incr?"~":"");
|
||||
else
|
||||
printf("CC%d-%d%s ", s->data, channel, s->incr?"~":"");
|
||||
|
@ -542,13 +634,29 @@ print_stroke(stroke *s)
|
|||
printf("PC%d-%d ", s->data, channel);
|
||||
break;
|
||||
case 0xd0:
|
||||
if (s->step)
|
||||
if (mod) {
|
||||
int v = datavals(val%mod, s->step, s->steps, s->n_steps);
|
||||
printf("CP[%d]-%d ", v, channel);
|
||||
} 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);
|
||||
} else if (s->step)
|
||||
printf("CP[%d]-%d ", s->step, channel);
|
||||
else
|
||||
printf("CP-%d ", channel);
|
||||
break;
|
||||
case 0xe0:
|
||||
if (s->step)
|
||||
if (mod) {
|
||||
int v = datavals(val%mod, s->step, s->steps, s->n_steps);
|
||||
printf("PB[%d]-%d ", v, channel);
|
||||
} 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);
|
||||
} else if (s->step)
|
||||
printf("PB[%d]-%d ", s->step, channel);
|
||||
else
|
||||
printf("PB-%d ", channel);
|
||||
|
@ -561,14 +669,15 @@ print_stroke(stroke *s)
|
|||
}
|
||||
|
||||
void
|
||||
print_stroke_sequence(char *name, char *up_or_down, stroke *s)
|
||||
print_stroke_sequence(char *name, char *up_or_down, stroke *s,
|
||||
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);
|
||||
else
|
||||
printf("%s: ", name);
|
||||
while (s) {
|
||||
print_stroke(s);
|
||||
print_stroke(s, mod, step, n_steps, steps, val);
|
||||
s = s->next;
|
||||
}
|
||||
printf("\n");
|
||||
|
@ -630,7 +739,7 @@ append_shift(void)
|
|||
}
|
||||
|
||||
void
|
||||
append_midi(int status, int data, int step, int incr)
|
||||
append_midi(int status, int data, int step, int n_steps, int *steps, int incr)
|
||||
{
|
||||
stroke *s = (stroke *)allocate(sizeof(stroke));
|
||||
|
||||
|
@ -641,6 +750,8 @@ append_midi(int status, int data, int step, int incr)
|
|||
s->status = status;
|
||||
s->data = data;
|
||||
s->step = step;
|
||||
s->n_steps = n_steps;
|
||||
s->steps = stepsdup(n_steps, steps);
|
||||
s->incr = incr;
|
||||
// if this is a keystroke event, for all messages but program change (which
|
||||
// has no "on" and "off" states), mark the event as "dirty" so that the
|
||||
|
@ -781,12 +892,47 @@ static int note_number(char c, char b, int k)
|
|||
}
|
||||
}
|
||||
|
||||
static char *parse_steps(char *tok, char *p,
|
||||
int *step, int *n_steps, int **steps)
|
||||
{
|
||||
int l, n;
|
||||
if (sscanf(++p, "%d%n", &l, &n) == 1) {
|
||||
p += n;
|
||||
if (*p == ',') {
|
||||
int n_st = 1;
|
||||
static int st[128];
|
||||
st[0] = l;
|
||||
while (*p == ',') {
|
||||
if (sscanf(++p, "%d%n", &l, &n) == 1) {
|
||||
p += n;
|
||||
} else
|
||||
return 0;
|
||||
if (n_st < 128)
|
||||
st[n_st++] = l;
|
||||
else if (n_st == 128)
|
||||
fprintf(stderr, "warning: too many steps: %s\n", tok);
|
||||
}
|
||||
*n_steps = n_st;
|
||||
*steps = st;
|
||||
*step = 0;
|
||||
} else {
|
||||
*n_steps = 0;
|
||||
*steps = 0;
|
||||
*step = l;
|
||||
}
|
||||
return p;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
parse_midi(char *tok, char *s, int lhs, int mode,
|
||||
int *status, int *data, int *step, int *incr, int *dir)
|
||||
int *status, int *data, int *step, int *n_steps, int **steps,
|
||||
int *incr, int *dir, int *mod)
|
||||
{
|
||||
char *p = tok, *t;
|
||||
int n, m = -1, k = midi_channel, l;
|
||||
int n, m = -1, k = midi_channel;
|
||||
s[0] = 0;
|
||||
while (*p && !isdigit(*p) && !strchr("+-=<>~[:", *p)) p++;
|
||||
if (p == tok || p-tok > 10) return 0; // no valid token
|
||||
|
@ -826,14 +972,30 @@ parse_midi(char *tok, char *s, int lhs, int mode,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
// step size
|
||||
// step size / modulus
|
||||
*mod = 0;
|
||||
int step2 = 0, n_steps2 = 0, *steps2 = 0;
|
||||
if (*p == '[') {
|
||||
if (sscanf(++p, "%d%n", &l, &n) == 1) {
|
||||
if (!l || (lhs && l<0)) return 0; // must be nonzero / positive on lhs
|
||||
p += n;
|
||||
if ((p = parse_steps(tok, p, step, n_steps, steps))) {
|
||||
if (*n_steps) {
|
||||
// only permitted on the rhs in mod translations
|
||||
if (lhs || mode < 2) return 0;
|
||||
} else if (!*step || (lhs && *step<0))
|
||||
// must be nonzero / positive on lhs
|
||||
return 0;
|
||||
if (*p != ']') return 0;
|
||||
p++;
|
||||
*step = l;
|
||||
if (*p == '[') {
|
||||
// possible step size on lhs for mod translations (we just record it
|
||||
// here, will be resolved later)
|
||||
if ((p = parse_steps(tok, p, &step2, &n_steps2, &steps2))) {
|
||||
if (!n_steps2 && !step2) return 0; // must be nonzero
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (*p != ']') return 0;
|
||||
p++;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -841,6 +1003,8 @@ parse_midi(char *tok, char *s, int lhs, int mode,
|
|||
// sentinel value; for the lhs, this will be filled in below; for
|
||||
// the rhs this indicates the default value
|
||||
*step = 0;
|
||||
*n_steps = 0;
|
||||
*steps = 0;
|
||||
}
|
||||
// suffix with MIDI channel (not permitted with 'ch')
|
||||
if (p[0] == '-' && isdigit(p[1])) {
|
||||
|
@ -872,7 +1036,7 @@ parse_midi(char *tok, char *s, int lhs, int mode,
|
|||
// an endless, sign-bit encoder
|
||||
if (*p != '~')
|
||||
return 0;
|
||||
else if (!mode)
|
||||
else if (mode)
|
||||
fprintf(stderr, "warning: incremental flag ignored in key mode: %s\n", tok);
|
||||
*incr = 2; *dir = 0;
|
||||
}
|
||||
|
@ -886,6 +1050,8 @@ parse_midi(char *tok, char *s, int lhs, int mode,
|
|||
if (strcmp(s, "ch") == 0) {
|
||||
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
|
||||
// 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
|
||||
|
@ -895,23 +1061,28 @@ parse_midi(char *tok, char *s, int lhs, int mode,
|
|||
} else if (strcmp(s, "pb") == 0) {
|
||||
// pitch bend, no data byte
|
||||
*status = 0xe0 | k; *data = 0;
|
||||
// negative step size is always permitted on rhs here, even in key mode
|
||||
// step size only permitted on lhs if incremental
|
||||
if (lhs && *step && !*incr) return 0;
|
||||
// step size on lhs indicates modulus if non-incremental
|
||||
if (lhs && *step && !*incr) {
|
||||
*mod = *step; *step = step2;
|
||||
*n_steps = n_steps2; *steps = steps2;
|
||||
}
|
||||
if (lhs && !*step) *step = 1; // default
|
||||
return 1;
|
||||
} else if (strcmp(s, "cp") == 0) {
|
||||
// channel pressure, no data byte
|
||||
*status = 0xd0 | k; *data = 0;
|
||||
// negative step size not permitted on rhs in key mode
|
||||
if (!lhs && *step < 0 && !mode) return 0;
|
||||
// step size only permitted on lhs if incremental
|
||||
if (lhs && *step && !*incr) return 0;
|
||||
// step size on lhs indicates modulus if non-incremental
|
||||
if (lhs && *step && !*incr) {
|
||||
*mod = *step; *step = step2;
|
||||
*n_steps = n_steps2; *steps = steps2;
|
||||
}
|
||||
if (lhs && !*step) *step = 1; // default
|
||||
return 1;
|
||||
} else if (strcmp(s, "pc") == 0) {
|
||||
// program change
|
||||
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 (m < 0 || m > 127) return 0;
|
||||
*status = 0xc0 | k; *data = m;
|
||||
return 1;
|
||||
|
@ -919,27 +1090,31 @@ parse_midi(char *tok, char *s, int lhs, int mode,
|
|||
// control change
|
||||
if (m < 0 || m > 127) return 0;
|
||||
*status = 0xb0 | k; *data = m;
|
||||
// negative step size not permitted on rhs in key mode
|
||||
if (!lhs && *step < 0 && !mode) return 0;
|
||||
// step size only permitted on lhs if incremental
|
||||
if (lhs && *step && !*incr) return 0;
|
||||
// step size on lhs indicates modulus if non-incremental
|
||||
if (lhs && *step && !*incr) {
|
||||
*mod = *step; *step = step2;
|
||||
*n_steps = n_steps2; *steps = steps2;
|
||||
}
|
||||
if (lhs && !*step) *step = 1; // default
|
||||
return 1;
|
||||
} else if (strcmp(s, "kp") == 0) {
|
||||
// key pressure
|
||||
if (m < 0 || m > 127) return 0;
|
||||
*status = 0xa0 | k; *data = m;
|
||||
// negative step size not permitted on rhs in key mode
|
||||
if (!lhs && *step < 0 && !mode) return 0;
|
||||
// step size only permitted on lhs if incremental
|
||||
if (lhs && *step && !*incr) return 0;
|
||||
// step size on lhs indicates modulus if non-incremental
|
||||
if (lhs && *step && !*incr) {
|
||||
*mod = *step; *step = step2;
|
||||
*n_steps = n_steps2; *steps = steps2;
|
||||
}
|
||||
if (lhs && !*step) *step = 1; // default
|
||||
return 1;
|
||||
} else {
|
||||
// negative step size not permitted on rhs
|
||||
if (!lhs && *step < 0) return 0;
|
||||
// step size not permitted on lhs
|
||||
if (lhs && *step) return 0;
|
||||
// step size on lhs indicates modulus
|
||||
if (lhs && *step) {
|
||||
*mod = *step; *step = step2;
|
||||
*n_steps = n_steps2; *steps = steps2;
|
||||
}
|
||||
if (lhs && !*step) *step = 1; // default
|
||||
// we must be looking at a MIDI note here, with m denoting the
|
||||
// octave number; first character is the note name (must be a..g);
|
||||
// optionally, the second character may denote an accidental (# or b)
|
||||
|
@ -953,7 +1128,7 @@ parse_midi(char *tok, char *s, int lhs, int mode,
|
|||
int
|
||||
start_translation(translation *tr, char *which_key)
|
||||
{
|
||||
int k, status, data, step, incr, dir;
|
||||
int k, status, data, step, n_steps, *steps, incr, dir, mod;
|
||||
char buf[100];
|
||||
|
||||
//printf("start_translation(%s)\n", which_key);
|
||||
|
@ -970,19 +1145,29 @@ 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, &incr, &dir)) {
|
||||
if (parse_midi(which_key+k, buf, 1, 0, &status, &data, &step, &n_steps, &steps, &incr, &dir, &mod)) {
|
||||
int chan = status & 0x0f;
|
||||
mode = !!incr;
|
||||
mode = incr?0:mod?2:1;
|
||||
switch (status & 0xf0) {
|
||||
case 0x90:
|
||||
// note on/off
|
||||
first_stroke = find_note(tr, k, chan, data, 0);
|
||||
release_first_stroke = find_note(tr, k, chan, data, 1);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_note(tr, 0, chan, data, 0);
|
||||
alt_release_stroke = find_note(tr, 0, chan, data, 1);
|
||||
if (mod) {
|
||||
// note mod
|
||||
first_stroke = find_note(tr, k, chan, data, 0, mod,
|
||||
step, n_steps, steps);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_note(tr, 0, chan, data, 0, mod,
|
||||
step, n_steps, steps);
|
||||
}
|
||||
} else {
|
||||
// note on/off
|
||||
first_stroke = find_note(tr, k, chan, data, 0, 0, 0, 0, 0);
|
||||
release_first_stroke = find_note(tr, k, chan, data, 1, 0, 0, 0, 0);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_note(tr, 0, chan, data, 0, 0, 0, 0, 0);
|
||||
alt_release_stroke = find_note(tr, 0, chan, data, 1, 0, 0, 0, 0);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
}
|
||||
is_keystroke = 1;
|
||||
break;
|
||||
case 0xc0:
|
||||
// pc: To make our live easier and for consistency with the other
|
||||
|
@ -999,16 +1184,7 @@ start_translation(translation *tr, char *which_key)
|
|||
is_keystroke = 1;
|
||||
break;
|
||||
case 0xb0:
|
||||
if (!incr) {
|
||||
// cc on/off
|
||||
first_stroke = find_cc(tr, k, chan, data, 0);
|
||||
release_first_stroke = find_cc(tr, k, chan, data, 1);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_cc(tr, 0, chan, data, 0);
|
||||
alt_release_stroke = find_cc(tr, 0, chan, data, 1);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
} else {
|
||||
if (incr) {
|
||||
// cc (step up, down)
|
||||
if (step <= 0) {
|
||||
fprintf(stderr, "zero or negative step size not permitted here: [%s]%s\n", current_translation, which_key);
|
||||
|
@ -1032,19 +1208,27 @@ start_translation(translation *tr, char *which_key)
|
|||
alt_release_stroke = find_ccs(tr, 0, chan, data, 1, step, incr>1);
|
||||
}
|
||||
}
|
||||
} else if (mod) {
|
||||
// cc mod
|
||||
first_stroke = find_cc(tr, k, chan, data, 0, mod,
|
||||
step, n_steps, steps);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_cc(tr, 0, chan, data, 0, mod,
|
||||
step, n_steps, steps);
|
||||
}
|
||||
} else {
|
||||
// cc on/off
|
||||
first_stroke = find_cc(tr, k, chan, data, 0, 0, 0, 0, 0);
|
||||
release_first_stroke = find_cc(tr, k, chan, data, 1, 0, 0, 0, 0);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_cc(tr, 0, chan, data, 0, 0, 0, 0, 0);
|
||||
alt_release_stroke = find_cc(tr, 0, chan, data, 1, 0, 0, 0, 0);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
}
|
||||
break;
|
||||
case 0xa0:
|
||||
if (!incr) {
|
||||
// kp on/off
|
||||
first_stroke = find_kp(tr, k, chan, data, 0);
|
||||
release_first_stroke = find_kp(tr, k, chan, data, 1);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_kp(tr, 0, chan, data, 0);
|
||||
alt_release_stroke = find_kp(tr, 0, chan, data, 1);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
} else {
|
||||
if (incr) {
|
||||
// kp (step up, down)
|
||||
if (step <= 0) {
|
||||
fprintf(stderr, "zero or negative step size not permitted here: [%s]%s\n", current_translation, which_key);
|
||||
|
@ -1061,19 +1245,27 @@ start_translation(translation *tr, char *which_key)
|
|||
alt_release_stroke = find_kps(tr, 0, chan, data, 1, step);
|
||||
}
|
||||
}
|
||||
} else if (mod) {
|
||||
// kp mod
|
||||
first_stroke = find_kp(tr, k, chan, data, 0, mod,
|
||||
step, n_steps, steps);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_kp(tr, 0, chan, data, 0, mod,
|
||||
step, n_steps, steps);
|
||||
}
|
||||
} else {
|
||||
// kp on/off
|
||||
first_stroke = find_kp(tr, k, chan, data, 0, 0, 0, 0, 0);
|
||||
release_first_stroke = find_kp(tr, k, chan, data, 1, 0, 0, 0, 0);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_kp(tr, 0, chan, data, 0, 0, 0, 0, 0);
|
||||
alt_release_stroke = find_kp(tr, 0, chan, data, 1, 0, 0, 0, 0);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
}
|
||||
break;
|
||||
case 0xd0:
|
||||
if (!incr) {
|
||||
// cp on/off
|
||||
first_stroke = find_cp(tr, k, chan, 0);
|
||||
release_first_stroke = find_cp(tr, k, chan, 1);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_cp(tr, 0, chan, 0);
|
||||
alt_release_stroke = find_cp(tr, 0, chan, 1);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
} else {
|
||||
if (incr) {
|
||||
// cp (step up, down)
|
||||
if (step <= 0) {
|
||||
fprintf(stderr, "zero or negative step size not permitted here: [%s]%s\n", current_translation, which_key);
|
||||
|
@ -1090,19 +1282,27 @@ start_translation(translation *tr, char *which_key)
|
|||
alt_release_stroke = find_cps(tr, 0, chan, 1, step);
|
||||
}
|
||||
}
|
||||
} else if (mod) {
|
||||
// cp mod
|
||||
first_stroke = find_cp(tr, k, chan, 0, mod,
|
||||
step, n_steps, steps);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_cp(tr, 0, chan, 0, mod,
|
||||
step, n_steps, steps);
|
||||
}
|
||||
} else {
|
||||
// cp on/off
|
||||
first_stroke = find_cp(tr, k, chan, 0, 0, 0, 0, 0);
|
||||
release_first_stroke = find_cp(tr, k, chan, 1, 0, 0, 0, 0);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_cp(tr, 0, chan, 0, 0, 0, 0, 0);
|
||||
alt_release_stroke = find_cp(tr, 0, chan, 1, 0, 0, 0, 0);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
}
|
||||
break;
|
||||
case 0xe0:
|
||||
if (!incr) {
|
||||
// pb on/off
|
||||
first_stroke = find_pb(tr, k, chan, 0);
|
||||
release_first_stroke = find_pb(tr, k, chan, 1);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_pb(tr, 0, chan, 0);
|
||||
alt_release_stroke = find_pb(tr, 0, chan, 1);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
} else {
|
||||
if (incr) {
|
||||
// pb (step up, down)
|
||||
if (step <= 0) {
|
||||
fprintf(stderr, "zero or negative step size not permitted here: [%s]%s\n", current_translation, which_key);
|
||||
|
@ -1119,6 +1319,23 @@ start_translation(translation *tr, char *which_key)
|
|||
alt_release_stroke = find_pbs(tr, 0, chan, 1, step);
|
||||
}
|
||||
}
|
||||
} else if (mod) {
|
||||
// pb mod
|
||||
first_stroke = find_pb(tr, k, chan, 0, mod,
|
||||
step, n_steps, steps);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_pb(tr, 0, chan, 0, mod,
|
||||
step, n_steps, steps);
|
||||
}
|
||||
} else {
|
||||
// pb on/off
|
||||
first_stroke = find_pb(tr, k, chan, 0, 0, 0, 0, 0);
|
||||
release_first_stroke = find_pb(tr, k, chan, 1, 0, 0, 0, 0);
|
||||
if (is_anyshift) {
|
||||
alt_press_stroke = find_pb(tr, 0, chan, 0, 0, 0, 0, 0);
|
||||
alt_release_stroke = find_pb(tr, 0, chan, 1, 0, 0, 0, 0);
|
||||
}
|
||||
is_keystroke = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1187,7 +1404,7 @@ 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->incr);
|
||||
append_midi(s->status, s->data, s->step, s->n_steps, s->steps, s->incr);
|
||||
s->dirty = 0;
|
||||
}
|
||||
s = s->next;
|
||||
|
@ -1209,7 +1426,7 @@ add_release(int all_keys)
|
|||
} else if (s->shift) {
|
||||
append_shift();
|
||||
} else {
|
||||
append_midi(s->status, s->data, s->step, s->incr);
|
||||
append_midi(s->status, s->data, s->step, s->n_steps, s->steps, s->incr);
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
|
@ -1224,7 +1441,7 @@ add_release(int all_keys)
|
|||
} else if (s->shift) {
|
||||
append_shift();
|
||||
} else {
|
||||
append_midi(s->status, s->data, s->step, s->incr);
|
||||
append_midi(s->status, s->data, s->step, s->n_steps, s->steps, s->incr);
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
|
@ -1237,7 +1454,7 @@ add_release(int all_keys)
|
|||
} else if (s->shift) {
|
||||
append_shift();
|
||||
} else {
|
||||
append_midi(s->status, s->data, s->step, s->incr);
|
||||
append_midi(s->status, s->data, s->step, s->n_steps, s->steps, s->incr);
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
|
@ -1276,16 +1493,16 @@ add_string(char *str)
|
|||
void
|
||||
add_midi(char *tok)
|
||||
{
|
||||
int status, data, step, incr, dir = 0;
|
||||
int status, data, step, n_steps, *steps, incr, dir = 0, mod = 0;
|
||||
char buf[100];
|
||||
if (parse_midi(tok, buf, 0, mode, &status, &data, &step, &incr, &dir)) {
|
||||
if (parse_midi(tok, buf, 0, mode, &status, &data, &step, &n_steps, &steps, &incr, &dir, &mod)) {
|
||||
if (status == 0) {
|
||||
// 'ch' token; this doesn't actually generate any output, it just sets
|
||||
// the default MIDI channel
|
||||
midi_channel = data;
|
||||
} else {
|
||||
if ((status & 0xf0) != 0xe0 || step != 0)
|
||||
append_midi(status, data, step, incr!=0);
|
||||
append_midi(status, data, step, n_steps, steps, incr!=0);
|
||||
else
|
||||
fprintf(stderr, "zero step size not permitted: %s\n", tok);
|
||||
}
|
||||
|
@ -1309,10 +1526,10 @@ finish_translation(void)
|
|||
add_release(1);
|
||||
if (debug_strokes) {
|
||||
if (is_keystroke) {
|
||||
print_stroke_sequence(key_name, "D", *press_first_stroke);
|
||||
print_stroke_sequence(key_name, "U", *release_first_stroke);
|
||||
print_stroke_sequence(key_name, "D", *press_first_stroke, 0, 0, 0, 0, 0);
|
||||
print_stroke_sequence(key_name, "U", *release_first_stroke, 0, 0, 0, 0, 0);
|
||||
} else {
|
||||
print_stroke_sequence(key_name, "", *first_stroke);
|
||||
print_stroke_sequence(key_name, "", *first_stroke, 0, 0, 0, 0, 0);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue