aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2019-08-01 20:58:21 +0200
committercbdev <cb@cbcdn.com>2019-08-01 20:58:21 +0200
commitbbeade8898200a8024169ece30c620016fd5eaf1 (patch)
tree889b75be9fcbc8251cb05972c7fb40ac6e6e650f
parenta23ce7718ab61e73586d2738329d6bbace0b764b (diff)
downloadmidimonster-bbeade8898200a8024169ece30c620016fd5eaf1.tar.gz
midimonster-bbeade8898200a8024169ece30c620016fd5eaf1.tar.bz2
midimonster-bbeade8898200a8024169ece30c620016fd5eaf1.zip
Implement midi backend detect option
-rw-r--r--README.md2
-rw-r--r--backends/evdev.md2
-rw-r--r--backends/midi.c41
-rw-r--r--backends/midi.md1
4 files changed, 38 insertions, 8 deletions
diff --git a/README.md b/README.md
index d64190f..8a0d7f9 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ on any other (or the same) supported protocol, for example to:
* Dynamically route and modify events using the Lua programming language ([Example configuration](configs/lua.cfg) and [Script](configs/demo.lua)) to create your own lighting controller or run effects on TouchOSC (Flying faders demo [configuration](configs/flying-faders.cfg) and [script](configs/flying-faders.lua))
* Use an OSC app as a simple lighting controller via ArtNet or sACN
* Visualize ArtNet data using OSC tools
-* Control lighting fixtures or DAWs using gamepad controllers ([Example configuration](configs/evdev.conf))
+* Control lighting fixtures or DAWs using gamepad controllers, trackballs, etc ([Example configuration](configs/evdev.conf))
* Play games or type using MIDI controllers
[![Build Status](https://travis-ci.com/cbdevnet/midimonster.svg?branch=master)](https://travis-ci.com/cbdevnet/midimonster) [![Coverity Scan Build Status](https://scan.coverity.com/projects/15168/badge.svg)](https://scan.coverity.com/projects/15168)
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