aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2020-03-29 11:28:44 +0200
committercbdev <cb@cbcdn.com>2020-03-29 11:28:44 +0200
commit3c6d2ccce4dd9be3f6497fb75d0456900e16ab0c (patch)
treeec1807891f10b0eec73b595d55e4e8f9b401f0f7
parentcf6a8e9a0f125633b1ef7d84e10935695598e654 (diff)
downloadmidimonster-3c6d2ccce4dd9be3f6497fb75d0456900e16ab0c.tar.gz
midimonster-3c6d2ccce4dd9be3f6497fb75d0456900e16ab0c.tar.bz2
midimonster-3c6d2ccce4dd9be3f6497fb75d0456900e16ab0c.zip
Reschedule sacn frame output on EAGAIN
-rw-r--r--DEVELOPMENT.md6
-rw-r--r--backends/sacn.c64
2 files changed, 50 insertions, 20 deletions
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 90c63ce..495c4f9 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -41,6 +41,8 @@ in spirit rather than by the letter.
* Avoid `atoi()`/`itoa()`, use `strto[u]l[l]()` and `snprintf()`
* Avoid unsafe functions without explicit bounds parameters (eg. `strcat()`).
-## Architecture
+# Build pipeline
-TBD
+# Architecture
+
+# Debugging
diff --git a/backends/sacn.c b/backends/sacn.c
index bce3887..b3376d7 100644
--- a/backends/sacn.c
+++ b/backends/sacn.c
@@ -275,9 +275,10 @@ static channel* sacn_channel(instance* inst, char* spec, uint8_t flags){
return data->data.channel + chan_a;
}
-static int sacn_transmit(instance* inst){
- size_t u;
+static int sacn_transmit(instance* inst, sacn_output_universe* output){
sacn_instance_data* data = (sacn_instance_data*) inst->impl;
+
+ //build sacn frame
sacn_data_pdu pdu = {
.root = {
.preamble_size = htobe16(0x10),
@@ -312,16 +313,31 @@ static int sacn_transmit(instance* inst){
memcpy((((uint8_t*)pdu.data.data) + 1), data->data.out, 512);
if(sendto(global_cfg.fd[data->fd_index].fd, (uint8_t*) &pdu, sizeof(pdu), 0, (struct sockaddr*) &data->dest_addr, data->dest_len) < 0){
- LOGPF("Failed to output frame for instance %s: %s", inst->name, strerror(errno));
- }
+ #ifndef _WIN32
+ if(errno != EAGAIN){
+ LOGPF("Failed to output frame for instance %s: %s", inst->name, strerror(errno));
+ #else
+ if(WSAGetLastError() != WSAEWOULDBLOCK){
+ char* error = NULL;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error, 0, NULL);
+ LOGPF("Failed to output frame for instance %s: %s", inst->name, error);
+ LocalFree(error);
+ #endif
+ return 1;
+ }
- //update last transmit timestamp, unmark instance
- for(u = 0; u < global_cfg.fd[data->fd_index].universes; u++){
- if(global_cfg.fd[data->fd_index].universe[u].universe == data->uni){
- global_cfg.fd[data->fd_index].universe[u].last_frame = mm_timestamp();
- global_cfg.fd[data->fd_index].universe[u].mark = 0;
+ //reschedule output
+ output->mark = 1;
+ if(!global_cfg.next_frame || global_cfg.next_frame > SACN_SYNTHESIZE_MARGIN){
+ global_cfg.next_frame = SACN_SYNTHESIZE_MARGIN;
}
+ return 0;
}
+
+ //update last transmit timestamp, unmark instance
+ output->last_frame = mm_timestamp();
+ output->mark = 0;
return 0;
}
@@ -357,14 +373,14 @@ static int sacn_set(instance* inst, size_t num, channel** c, channel_value* v){
//send packet if required
if(mark){
- if(!data->realtime){
- //find output instance data
- for(u = 0; u < global_cfg.fd[data->fd_index].universes; u++){
- if(global_cfg.fd[data->fd_index].universe[u].universe == data->uni){
- break;
- }
+ //find output instance data
+ for(u = 0; u < global_cfg.fd[data->fd_index].universes; u++){
+ if(global_cfg.fd[data->fd_index].universe[u].universe == data->uni){
+ break;
}
+ }
+ if(!data->realtime){
frame_delta = mm_timestamp() - global_cfg.fd[data->fd_index].universe[u].last_frame;
//check if ratelimiting engaged
@@ -376,7 +392,7 @@ static int sacn_set(instance* inst, size_t num, channel** c, channel_value* v){
return 0;
}
}
- sacn_transmit(inst);
+ sacn_transmit(inst, global_cfg.fd[data->fd_index].universe + u);
}
return 0;
@@ -496,7 +512,19 @@ static void sacn_discovery(size_t fd){
memcpy(pdu.data.data, global_cfg.fd[fd].universe + page * 512, universes * sizeof(uint16_t));
if(sendto(global_cfg.fd[fd].fd, (uint8_t*) &pdu, sizeof(pdu) - (512 - universes) * sizeof(uint16_t), 0, (struct sockaddr*) &discovery_dest, sizeof(discovery_dest)) < 0){
- LOGPF("Failed to output universe discovery frame for interface %" PRIsize_t ": %s", fd, strerror(errno));
+ #ifndef _WIN32
+ if(errno != EAGAIN){
+ LOGPF("Failed to output universe discovery frame for interface %" PRIsize_t ": %s", fd, strerror(errno));
+ }
+ #else
+ if(WSAGetLastError() != WSAEWOULDBLOCK){
+ char* error = NULL;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error, 0, NULL);
+ LOGPF("Failed to output universe discovery frame for interface %" PRIsize_t ": %s", fd, error);
+ LocalFree(error);
+ }
+ #endif
}
}
}
@@ -537,7 +565,7 @@ static int sacn_handle(size_t num, managed_fd* fds){
instance_id.fields.uni = global_cfg.fd[u].universe[c].universe;
inst = mm_instance_find(BACKEND_NAME, instance_id.label);
if(inst){
- sacn_transmit(inst);
+ sacn_transmit(inst, global_cfg.fd[u].universe + c);
}
}