diff options
Diffstat (limited to 'backends')
| -rw-r--r-- | backends/artnet.c | 52 | ||||
| -rw-r--r-- | backends/artnet.h | 15 | ||||
| -rw-r--r-- | backends/artnet.md | 3 | 
3 files changed, 53 insertions, 17 deletions
| diff --git a/backends/artnet.c b/backends/artnet.c index ed426b0..77f03dd 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")){ @@ -211,7 +219,8 @@ 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; @@ -226,7 +235,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); @@ -248,6 +256,21 @@ 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; +			} +		} + +		//check output rate limit, request next frame +		if(mm_timestamp() - artnet_fd[data->fd_index].output_instance[u].last_frame < ARTNET_FRAME_TIMEOUT){ +			artnet_fd[data->fd_index].output_instance[u].mark = 1; +			if(!next_frame || next_frame < mm_timestamp() - artnet_fd[data->fd_index].output_instance[u].last_frame){ +				next_frame = mm_timestamp() - artnet_fd[data->fd_index].output_instance[u].last_frame; +			} +			return 0; +		}  		return artnet_transmit(inst);  	} @@ -325,15 +348,23 @@ 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){ +			if(timestamp - artnet_fd[u].output_instance[c].last_frame >= ARTNET_KEEPALIVE_INTERVAL //timeout  +					|| (artnet_fd[u].output_instance[c].mark && timestamp - artnet_fd[u].output_instance[c].last_frame >= ARTNET_FRAME_TIMEOUT)){ //synthesized frame  				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 > mm_timestamp() - artnet_fd[u].output_instance[c].last_frame)){ +				next_frame = mm_timestamp() - artnet_fd[u].output_instance[c].last_frame; +			}  		}  	} @@ -407,15 +438,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++;  		} @@ -443,7 +474,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); diff --git a/backends/artnet.h b/backends/artnet.h index 1efdee6..aac73fe 100644 --- a/backends/artnet.h +++ b/backends/artnet.h @@ -4,6 +4,7 @@  #include "midimonster.h"  MM_PLUGIN_API int init(); +static uint32_t artnet_interval();  static int artnet_configure(char* option, char* value);  static int artnet_configure_instance(instance* instance, char* option, char* value);  static int artnet_instance(instance* inst); @@ -16,7 +17,10 @@ static int artnet_shutdown(size_t n, instance** inst);  #define ARTNET_PORT "6454"  #define ARTNET_VERSION 14  #define ARTNET_RECV_BUF 4096 -#define ARTNET_KEEPALIVE_INTERVAL 2000 + +#define ARTNET_KEEPALIVE_INTERVAL 1000 +//limit transmit rate to at most 44 packets per second (1000/44 ~= 22) +#define ARTNET_FRAME_TIMEOUT 20  #define MAP_COARSE 0x0200  #define MAP_FINE 0x0400 @@ -52,11 +56,16 @@ typedef union /*_artnet_instance_id*/ {  	uint64_t label;  } artnet_instance_id; +typedef struct /*_artnet_fd_universe*/ { +	uint64_t label; +	uint64_t last_frame; +	uint8_t mark; +} artnet_output_universe; +  typedef struct /*_artnet_fd*/ {  	int fd;  	size_t output_instances; -	artnet_instance_id* output_instance; -	uint64_t* last_frame; +	artnet_output_universe* output_instance;  } artnet_descriptor;  #pragma pack(push, 1) diff --git a/backends/artnet.md b/backends/artnet.md index 90a7697..7e1ecff 100644 --- a/backends/artnet.md +++ b/backends/artnet.md @@ -36,6 +36,3 @@ net1.1+2 > net2.5+123  A normal channel that is part of a wide channel can not be mapped individually.  #### Known bugs / problems - -The minimum inter-frame-time is disregarded, as the packet rate is determined by the rate of incoming -channel events.
\ No newline at end of file | 
