From bbeade8898200a8024169ece30c620016fd5eaf1 Mon Sep 17 00:00:00 2001 From: cbdev Date: Thu, 1 Aug 2019 20:58:21 +0200 Subject: Implement midi backend detect option --- backends/evdev.md | 2 +- backends/midi.c | 41 +++++++++++++++++++++++++++++++++++------ backends/midi.md | 1 + 3 files changed, 37 insertions(+), 7 deletions(-) (limited to 'backends') diff --git a/backends/evdev.md b/backends/evdev.md index 88dfc85..d57201d 100644 --- a/backends/evdev.md +++ b/backends/evdev.md @@ -9,7 +9,7 @@ This functionality may require elevated privileges (such as special group member | Option | Example value | Default value | Description | |---------------|-----------------------|-----------------------|-----------------------| -| `detect` | `on` | `off` | Output the channel specification for all events coming in on configured instances to help with configuration. | +| `detect` | `on` | `off` | Output channel specifications for any events coming in on configured instances to help with configuration. | #### Instance configuration diff --git a/backends/midi.c b/backends/midi.c index 2999e6b..c1480c0 100644 --- a/backends/midi.c +++ b/backends/midi.c @@ -31,6 +31,12 @@ enum /*_midi_channel_type*/ { sysmsg }; +static struct { + uint8_t detect; +} midi_config = { + .detect = 0 +}; + int init(){ backend midi = { .name = BACKEND_NAME, @@ -55,8 +61,8 @@ int init(){ return 1; } - snd_seq_nonblock(sequencer, 1); - + snd_seq_nonblock(sequencer, 1); + fprintf(stderr, "MIDI client ID is %d\n", snd_seq_client_id(sequencer)); return 0; } @@ -70,6 +76,14 @@ static int midi_configure(char* option, char* value){ return 0; } + if(!strcmp(option, "detect")){ + midi_config.detect = 1; + if(!strcmp(value, "off")){ + midi_config.detect = 0; + } + return 0; + } + fprintf(stderr, "Unknown MIDI backend option %s\n", option); return 1; } @@ -214,7 +228,7 @@ static int midi_set(instance* inst, size_t num, channel** c, channel_value* v){ snd_seq_ev_set_source(&ev, data->port); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); - + switch(ident.fields.type){ case note: snd_seq_ev_set_noteon(&ev, ident.fields.channel, ident.fields.control, v[u].normalised * 127.0); @@ -224,7 +238,6 @@ static int midi_set(instance* inst, size_t num, channel** c, channel_value* v){ break; case pressure: snd_seq_ev_set_keypress(&ev, ident.fields.channel, ident.fields.control, v[u].normalised * 127.0); - break; case pitchbend: snd_seq_ev_set_pitchbend(&ev, ident.fields.channel, (v[u].normalised * 16383.0) - 8192); @@ -249,6 +262,7 @@ static int midi_handle(size_t num, managed_fd* fds){ instance* inst = NULL; channel* changed = NULL; channel_value val; + char* event_type = NULL; midi_channel_ident ident = { .label = 0 }; @@ -258,6 +272,7 @@ static int midi_handle(size_t num, managed_fd* fds){ } while(snd_seq_event_input(sequencer, &ev) > 0){ + event_type = NULL; ident.label = 0; switch(ev->type){ case SND_SEQ_EVENT_NOTEON: @@ -267,22 +282,26 @@ static int midi_handle(size_t num, managed_fd* fds){ ident.fields.channel = ev->data.note.channel; ident.fields.control = ev->data.note.note; val.normalised = (double)ev->data.note.velocity / 127.0; + event_type = "note"; break; case SND_SEQ_EVENT_KEYPRESS: ident.fields.type = pressure; ident.fields.channel = ev->data.note.channel; ident.fields.control = ev->data.note.note; val.normalised = (double)ev->data.note.velocity / 127.0; + event_type = "pressure"; break; case SND_SEQ_EVENT_CHANPRESS: ident.fields.type = aftertouch; ident.fields.channel = ev->data.control.channel; val.normalised = (double)ev->data.control.value / 127.0; + event_type = "aftertouch"; break; case SND_SEQ_EVENT_PITCHBEND: ident.fields.type = pitchbend; ident.fields.channel = ev->data.control.channel; val.normalised = ((double)ev->data.control.value + 8192) / 16383.0; + event_type = "pitch"; break; case SND_SEQ_EVENT_CONTROLLER: ident.fields.type = cc; @@ -290,6 +309,7 @@ static int midi_handle(size_t num, managed_fd* fds){ ident.fields.control = ev->data.control.param; val.raw.u64 = ev->data.control.value; val.normalised = (double)ev->data.control.value / 127.0; + event_type = "cc"; break; case SND_SEQ_EVENT_CONTROL14: case SND_SEQ_EVENT_NONREGPARAM: @@ -318,6 +338,15 @@ static int midi_handle(size_t num, managed_fd* fds){ return 1; } } + + if(midi_config.detect && event_type){ + if(ident.fields.type == pitchbend || ident.fields.type == aftertouch){ + fprintf(stderr, "Incoming MIDI data on channel %s.ch%d.%s\n", inst->name, ident.fields.channel, event_type); + } + else{ + fprintf(stderr, "Incoming MIDI data on channel %s.ch%d.%s%d\n", inst->name, ident.fields.channel, event_type, ident.fields.control); + } + } } free(ev); return 0; @@ -375,13 +404,13 @@ static int midi_start(){ } //register all fds to core - nfds = snd_seq_poll_descriptors_count(sequencer, POLLIN | POLLOUT); + nfds = snd_seq_poll_descriptors_count(sequencer, POLLIN | POLLOUT); pfds = calloc(nfds, sizeof(struct pollfd)); if(!pfds){ fprintf(stderr, "Failed to allocate memory\n"); goto bail; } - nfds = snd_seq_poll_descriptors(sequencer, pfds, nfds, POLLIN | POLLOUT); + nfds = snd_seq_poll_descriptors(sequencer, pfds, nfds, POLLIN | POLLOUT); fprintf(stderr, "MIDI backend registering %d descriptors to core\n", nfds); for(p = 0; p < nfds; p++){ diff --git a/backends/midi.md b/backends/midi.md index 9733cc2..5e295ee 100644 --- a/backends/midi.md +++ b/backends/midi.md @@ -7,6 +7,7 @@ The MIDI backend provides read-write access to the MIDI protocol via virtual por | Option | Example value | Default value | Description | |---------------|-----------------------|-----------------------|-----------------------| | `name` | `MIDIMonster` | none | MIDI client name | +| `detect` | `on` | `off` | Output channel specifications for any events coming in on configured instances to help with configuration. | #### Instance configuration -- cgit v1.2.3