aboutsummaryrefslogtreecommitdiffhomepage
path: root/backends/artnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'backends/artnet.c')
-rw-r--r--backends/artnet.c71
1 files changed, 50 insertions, 21 deletions
diff --git a/backends/artnet.c b/backends/artnet.c
index 0bd1a32..9fac332 100644
--- a/backends/artnet.c
+++ b/backends/artnet.c
@@ -9,6 +9,7 @@
#define MAX_FDS 255
+static uint32_t next_frame = 0;
static uint8_t default_net = 0;
static size_t artnet_fds = 0;
static artnet_descriptor* artnet_fd = NULL;
@@ -37,7 +38,6 @@ static int artnet_listener(char* host, char* port){
artnet_fd[artnet_fds].fd = fd;
artnet_fd[artnet_fds].output_instances = 0;
artnet_fd[artnet_fds].output_instance = NULL;
- artnet_fd[artnet_fds].last_frame = NULL;
artnet_fds++;
return 0;
}
@@ -52,6 +52,7 @@ MM_PLUGIN_API int init(){
.handle = artnet_set,
.process = artnet_handle,
.start = artnet_start,
+ .interval = artnet_interval,
.shutdown = artnet_shutdown
};
@@ -68,6 +69,13 @@ MM_PLUGIN_API int init(){
return 0;
}
+static uint32_t artnet_interval(){
+ if(next_frame){
+ return next_frame;
+ }
+ return ARTNET_KEEPALIVE_INTERVAL;
+}
+
static int artnet_configure(char* option, char* value){
char* host = NULL, *port = NULL, *fd_opts = NULL;
if(!strcmp(option, "net")){
@@ -94,23 +102,17 @@ static int artnet_configure(char* option, char* value){
return 1;
}
-static instance* artnet_instance(){
- artnet_instance_data* data = NULL;
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
- data = calloc(1, sizeof(artnet_instance_data));
+static int artnet_instance(instance* inst){
+ artnet_instance_data* data = calloc(1, sizeof(artnet_instance_data));
if(!data){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
data->net = default_net;
inst->impl = data;
- return inst;
+ return 0;
}
static int artnet_configure_instance(instance* inst, char* option, char* value){
@@ -217,13 +219,15 @@ static int artnet_transmit(instance* inst){
//update last frame timestamp
for(u = 0; u < artnet_fd[data->fd_index].output_instances; u++){
if(artnet_fd[data->fd_index].output_instance[u].label == inst->ident){
- artnet_fd[data->fd_index].last_frame[u] = mm_timestamp();
+ artnet_fd[data->fd_index].output_instance[u].last_frame = mm_timestamp();
+ artnet_fd[data->fd_index].output_instance[u].mark = 0;
}
}
return 0;
}
static int artnet_set(instance* inst, size_t num, channel** c, channel_value* v){
+ uint32_t frame_delta = 0;
size_t u, mark = 0;
artnet_instance_data* data = (artnet_instance_data*) inst->impl;
@@ -232,7 +236,6 @@ static int artnet_set(instance* inst, size_t num, channel** c, channel_value* v)
return 0;
}
- //FIXME maybe introduce minimum frame interval
for(u = 0; u < num; u++){
if(IS_WIDE(data->data.map[c[u]->ident])){
uint32_t val = v[u].normalised * ((double) 0xFFFF);
@@ -254,6 +257,22 @@ static int artnet_set(instance* inst, size_t num, channel** c, channel_value* v)
}
if(mark){
+ //find last frame time
+ for(u = 0; u < artnet_fd[data->fd_index].output_instances; u++){
+ if(artnet_fd[data->fd_index].output_instance[u].label == inst->ident){
+ break;
+ }
+ }
+
+ frame_delta = mm_timestamp() - artnet_fd[data->fd_index].output_instance[u].last_frame;
+ //check output rate limit, request next frame
+ if(frame_delta < ARTNET_FRAME_TIMEOUT){
+ artnet_fd[data->fd_index].output_instance[u].mark = 1;
+ if(!next_frame || next_frame > (ARTNET_KEEPALIVE_INTERVAL - frame_delta)){
+ next_frame = (ARTNET_KEEPALIVE_INTERVAL - frame_delta);
+ }
+ return 0;
+ }
return artnet_transmit(inst);
}
@@ -323,6 +342,7 @@ static inline int artnet_process_frame(instance* inst, artnet_pkt* frame){
static int artnet_handle(size_t num, managed_fd* fds){
size_t u, c;
uint64_t timestamp = mm_timestamp();
+ uint32_t synthesize_delta = 0;
ssize_t bytes_read;
char recv_buf[ARTNET_RECV_BUF];
artnet_instance_id inst_id = {
@@ -331,15 +351,25 @@ static int artnet_handle(size_t num, managed_fd* fds){
instance* inst = NULL;
artnet_pkt* frame = (artnet_pkt*) recv_buf;
- //transmit keepalive frames
+ //transmit keepalive & synthesized frames
+ next_frame = 0;
for(u = 0; u < artnet_fds; u++){
for(c = 0; c < artnet_fd[u].output_instances; c++){
- if(timestamp - artnet_fd[u].last_frame[c] >= ARTNET_KEEPALIVE_INTERVAL){
+ synthesize_delta = timestamp - artnet_fd[u].output_instance[c].last_frame;
+ if((artnet_fd[u].output_instance[c].mark
+ && synthesize_delta >= ARTNET_FRAME_TIMEOUT + ARTNET_SYNTHESIZE_MARGIN) //synthesize next frame
+ || synthesize_delta >= ARTNET_KEEPALIVE_INTERVAL){ //keepalive timeout
inst = mm_instance_find(BACKEND_NAME, artnet_fd[u].output_instance[c].label);
if(inst){
artnet_transmit(inst);
}
}
+
+ //update next_frame
+ if(artnet_fd[u].output_instance[c].mark
+ && (!next_frame || next_frame > ARTNET_FRAME_TIMEOUT + ARTNET_SYNTHESIZE_MARGIN - synthesize_delta)){
+ next_frame = ARTNET_FRAME_TIMEOUT + ARTNET_SYNTHESIZE_MARGIN - synthesize_delta;
+ }
}
}
@@ -413,15 +443,15 @@ static int artnet_start(size_t n, instance** inst){
//if enabled for output, add to keepalive tracking
if(data->dest_len){
- artnet_fd[data->fd_index].output_instance = realloc(artnet_fd[data->fd_index].output_instance, (artnet_fd[data->fd_index].output_instances + 1) * sizeof(artnet_instance_id));
- artnet_fd[data->fd_index].last_frame = realloc(artnet_fd[data->fd_index].last_frame, (artnet_fd[data->fd_index].output_instances + 1) * sizeof(uint64_t));
+ artnet_fd[data->fd_index].output_instance = realloc(artnet_fd[data->fd_index].output_instance, (artnet_fd[data->fd_index].output_instances + 1) * sizeof(artnet_output_universe));
- if(!artnet_fd[data->fd_index].output_instance || !artnet_fd[data->fd_index].last_frame){
+ if(!artnet_fd[data->fd_index].output_instance){
LOG("Failed to allocate memory");
goto bail;
}
- artnet_fd[data->fd_index].output_instance[artnet_fd[data->fd_index].output_instances] = id;
- artnet_fd[data->fd_index].last_frame[artnet_fd[data->fd_index].output_instances] = 0;
+ artnet_fd[data->fd_index].output_instance[artnet_fd[data->fd_index].output_instances].label = id.label;
+ artnet_fd[data->fd_index].output_instance[artnet_fd[data->fd_index].output_instances].last_frame = 0;
+ artnet_fd[data->fd_index].output_instance[artnet_fd[data->fd_index].output_instances].mark = 0;
artnet_fd[data->fd_index].output_instances++;
}
@@ -449,7 +479,6 @@ static int artnet_shutdown(size_t n, instance** inst){
for(p = 0; p < artnet_fds; p++){
close(artnet_fd[p].fd);
free(artnet_fd[p].output_instance);
- free(artnet_fd[p].last_frame);
}
free(artnet_fd);