aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2020-07-26 23:01:35 +0200
committercbdev <cb@cbcdn.com>2020-07-26 23:01:35 +0200
commit6291031a98539bdf51262329b0dc20604c2bad70 (patch)
treec2ef603daf134a2c477d50b814c05215b464ed4d
parent897e6f2e84e80f2109c5cb553b5fe15e7ce4ad50 (diff)
downloadmidimonster-6291031a98539bdf51262329b0dc20604c2bad70.tar.gz
midimonster-6291031a98539bdf51262329b0dc20604c2bad70.tar.bz2
midimonster-6291031a98539bdf51262329b0dc20604c2bad70.zip
Implement rudimentary detect mode for sACN (#70)
-rw-r--r--backends/sacn.c39
-rw-r--r--backends/sacn.h1
-rw-r--r--backends/sacn.md1
-rw-r--r--configs/launchctl-sacn.cfg3
4 files changed, 40 insertions, 4 deletions
diff --git a/backends/sacn.c b/backends/sacn.c
index 170769f..247dfc7 100644
--- a/backends/sacn.c
+++ b/backends/sacn.c
@@ -1,4 +1,5 @@
#define BACKEND_NAME "sacn"
+#define DEBUG
#include <string.h>
#include <sys/types.h>
@@ -29,13 +30,15 @@ static struct /*_sacn_global_config*/ {
sacn_fd* fd;
uint64_t last_announce;
uint32_t next_frame;
+ uint8_t detect;
} global_cfg = {
.source_name = "MIDIMonster",
.cid = {'M', 'I', 'D', 'I', 'M', 'o', 'n', 's', 't', 'e', 'r'},
.fds = 0,
.fd = NULL,
.last_announce = 0,
- .next_frame = 0
+ .next_frame = 0,
+ .detect = 0
};
MM_PLUGIN_API int init(){
@@ -130,6 +133,16 @@ static int sacn_configure(char* option, char* value){
global_cfg.cid[u] = (strtoul(next, &next, 0) & 0xFF);
}
}
+ else if(!strcmp(option, "detect")){
+ global_cfg.detect = 0;
+ if(!strcmp(value, "on")){
+ global_cfg.detect = 1;
+ }
+ else if(!strcmp(value, "verbose")){
+ global_cfg.detect = 2;
+ }
+ return 0;
+ }
else if(!strcmp(option, "bind")){
mmbackend_parse_hostspec(value, &host, &port, &next);
@@ -138,8 +151,13 @@ static int sacn_configure(char* option, char* value){
return 1;
}
- if(next && !strncmp(next, "local", 5)){
- flags = mcast_loop;
+ //parse additional socket options
+ if(next){
+ for(next = strtok(next, " "); next; next = strtok(NULL, " ")){
+ if(!strcmp(next, "local")){
+ flags |= mcast_loop;
+ }
+ }
}
if(sacn_listener(host, port ? port : SACN_PORT, flags)){
@@ -401,6 +419,9 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame
//source filtering
if(inst_data->filter_enabled && memcmp(inst_data->cid_filter, frame->sender_cid, 16)){
+ if(global_cfg.detect > 1){
+ LOGPF("Discarding data for instance %s due to source filter rule", inst->name);
+ }
return 0;
}
@@ -418,11 +439,19 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame
//handle source priority (currently a 1-bit counter)
if(inst_data->data.last_priority > data->priority){
+ if(global_cfg.detect > 1){
+ LOGPF("Ignoring lower-priority (%d) source on %s, current source is %d", data->priority, inst->name, inst_data->data.last_priority);
+ }
inst_data->data.last_priority = data->priority;
return 0;
}
inst_data->data.last_priority = data->priority;
+ if(!inst_data->last_input && global_cfg.detect){
+ LOGPF("Valid data on instance %s (Universe %u): Source name %.*s, priority %d", inst->name, inst_data->uni, 64, data->source_name, data->priority);
+ }
+ inst_data->last_input = mm_timestamp();
+
//read data (except start code), mark changed channels
for(u = 1; u < be16toh(data->channels); u++){
if(IS_ACTIVE(inst_data->data.map[u - 1])
@@ -583,6 +612,10 @@ static int sacn_handle(size_t num, managed_fd* fds){
if(inst && sacn_process_frame(inst, frame, data)){
LOG("Failed to process frame");
}
+ else if(!inst && global_cfg.detect > 1){
+ //this will only happen with unicast input
+ LOGPF("Received data for unconfigured universe %d on descriptor %" PRIsize_t, be16toh(data->universe), ((uint64_t) fds[u].impl) & 0xFFFF);
+ }
}
}
} while(bytes_read > 0);
diff --git a/backends/sacn.h b/backends/sacn.h
index 4138f45..0c44ebc 100644
--- a/backends/sacn.h
+++ b/backends/sacn.h
@@ -40,6 +40,7 @@ typedef struct /*_sacn_universe_model*/ {
} sacn_universe;
typedef struct /*_sacn_instance_model*/ {
+ uint32_t last_input;
uint16_t uni;
uint8_t realtime;
uint8_t xmit_prio;
diff --git a/backends/sacn.md b/backends/sacn.md
index 598f430..3bc5b72 100644
--- a/backends/sacn.md
+++ b/backends/sacn.md
@@ -11,6 +11,7 @@ containing all write-enabled universes.
| `name` | `sACN source` | `MIDIMonster` | sACN source name |
| `cid` | `0xAA 0xBB 0xCC` ... | `MIDIMonster` | Source CID (16 bytes) |
| `bind` | `0.0.0.0 5568` | none | Binds a network address to listen for data. This option may be set multiple times, with each descriptor being assigned an index starting from 0 to be used with the `interface` instance configuration option. At least one descriptor is required for operation. |
+| `detect` | `on`, `verbose` | `off` | Output additional information on incoming and outgoing data packets to help with configuring complex scenarios. |
The `bind` configuration value can be extended by the keyword `local` to allow software on the
local host to process the sACN output frames from the MIDIMonster (e.g. `bind = 0.0.0.0 5568 local`).
diff --git a/configs/launchctl-sacn.cfg b/configs/launchctl-sacn.cfg
index 10a736a..612ac25 100644
--- a/configs/launchctl-sacn.cfg
+++ b/configs/launchctl-sacn.cfg
@@ -7,7 +7,8 @@
name = MIDIMonster
[backend sacn]
-bind = 0.0.0.0 5568 local
+bind = 0.0.0.0 5568
+detect = verbose
[midi lc]
read = Launch Control