aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2018-03-01 17:09:21 +0100
committercbdev <cb@cbcdn.com>2018-03-01 17:09:21 +0100
commitb266b47ec7da4a1d307c6389d43034e75a71d0be (patch)
treee4c42b8690bb9912c8958ace1c94debd8956e911
parent2477edba0ae270a337f284ac7862d172f66a0303 (diff)
downloadmidimonster-b266b47ec7da4a1d307c6389d43034e75a71d0be.tar.gz
midimonster-b266b47ec7da4a1d307c6389d43034e75a71d0be.tar.bz2
midimonster-b266b47ec7da4a1d307c6389d43034e75a71d0be.zip
Implement sACN universe discovery, update configuration syntax
-rw-r--r--sacn.c63
-rw-r--r--sacn.h9
2 files changed, 65 insertions, 7 deletions
diff --git a/sacn.c b/sacn.c
index e12157e..b807e2b 100644
--- a/sacn.c
+++ b/sacn.c
@@ -226,7 +226,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){
data->uni = strtoul(value, NULL, 10);
return 0;
}
- else if(!strcmp(option, "iface")){
+ else if(!strcmp(option, "interface")){
data->fd_index = strtoul(value, NULL, 10);
if(data->fd_index >= global_cfg.fds){
@@ -239,7 +239,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){
data->xmit_prio = strtoul(value, NULL, 10);
return 0;
}
- else if(!strcmp(option, "dest")){
+ else if(!strcmp(option, "destination")){
if(sacn_parse_hostspec(value, &host, &port, NULL)){
fprintf(stderr, "Not a valid sACN destination for instance %s: %s\n", inst->name, value);
return 1;
@@ -474,6 +474,54 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame
return 0;
}
+static void sacn_discovery(size_t fd){
+ size_t page = 0, pages = (global_cfg.fd[fd].universes / 512) + 1, universes;
+ struct sockaddr_in discovery_dest = {
+ .sin_family = AF_INET,
+ .sin_port = htobe16(SACN_PORT),
+ .sin_addr.s_addr = htobe32(((uint32_t) 0xefff0000) | 64214)
+ };
+
+ sacn_discovery_pdu pdu = {
+ .root = {
+ .preamble_size = htobe16(0x10),
+ .postamble_size = 0,
+ .magic = { 0 }, //memcpy'd
+ .flags = 0, //filled later
+ .vector = htobe32(ROOT_E131_EXTENDED),
+ .sender_cid = { 0 }, //memcpy'd
+ .frame_flags = 0, //filled later
+ .frame_vector = htobe32(FRAME_E131_DISCOVERY)
+ },
+ .data = {
+ .source_name = "", //memcpy'd
+ .flags = 0, //filled later
+ .vector = htobe32(DISCOVERY_UNIVERSE_LIST),
+ .page = 0, //filled later
+ .max_page = pages - 1,
+ .data = { 0 } //memcpy'd
+ }
+ };
+
+ memcpy(pdu.root.magic, SACN_PDU_MAGIC, sizeof(pdu.root.magic));
+ memcpy(pdu.root.sender_cid, global_cfg.cid, sizeof(pdu.root.sender_cid));
+ memcpy(pdu.data.source_name, global_cfg.source_name, sizeof(pdu.data.source_name));
+
+ for(; page < pages; page++){
+ universes = (global_cfg.fd[fd].universes - page * 512 >= 512) ? 512 : (global_cfg.fd[fd].universes % 512);
+ pdu.root.flags = htobe16(0x7000 | (104 + universes * sizeof(uint16_t)));
+ pdu.root.frame_flags = htobe16(0x7000 | (82 + universes * sizeof(uint16_t)));
+ pdu.data.flags = htobe16(0x7000 | (8 + universes * sizeof(uint16_t)));
+
+ pdu.data.page = page;
+ memcpy(pdu.data.data, global_cfg.fd[fd].universe + page * 512, universes);
+
+ if(sendto(global_cfg.fd[fd].fd, &pdu, sizeof(pdu) - (512 - universes) * sizeof(uint16_t), 0, (struct sockaddr*) &discovery_dest, sizeof(discovery_dest)) < 0){
+ fprintf(stderr, "Failed to output sACN universe discovery frame for interface %zu: %s\n", fd, strerror(errno));
+ }
+ }
+}
+
static int sacn_handle(size_t num, managed_fd* fds){
size_t u;
ssize_t bytes_read;
@@ -485,9 +533,14 @@ static int sacn_handle(size_t num, managed_fd* fds){
sacn_frame_root* frame = (sacn_frame_root*) recv_buf;
sacn_frame_data* data = (sacn_frame_data*) (recv_buf + sizeof(sacn_frame_root));
- if(global_cfg.last_announce > SACN_DISCOVERY_TIMEOUT){
- //TODO send universe discovery pdu
- //TODO this requires the core to provide time deltas
+ if(mm_timestamp() - global_cfg.last_announce > SACN_DISCOVERY_TIMEOUT){
+ //send universe discovery pdu
+ for(u = 0; u < global_cfg.fds; u++){
+ if(global_cfg.fd[u].universes){
+ sacn_discovery(u);
+ }
+ }
+ global_cfg.last_announce = mm_timestamp();
}
//early exit
diff --git a/sacn.h b/sacn.h
index 6355550..7804eaf 100644
--- a/sacn.h
+++ b/sacn.h
@@ -13,7 +13,7 @@ static int sacn_shutdown();
#define SACN_PORT "5568"
#define SACN_RECV_BUF 8192
-#define SACN_DISCOVERY_TIMEOUT 100000
+#define SACN_DISCOVERY_TIMEOUT 9000
#define SACN_PDU_MAGIC "ASC-E1.17\0\0\0"
#define MAP_COARSE 0x0200
@@ -100,13 +100,18 @@ typedef struct /*_sacn_frame_discovery*/ {
uint32_t vector;
uint8_t page;
uint8_t max_page;
- uint16_t universes[512];
+ uint16_t data[512];
} sacn_frame_discovery;
typedef struct /*_sacn_xmit_data*/ {
sacn_frame_root root;
sacn_frame_data data;
} sacn_data_pdu;
+
+typedef struct /*_sacn_xmit_discovery*/ {
+ sacn_frame_root root;
+ sacn_frame_discovery data;
+} sacn_discovery_pdu;
#pragma pack(pop)
#define ROOT_E131_DATA 0x4