aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2021-01-10 19:10:01 +0100
committercbdev <cb@cbcdn.com>2021-01-10 19:10:01 +0100
commit8ff86335bc9f5233564a0f791174a9cc49ae2df4 (patch)
tree7fba06d7df4bbfa59e0af0203a492bbc21f2ee25
parenta3a893f6b8b6c10ff281fcdfe0b4a4ddafe89023 (diff)
downloadmidimonster-8ff86335bc9f5233564a0f791174a9cc49ae2df4.tar.gz
midimonster-8ff86335bc9f5233564a0f791174a9cc49ae2df4.tar.bz2
midimonster-8ff86335bc9f5233564a0f791174a9cc49ae2df4.zip
Implement program change control for the rtpmidi backend (#79)
-rw-r--r--backends/rtpmidi.c23
-rw-r--r--backends/rtpmidi.h3
-rw-r--r--backends/rtpmidi.md4
3 files changed, 20 insertions, 10 deletions
diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c
index 7c5aa69..8d5525c 100644
--- a/backends/rtpmidi.c
+++ b/backends/rtpmidi.c
@@ -427,6 +427,8 @@ static char* rtpmidi_type_name(uint8_t type){
return "aftertouch";
case pitchbend:
return "pitch";
+ case program:
+ return "program";
}
return "unknown";
}
@@ -552,7 +554,7 @@ static int rtpmidi_peer_applecommand(instance* inst, size_t peer, uint8_t contro
memcpy(&dest_addr, &(data->peer[peer].dest), min(sizeof(dest_addr), data->peer[peer].dest_len));
if(control){
- //calculate remote control port from data port
+ //calculate remote control port from data port
((struct sockaddr_in*) &dest_addr)->sin_port = htobe16(be16toh(((struct sockaddr_in*) &dest_addr)->sin_port) - 1);
}
@@ -715,6 +717,9 @@ static channel* rtpmidi_channel(instance* inst, char* spec, uint8_t flags){
else if(!strncmp(next_token, "aftertouch", 10)){
ident.fields.type = aftertouch;
}
+ else if(!strncmp(next_token, "program", 7)){
+ ident.fields.type = program;
+ }
else{
LOGPF("Unknown control type in spec %s", spec);
return NULL;
@@ -761,11 +766,11 @@ static int rtpmidi_set(instance* inst, size_t num, channel** c, channel_value* v
payload[3] = v[u].normalised * 127.0;
if(ident.fields.type == pitchbend){
- payload[2] = ((int)(v[u].normalised * 16384.0)) & 0x7F;
- payload[3] = (((int)(v[u].normalised * 16384.0)) >> 7) & 0x7F;
+ payload[2] = ((int)(v[u].normalised * 16383.0)) & 0x7F;
+ payload[3] = (((int)(v[u].normalised * 16383.0)) >> 7) & 0x7F;
}
- //channel-wide aftertouch is only 2 bytes
- else if(ident.fields.type == aftertouch){
+ //channel-wides aftertouch and program are only 2 bytes
+ else if(ident.fields.type == aftertouch || ident.fields.type == program){
payload[2] = payload[3];
payload -= 1;
offset -= 1;
@@ -996,7 +1001,7 @@ static int rtpmidi_parse(instance* inst, uint8_t* frame, size_t bytes){
ident.fields.channel = midi_status & 0x0F;
//single byte command
- if(ident.fields.type == aftertouch){
+ if(ident.fields.type == aftertouch || ident.fields.type == program){
ident.fields.control = 0;
val.normalised = (double) frame[offset] / 127.0;
offset++;
@@ -1010,7 +1015,7 @@ static int rtpmidi_parse(instance* inst, uint8_t* frame, size_t bytes){
if(ident.fields.type == pitchbend){
ident.fields.control = 0;
- val.normalised = (double)((frame[offset] << 7) | frame[offset - 1]) / 16384.0;
+ val.normalised = (double)((frame[offset] << 7) | frame[offset - 1]) / 16383.0;
}
else{
ident.fields.control = frame[offset - 1];
@@ -1030,7 +1035,9 @@ static int rtpmidi_parse(instance* inst, uint8_t* frame, size_t bytes){
ident.fields.type, ident.fields.channel, ident.fields.control, val.normalised);
if(cfg.detect){
- if(ident.fields.type == pitchbend || ident.fields.type == aftertouch){
+ if(ident.fields.type == pitchbend
+ || ident.fields.type == aftertouch
+ || ident.fields.type == program){
LOGPF("Incoming data on channel %s.ch%d.%s, value %f",
inst->name, ident.fields.channel,
rtpmidi_type_name(ident.fields.type), val.normalised);
diff --git a/backends/rtpmidi.h b/backends/rtpmidi.h
index 7e6eccc..5f1621e 100644
--- a/backends/rtpmidi.h
+++ b/backends/rtpmidi.h
@@ -35,8 +35,9 @@ static int rtpmidi_shutdown(size_t n, instance** inst);
enum /*_rtpmidi_channel_type*/ {
none = 0,
note = 0x90,
- cc = 0xB0,
pressure = 0xA0,
+ cc = 0xB0,
+ program = 0xC0,
aftertouch = 0xD0,
pitchbend = 0xE0
};
diff --git a/backends/rtpmidi.md b/backends/rtpmidi.md
index 82548bf..9f56f3d 100644
--- a/backends/rtpmidi.md
+++ b/backends/rtpmidi.md
@@ -63,11 +63,12 @@ The `rtpmidi` backend supports mapping different MIDI events to MIDIMonster chan
* `pressure` - Note pressure/aftertouch messages
* `aftertouch` - Channel-wide aftertouch messages
* `pitch` - Channel pitchbend messages
+* `program` - Channel program change messages
A MIDIMonster channel is specified using the syntax `channel<channel>.<type><index>`. The shorthand `ch` may be
used instead of the word `channel` (Note that `channel` here refers to the MIDI channel number).
-The `pitch` and `aftertouch` events are channel-wide, thus they can be specified as `channel<channel>.<type>`.
+The `pitch`, `aftertouch` program messages/events are channel-wide, thus they can be specified as `channel<channel>.<type>`.
MIDI channels range from `0` to `15`. Each MIDI channel consists of 128 notes (numbered `0` through `127`), which
additionally each have a pressure control, 128 CC's (numbered likewise), a channel pressure control (also called
@@ -80,6 +81,7 @@ rmidi1.ch0.note9 > rmidi2.channel1.cc4
rmidi1.channel15.pressure1 > rmidi1.channel0.note0
rmidi1.ch1.aftertouch > rmidi2.ch2.cc0
rmidi1.ch0.pitch > rmidi2.ch1.pitch
+rmidi2.ch15.note1 > rmidi2.ch2.program
```
#### Known bugs / problems