aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2017-06-05 18:53:41 +0200
committercbdev <cb@cbcdn.com>2017-06-05 18:53:41 +0200
commit40e123db7713b188162cd94d935f7a395405567a (patch)
treef745b15d41af6a38b675bdbe2de6473657c7e212
parented55916e772264dc8278fc8c96d4139aec31e89e (diff)
downloadmidimonster-40e123db7713b188162cd94d935f7a395405567a.tar.gz
midimonster-40e123db7713b188162cd94d935f7a395405567a.tar.bz2
midimonster-40e123db7713b188162cd94d935f7a395405567a.zip
Core select loop
-rw-r--r--TODO1
-rw-r--r--artnet.c49
-rw-r--r--artnet.h17
-rw-r--r--backend.c10
-rw-r--r--backend.h3
-rw-r--r--midi.c2
-rw-r--r--midimonster.c106
-rw-r--r--midimonster.h8
8 files changed, 186 insertions, 10 deletions
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..c83eb34
--- /dev/null
+++ b/TODO
@@ -0,0 +1 @@
+Wide channels (DMX/MIDI)
diff --git a/artnet.c b/artnet.c
index 2684d46..6eef2fe 100644
--- a/artnet.c
+++ b/artnet.c
@@ -3,6 +3,13 @@
#define BACKEND_NAME "artnet"
static uint8_t default_net = 0;
+static struct {
+ char* host;
+ char* port;
+} bind = {
+ .host = NULL,
+ .port = NULL
+};
int artnet_init(){
backend artnet = {
@@ -26,8 +33,20 @@ int artnet_init(){
}
static int artnet_configure(char* option, char* value){
+ char* separator = value;
if(!strcmp(option, "bind")){
- //TODO create socket, hand over to be managed (unregister previous socket?)
+ for(; *separator && *separator != ' '; separator++){
+ }
+
+ if(*separator){
+ *separator = 0;
+ separator++;
+ free(bind.port);
+ bind.port = strdup(separator);
+ }
+
+ free(bind.host);
+ bind.host = strdup(value);
return 0;
}
else if(!strcmp(option, "net")){
@@ -67,10 +86,10 @@ static int artnet_configure_instance(instance* instance, char* option, char* val
}
else if(!strcmp(option, "output")){
if(!strcmp(value, "true")){
- data->mode |= MODE_OUTPUT;
+ data->mode |= output;
}
else{
- data->mode &= ~MODE_OUTPUT;
+ data->mode &= ~output;
}
return 0;
}
@@ -99,8 +118,25 @@ static int artnet_handle(size_t num, int* fd, void** data){
}
static int artnet_start(){
- //TODO
- return 1;
+ if(!bind.host){
+ bind.host = strdup("127.0.0.1");
+ }
+
+ if(!bind.port){
+ bind.port = strdup("6454");
+ }
+
+ if(!bind.host || !bind.port){
+ fprintf(stderr, "Failed to allocate memory\n");
+ return 1;
+ }
+
+ //TODO allocate all active universes
+ //TODO open socket
+ fprintf(stderr, "Listening for ArtNet data on %s port %s\n", bind.host, bind.port);
+ //TODO parse all universe destinations
+
+ return 0;
}
static int artnet_shutdown(){
@@ -115,6 +151,9 @@ static int artnet_shutdown(){
free(inst[p]->impl);
}
free(inst);
+
+ free(bind.host);
+ free(bind.port);
fprintf(stderr, "ArtNet backend shut down\n");
return 0;
}
diff --git a/artnet.h b/artnet.h
index 8e05153..4976938 100644
--- a/artnet.h
+++ b/artnet.h
@@ -10,10 +10,23 @@ static int artnet_handle(size_t num, int* fd, void** data);
static int artnet_start();
static int artnet_shutdown();
-#define MODE_OUTPUT 1
-
typedef struct /*_artnet_instance_model*/ {
uint8_t net;
uint8_t uni;
uint8_t mode;
+ char* dest;
} artnet_instance_data;
+
+enum {
+ output = 1,
+ mark = 2
+};
+
+typedef struct /*_artnet_universe_model*/ {
+ uint8_t net;
+ uint8_t uni;
+ uint8_t flags;
+ uint8_t last_frame;
+ uint8_t data[512];
+ uint8_t mask[512];
+} artnet_universe;
diff --git a/backend.c b/backend.c
index 65ee748..f49bd91 100644
--- a/backend.c
+++ b/backend.c
@@ -127,6 +127,16 @@ instance* instance_match(char* name){
return NULL;
}
+struct timeval backend_timeout(){
+ //TODO fetch minimum poll interval from backends
+ struct timeval tv = {
+ 0,
+ 10000
+ };
+
+ return tv;
+}
+
int mm_backend_register(backend b){
if(!backend_match(b.name)){
backends = realloc(backends, (nbackends + 1) * sizeof(backend));
diff --git a/backend.h b/backend.h
index e1ad4ab..16cf77e 100644
--- a/backend.h
+++ b/backend.h
@@ -1,5 +1,8 @@
+#include <sys/types.h>
+
backend* backend_match(char* name);
instance* instance_match(char* name);
+struct timeval backend_timeout();
int backends_start();
int backends_stop();
void instances_free();
diff --git a/midi.c b/midi.c
index 3cd8507..00ff0a4 100644
--- a/midi.c
+++ b/midi.c
@@ -141,7 +141,7 @@ static int midi_handle(size_t num, int* fd, void** data){
}
static int midi_start(){
- return 1;
+ return 0;
}
static int midi_shutdown(){
diff --git a/midimonster.c b/midimonster.c
index 367ca6f..2c3013d 100644
--- a/midimonster.c
+++ b/midimonster.c
@@ -1,4 +1,8 @@
#include <string.h>
+#include <signal.h>
+#include <sys/select.h>
+#include <unistd.h>
+#include <errno.h>
#include "midimonster.h"
#include "config.h"
#include "backend.h"
@@ -10,6 +14,13 @@ int osc_init();
static size_t mappings = 0;
static channel_mapping* map = NULL;
+static size_t fds = 0;
+static managed_fd* fd = NULL;
+volatile static sig_atomic_t shutdown_requested = 0;
+
+void signal_handler(int signum){
+ shutdown_requested = 1;
+}
int mm_map_channel(channel* from, channel* to){
size_t u, m;
@@ -60,6 +71,68 @@ void map_free(){
map = NULL;
}
+int mm_manage_fd(int new_fd, char* back, int manage, void* impl){
+ backend* b = backend_match(back);
+ size_t u;
+
+ if(!b){
+ fprintf(stderr, "Unknown backend %s registered for managed fd\n", back);
+ return 1;
+ }
+
+ //find exact match
+ for(u = 0; u < fds; u++){
+ if(fd[u].fd == new_fd && fd[u].backend == b){
+ if(!manage){
+ fd[u].fd = -1;
+ fd[u].backend = NULL;
+ fd[u].impl = NULL;
+ }
+ return 0;
+ }
+ }
+
+ if(!manage){
+ return 0;
+ }
+
+ //find free slot
+ for(u = 0; u < fds; u++){
+ if(fd[u].fd < 0){
+ break;
+ }
+ }
+ //if necessary expand
+ if(u == fds){
+ fd = realloc(fd, (fds + 1) * sizeof(managed_fd));
+ if(!fd){
+ fprintf(stderr, "Failed to allocate memory\n");
+ return 1;
+ }
+ fds++;
+ }
+
+ //store new fd
+ fd[u].fd = new_fd;
+ fd[u].backend = b;
+ fd[u].impl = impl;
+ return 0;
+}
+
+void fds_free(){
+ size_t u;
+ for(u = 0; u < fds; u++){
+ //TODO free impl
+ if(fd[u].fd >= 0){
+ close(fd[u].fd);
+ fd[u].fd = -1;
+ }
+ }
+ free(fd);
+ fds = 0;
+ fd = NULL;
+}
+
int usage(char* fn){
fprintf(stderr, "MIDIMonster v0.1\n");
fprintf(stderr, "Usage:\n");
@@ -68,7 +141,10 @@ int usage(char* fn){
}
int main(int argc, char** argv){
- int rv = EXIT_FAILURE;
+ fd_set all_fds, read_fds;
+ struct timeval tv;
+ size_t u;
+ int rv = EXIT_FAILURE, error, maxfd = -1;
char* cfg_file = DEFAULT_CFG;
if(argc > 1){
cfg_file = argv[1];
@@ -88,6 +164,7 @@ int main(int argc, char** argv){
channels_free();
instances_free();
map_free();
+ fds_free();
return usage(argv[0]);
}
@@ -97,7 +174,31 @@ int main(int argc, char** argv){
goto bail;
}
- //TODO wait for & translate events
+ signal(SIGINT, signal_handler);
+
+ //create initial fd set
+ FD_ZERO(&all_fds);
+ for(u = 0; u < fds; u++){
+ if(fd[u].fd >= 0){
+ FD_SET(fd[u].fd, &all_fds);
+ maxfd = max(maxfd, fd[u].fd);
+ }
+ }
+
+ //process events
+ while(!shutdown_requested){
+ //wait for & translate events
+ read_fds = all_fds;
+ tv = backend_timeout();
+ error = select(maxfd + 1, &read_fds, NULL, NULL, &tv);
+ if(error < 0){
+ fprintf(stderr, "select failed: %s\n", strerror(errno));
+ break;
+ }
+ //TODO process all backends, collect events
+ //TODO push all events to backends
+ //FIXME notify non-fd backends
+ }
rv = EXIT_SUCCESS;
bail:
@@ -106,6 +207,7 @@ bail:
channels_free();
instances_free();
map_free();
+ fds_free();
return rv;
}
diff --git a/midimonster.h b/midimonster.h
index b2af7a3..181f1da 100644
--- a/midimonster.h
+++ b/midimonster.h
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#define max(a,b) (((a) > (b)) ? (a) : (b))
#define DEFAULT_CFG "monster.cfg"
@@ -54,6 +55,7 @@ typedef struct _backend_channel {
} channel;
//FIXME might be replaced by struct pollfd
+//FIXME who frees impl
typedef struct /*_mm_managed_fd*/ {
int fd;
backend* backend;
@@ -97,6 +99,12 @@ instance* mm_instance();
* will receive a call to its channel_free function.
*/
channel* mm_channel(instance* i, uint64_t ident);
+/*
+ * Register a file descriptor to be selected on. The backend
+ * will be notified via the mmbackend_process_fd call.
+ * This function may only be called from within the
+ * mmbackend_start procedure.
+ */
int mm_manage_fd(int fd, char* backend, int manage, void* impl);
int mm_channel_event(channel* c, channel_value v);
/*