diff options
| -rw-r--r-- | artnet.c | 74 | ||||
| -rw-r--r-- | artnet.h | 10 | ||||
| -rw-r--r-- | backend.c | 43 | ||||
| -rw-r--r-- | backend.h | 2 | ||||
| -rw-r--r-- | config.c | 138 | ||||
| -rw-r--r-- | config.h | 1 | ||||
| -rw-r--r-- | makefile | 7 | ||||
| -rw-r--r-- | midi.c | 3 | ||||
| -rw-r--r-- | midi.h | 2 | ||||
| -rw-r--r-- | midimonster.c | 26 | ||||
| -rw-r--r-- | midimonster.h | 16 | ||||
| -rw-r--r-- | monster.cfg | 3 | ||||
| -rw-r--r-- | osc.c | 3 | ||||
| -rw-r--r-- | osc.h | 2 | 
14 files changed, 321 insertions, 9 deletions
@@ -0,0 +1,74 @@ +#include <string.h> +#include "artnet.h" + +size_t ninstances = 0; +instance* instances = NULL; + +int artnet_init(){ +	backend artnet = { +		.name = "artnet", +		.conf = artnet_configure, +		.create = artnet_instance, +		.conf_instance = artnet_configure_instance, +		.channel = artnet_channel, +		.handle = artnet_set, +		.process = artnet_handle, +		.shutdown = artnet_shutdown +	}; + +	//register backend +	if(!mm_backend_register(artnet)){ +		fprintf(stderr, "Failed to register ArtNet backend\n"); +		return 1; +	} +	return 0; +} + +static int artnet_configure(char* option, char* value){ +	fprintf(stderr, "ArtNet backend configured: %s -> %s\n", option, value); +	return 0; +} + +static instance* artnet_instance(){ +	fprintf(stderr, "Creating new ArtNet instance\n"); +	instances = realloc(instances, (ninstances + 1) * sizeof(instance)); +	if(!instances){ +		fprintf(stderr, "Failed to allocate memory\n"); +		ninstances = 0; +		return NULL; +	} +	memset(instances + ninstances, 0, sizeof(instance)); +	ninstances++; +	return instances + (ninstances - 1); +} + +static int artnet_configure_instance(instance* instance, char* option, char* value){ +	fprintf(stderr, "ArtNet instance configured: %s -> %s\n", option, value); +	return 1; +} + +static channel* artnet_channel(instance* instance, char* spec){ +	fprintf(stderr, "Parsing ArtNet channelspec %s\n", spec); +	return NULL; +} + +static int artnet_set(size_t num, channel* c, channel_value* v){ +	return 1; +} + +static int artnet_handle(size_t num, int* fd, void** data){ +	return 1; +} + +static int artnet_shutdown(){ +	size_t u; + +	for(u = 0; u < ninstances; u++){ +		mm_instance_free(instances + u); +	} +	free(instances); +	ninstances = 0; + +	fprintf(stderr, "ArtNet backend shut down\n"); +	return 0; +} @@ -0,0 +1,10 @@ +#include "midimonster.h" + +int artnet_init(); +static int artnet_configure(char* option, char* value); +static int artnet_configure_instance(instance* instance, char* option, char* value); +static instance* artnet_instance(); +static channel* artnet_channel(instance* instance, char* spec); +static int artnet_set(size_t num, channel* c, channel_value* v); +static int artnet_handle(size_t num, int* fd, void** data); +static int artnet_shutdown(); diff --git a/backend.c b/backend.c new file mode 100644 index 0000000..e1e143f --- /dev/null +++ b/backend.c @@ -0,0 +1,43 @@ +#include <string.h> +#include "midimonster.h" +#include "backend.h" + +static size_t nbackends = 0; +static backend* backends = NULL; + +backend* backend_match(char* name){ +	size_t u; +	for(u = 0; u < nbackends; u++){ +		if(!strcmp(backends[u].name, name)){ +			return backends + u; +		} +	} +	return NULL; +} + +backend* mm_backend_register(backend b){ +	if(!backend_match(b.name)){ +		backends = realloc(backends, (nbackends + 1) * sizeof(backend)); +		if(!backends){ +			fprintf(stderr, "Failed to allocate memory\n"); +			nbackends = 0; +			return NULL; +		} +		backends[nbackends] = b; +		nbackends++; + +		fprintf(stderr, "Registered backend %s\n", b.name); +		return backends + (nbackends - 1); +	} +	return NULL; +} + +int backends_stop(){ +	size_t u; +	for(u = 0; u < nbackends; u++){ +		backends[u].shutdown(); +	} +	free(backends); +	nbackends = 0; +	return 0; +} diff --git a/backend.h b/backend.h new file mode 100644 index 0000000..5c844a7 --- /dev/null +++ b/backend.h @@ -0,0 +1,2 @@ +backend* backend_match(char* name); +int backends_stop(); diff --git a/config.c b/config.c new file mode 100644 index 0000000..de6767d --- /dev/null +++ b/config.c @@ -0,0 +1,138 @@ +#include <string.h> +#include <ctype.h> +#include "midimonster.h" +#include "config.h" +#include "backend.h" + +enum { +	none, +	backend_cfg, +	instance_cfg, +	map +} parser_state = none; + +backend* current_backend = NULL; +instance* current_instance = NULL; + +static char* config_trim_line(char* in){ +	ssize_t u; +	//trim front +	for(; *in && !isgraph(*in); in++){ +	} + +	//trim back +	for(u = strlen(in); u >= 0 && !isgraph(in[u]); u--){ +		in[u] = 0; +	} + +	return in; +} + +int config_read(char* cfg_file){ +	int rv = 1; +	size_t line_alloc = 0; +	ssize_t status; +	char* line_raw = NULL, *line, *separator; +	FILE* source = fopen(cfg_file, "r"); +	if(!source){ +		fprintf(stderr, "Failed to open configuration file for reading\n"); +		return 1; +	} + +	for(status = getline(&line_raw, &line_alloc, source); status >= 0; status = getline(&line_raw, &line_alloc, source)){ +		line = config_trim_line(line_raw); +		if(*line == ';' || strlen(line) == 0){ +			//skip comments +			continue; +		} +		if(*line == '[' && line[strlen(line) - 1] == ']'){ +			if(!strncmp(line, "[backend ", 9)){ +				//backend configuration +				parser_state = backend_cfg; +				line[strlen(line) - 1] = 0; +				current_backend = backend_match(line + 9); + +				if(!current_backend){ +					fprintf(stderr, "Cannot configure unknown backend %s\n", line + 9); +					goto bail; +				} +			} +			else if(!strcmp(line, "[map]")){ +				//mapping configuration +				parser_state = map; +			} +			else{ +				//backend instance configuration +				parser_state = instance_cfg; +				 +				//trim braces +				line[strlen(line) - 1] = 0; +				line++; + +				//find separating space and terminate +				for(separator = line; *separator && *separator != ' '; separator++){ +				} +				if(!*separator){ +					fprintf(stderr, "No instance name specified for backend %s\n", line); +					goto bail; +				} +				*separator = 0; +				separator++; + +				current_backend = backend_match(line); +				if(!current_backend){ +					fprintf(stderr, "No such backend %s\n", line); +					goto bail; +				} + +				current_instance = current_backend->create(); +				if(!current_instance){ +					fprintf(stderr, "Failed to instantiate backend %s\n", line); +					goto bail; +				} + +				current_instance->name = strdup(separator); +				current_instance->backend = current_backend; +				fprintf(stderr, "Created %s instance %s\n", line, separator); +			} +		} +		else{ +			//pass to parser +			//find separator +			for(separator = line; *separator && *separator != '='; separator++){ +			} + +			if(!*separator){ +				fprintf(stderr, "No assignment: %s\n", line); +				goto bail; +			} + +			*separator = 0; +			separator++; + +			if(parser_state == backend_cfg && current_backend->conf(config_trim_line(line), config_trim_line(separator))){ +				fprintf(stderr, "Failed to configure backend %s\n", current_backend->name); +				goto bail; +			} +			else if(parser_state == instance_cfg && current_backend->conf_instance(current_instance, config_trim_line(line), config_trim_line(separator))){ +				fprintf(stderr, "Failed to configure instance %s\n", current_instance->name); +				goto bail; +			} +			else if(parser_state == map){ +				//TODO map two channels +			} +		} +	} + +	rv = 0; +bail: +	fclose(source); +	free(line_raw); +	return rv; +} + +void mm_instance_free(instance* inst){ +	free(inst->name); +	inst->name = NULL; +	inst->backend = NULL; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..7cc2a42 --- /dev/null +++ b/config.h @@ -0,0 +1 @@ +int config_read(char* file); @@ -1,8 +1,8 @@  LDLIBS = -lasound  CFLAGS = -g -Wall -BACKENDS = artnet.o midi.o -OBJS = $(BACKENDS) +BACKENDS = artnet.o midi.o osc.o +OBJS = config.o backend.o $(BACKENDS)  midimonster: midimonster.h $(OBJS) @@ -11,3 +11,6 @@ all: midimonster  clean:  	$(RM) midimonster  	$(RM) $(OBJS) + +run: +	valgrind --leak-check=full --show-leak-kinds=all ./midimonster @@ -0,0 +1,3 @@ +int midi_start(){ +	return 1; +} @@ -0,0 +1,2 @@ +#include "midimonster.h" +int midi_start(); diff --git a/midimonster.c b/midimonster.c index 58166d6..5d7ec7f 100644 --- a/midimonster.c +++ b/midimonster.c @@ -1,4 +1,11 @@  #include "midimonster.h" +#include "config.h" +#include "backend.h" + +//temporary prototypes +int artnet_init(); +int midi_init(); +int osc_init();  int usage(char* fn){  	fprintf(stderr, "MIDIMonster v0.1\n"); @@ -8,15 +15,32 @@ int usage(char* fn){  }  int main(int argc, char** argv){ +	int rv = EXIT_FAILURE;  	char* cfg_file = DEFAULT_CFG;  	if(argc > 1){  		cfg_file = argv[1];  	}  	//initialize backends +	//TODO replace this with loading shared objects +	if(artnet_init() /*|| midi_init() || osc_init()*/){ +		fprintf(stderr, "Failed to initialize a backend\n"); +		goto bail; +	} +  	//read config +	if(config_read(cfg_file)){ +		fprintf(stderr, "Failed to read configuration file %s\n", cfg_file); +		backends_stop(); +		return usage(argv[0]); +	} +  	//wait for events +	 +	rv = EXIT_SUCCESS; +bail:  	//free all data +	backends_stop(); -	return EXIT_SUCCESS; +	return rv;  } diff --git a/midimonster.h b/midimonster.h index 59c97eb..8c323f1 100644 --- a/midimonster.h +++ b/midimonster.h @@ -1,3 +1,5 @@ +#ifndef MIDIMONSTER_HEADER +#define MIDIMONSTER_HEADER  #include <stdio.h>  #include <stdlib.h>  #include <stdint.h> @@ -8,12 +10,12 @@ struct _channel_value;  struct _backend_channel;  struct _backend_instance; -typedef int (*mmbackend_handle_event)(struct _backend_channel* c, struct _channel_value v); -typedef struct _backend_channel* (*mmbackend_parse_channel)(char* spec); -typedef int (*mmbackend_configure)(char* option, char* value); +typedef int (*mmbackend_handle_event)(size_t channels, struct _backend_channel* c, struct _channel_value* v);  typedef struct _backend_instance* (*mmbackend_create_instance)(); -typedef int (*mmbackend_configure_instance)(char* option, char* value); -typedef int (*mmbackend_process_fd)(int fd, void** impl); +typedef struct _backend_channel* (*mmbackend_parse_channel)(struct _backend_instance* instance, char* spec); +typedef int (*mmbackend_configure)(char* option, char* value); +typedef int (*mmbackend_configure_instance)(struct _backend_instance* instance, char* option, char* value); +typedef int (*mmbackend_process_fd)(size_t fds, int* fd, void** impl);  typedef int (*mmbackend_shutdown)();  typedef struct _channel_value { @@ -46,6 +48,7 @@ typedef struct _backend_channel {  	void* impl;  } channel; +//FIXME might be replaced by struct pollfd  typedef struct /*_mm_managed_fd*/ {  	int fd;  	backend* backend; @@ -55,3 +58,6 @@ typedef struct /*_mm_managed_fd*/ {  backend* mm_backend_register(backend b);  int mm_manage_fd(int fd, backend* b, int manage, void* impl);  int mm_channel_event(channel* c, channel_value v); + +void mm_instance_free(instance* i); +#endif diff --git a/monster.cfg b/monster.cfg index 6391d40..8d3b0ad 100644 --- a/monster.cfg +++ b/monster.cfg @@ -23,4 +23,5 @@ net = 0  uni = 1  [map] - +artnet.231 = lc1.cc5 +artent.231 = osc.f/channel5/ toggle=127 @@ -0,0 +1,3 @@ +int osc_start(){ +	return 1; +} @@ -0,0 +1,2 @@ +#include "midimonster.h" +int osc_start();  | 
