aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2017-06-03 23:02:46 +0200
committercbdev <cb@cbcdn.com>2017-06-03 23:02:46 +0200
commitb7e009a98698c4ed81b16cbc274a3b47793c1bab (patch)
treed0f130451f381bea80822b5d1533fca36d4f3434
parent19fd0404ba636ff5f67cbf218d175ccbef29579a (diff)
downloadmidimonster-b7e009a98698c4ed81b16cbc274a3b47793c1bab.tar.gz
midimonster-b7e009a98698c4ed81b16cbc274a3b47793c1bab.tar.bz2
midimonster-b7e009a98698c4ed81b16cbc274a3b47793c1bab.zip
Config parser
-rw-r--r--artnet.c74
-rw-r--r--artnet.h10
-rw-r--r--backend.c43
-rw-r--r--backend.h2
-rw-r--r--config.c138
-rw-r--r--config.h1
-rw-r--r--makefile7
-rw-r--r--midi.c3
-rw-r--r--midi.h2
-rw-r--r--midimonster.c26
-rw-r--r--midimonster.h16
-rw-r--r--monster.cfg3
-rw-r--r--osc.c3
-rw-r--r--osc.h2
14 files changed, 321 insertions, 9 deletions
diff --git a/artnet.c b/artnet.c
index e69de29..a245cf1 100644
--- a/artnet.c
+++ b/artnet.c
@@ -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;
+}
diff --git a/artnet.h b/artnet.h
index e69de29..a7742f3 100644
--- a/artnet.h
+++ b/artnet.h
@@ -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);
diff --git a/makefile b/makefile
index dbef918..ec5238e 100644
--- a/makefile
+++ b/makefile
@@ -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
diff --git a/midi.c b/midi.c
index e69de29..c817bd2 100644
--- a/midi.c
+++ b/midi.c
@@ -0,0 +1,3 @@
+int midi_start(){
+ return 1;
+}
diff --git a/midi.h b/midi.h
index e69de29..eef2413 100644
--- a/midi.h
+++ b/midi.h
@@ -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
diff --git a/osc.c b/osc.c
new file mode 100644
index 0000000..040dd01
--- /dev/null
+++ b/osc.c
@@ -0,0 +1,3 @@
+int osc_start(){
+ return 1;
+}
diff --git a/osc.h b/osc.h
new file mode 100644
index 0000000..6cc321d
--- /dev/null
+++ b/osc.h
@@ -0,0 +1,2 @@
+#include "midimonster.h"
+int osc_start();