aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--artnet.c2
-rw-r--r--artnet.h2
-rw-r--r--backend.c31
-rw-r--r--backend.h2
-rw-r--r--midi.c64
-rw-r--r--midi.h2
-rw-r--r--midimonster.c60
-rw-r--r--midimonster.h2
-rw-r--r--monster.cfg10
10 files changed, 141 insertions, 35 deletions
diff --git a/TODO b/TODO
index c83eb34..e654306 100644
--- a/TODO
+++ b/TODO
@@ -1 +1,2 @@
Wide channels (DMX/MIDI)
+Note source in channel value struct
diff --git a/artnet.c b/artnet.c
index f2a2fa5..2147dd9 100644
--- a/artnet.c
+++ b/artnet.c
@@ -107,7 +107,7 @@ static channel* artnet_channel(instance* instance, char* spec){
return mm_channel(instance, channel, 1);
}
-static int artnet_set(instance* inst, size_t num, channel* c, channel_value* v){
+static int artnet_set(instance* inst, size_t num, channel** c, channel_value* v){
//TODO
return 1;
}
diff --git a/artnet.h b/artnet.h
index 00a75a7..806d125 100644
--- a/artnet.h
+++ b/artnet.h
@@ -5,7 +5,7 @@ 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(instance* inst, size_t num, channel* c, channel_value* v);
+static int artnet_set(instance* inst, size_t num, channel** c, channel_value* v);
static int artnet_handle(size_t num, managed_fd* fds);
static int artnet_start();
static int artnet_shutdown();
diff --git a/backend.c b/backend.c
index 1b297d4..eeb789d 100644
--- a/backend.c
+++ b/backend.c
@@ -31,9 +31,34 @@ int backends_handle(size_t nfds, managed_fd* fds){
return rv;
}
-int backends_notify(size_t nev, channel* c, channel_value* v){
- //TODO
- return 1;
+int backends_notify(size_t nev, channel** c, channel_value* v){
+ size_t u, p, n;
+ int rv = 0;
+ channel_value xval;
+ channel* xchnl;
+
+ //TODO eliminate duplicates
+ for(u = 0; u < ninstances && !rv; u++){
+ n = 0;
+
+ for(p = 0; p < nev; p++){
+ if(c[p]->instance == instances[u]){
+ xval = v[n];
+ xchnl = c[n];
+
+ v[n] = v[p];
+ c[n] = c[p];
+
+ v[p] = xval;
+ c[p] = xchnl;
+ n++;
+ }
+ }
+
+ rv |= instances[u]->backend->handle(instances[u], n, c, v);
+ }
+
+ return 0;
}
channel* mm_channel(instance* i, uint64_t ident, uint8_t create){
diff --git a/backend.h b/backend.h
index e2eaac5..daf96bc 100644
--- a/backend.h
+++ b/backend.h
@@ -1,7 +1,7 @@
#include <sys/types.h>
int backends_handle(size_t nfds, managed_fd* fds);
-int backends_notify(size_t nev, channel* c, channel_value* v);
+int backends_notify(size_t nev, channel** c, channel_value* v);
backend* backend_match(char* name);
instance* instance_match(char* name);
diff --git a/midi.c b/midi.c
index 857460f..da71a32 100644
--- a/midi.c
+++ b/midi.c
@@ -4,10 +4,20 @@
#define BACKEND_NAME "midi"
static snd_seq_t* sequencer = NULL;
+typedef union {
+ struct {
+ uint8_t pad[5];
+ uint8_t type;
+ uint8_t channel;
+ uint8_t control;
+ } fields;
+ uint64_t label;
+} midi_channel_ident;
/*
* TODO
* Optionally send note-off messages
+ * Optionally send updates as after-touch
*/
enum /*_midi_channel_type*/ {
@@ -104,15 +114,7 @@ static int midi_configure_instance(instance* instance, char* option, char* value
}
static channel* midi_channel(instance* instance, char* spec){
- union {
- struct {
- uint8_t pad[5];
- uint8_t type;
- uint8_t channel;
- uint8_t control;
- } fields;
- uint64_t label;
- } ident = {
+ midi_channel_ident ident = {
.label = 0
};
@@ -158,15 +160,39 @@ static channel* midi_channel(instance* instance, char* spec){
return NULL;
}
-static int midi_set(instance* inst, size_t num, channel* c, channel_value* v){
+static int midi_set(instance* inst, size_t num, channel** c, channel_value* v){
size_t u;
+ snd_seq_event_t ev;
midi_instance_data* data;
+ midi_channel_ident ident = {
+ .label = 0
+ };
for(u = 0; u < num; u++){
- data = (midi_instance_data*) c[u].instance->impl;
- //TODO write out event
+ data = (midi_instance_data*) c[u]->instance->impl;
+ ident.label = c[u]->ident;
+
+ snd_seq_ev_clear(&ev);
+ snd_seq_ev_set_source(&ev, data->port);
+ snd_seq_ev_set_subs(&ev);
+ snd_seq_ev_set_direct(&ev);
+
+ switch(ident.fields.type){
+ case note:
+ snd_seq_ev_set_noteon(&ev, ident.fields.channel, ident.fields.control, v[u].normalised * 127.0);
+ break;
+ case cc:
+ snd_seq_ev_set_controller(&ev, ident.fields.channel, ident.fields.control, v[u].normalised * 127.0);
+ break;
+ case nrpn:
+ //FIXME set to nrpn output
+ break;
+ }
+
+ snd_seq_event_output(sequencer, &ev);
}
+ snd_seq_drain_output(sequencer);
return 0;
}
@@ -175,18 +201,14 @@ static int midi_handle(size_t num, managed_fd* fds){
instance* inst = NULL;
channel* changed = NULL;
channel_value val;
- union {
- struct {
- uint8_t pad[5];
- uint8_t type;
- uint8_t channel;
- uint8_t control;
- } fields;
- uint64_t label;
- } ident = {
+ midi_channel_ident ident = {
.label = 0
};
+ if(!num){
+ return 0;
+ }
+
while(snd_seq_event_input(sequencer, &ev) > 0){
ident.label = 0;
switch(ev->type){
diff --git a/midi.h b/midi.h
index dc997bc..185176b 100644
--- a/midi.h
+++ b/midi.h
@@ -5,7 +5,7 @@ static int midi_configure(char* option, char* value);
static int midi_configure_instance(instance* instance, char* option, char* value);
static instance* midi_instance();
static channel* midi_channel(instance* instance, char* spec);
-static int midi_set(instance* inst, size_t num, channel* c, channel_value* v);
+static int midi_set(instance* inst, size_t num, channel** c, channel_value* v);
static int midi_handle(size_t num, managed_fd* fds);
static int midi_start();
static int midi_shutdown();
diff --git a/midimonster.c b/midimonster.c
index 33858fd..b1c14e2 100644
--- a/midimonster.c
+++ b/midimonster.c
@@ -16,6 +16,10 @@ static size_t mappings = 0;
static channel_mapping* map = NULL;
static size_t fds = 0;
static managed_fd* fd = NULL;
+static size_t ev_alloc = 0;
+static size_t evs = 0;
+static channel** ev_channel = NULL;
+static channel_value* ev_value = NULL;
volatile static sig_atomic_t shutdown_requested = 0;
void signal_handler(int signum){
@@ -40,6 +44,7 @@ int mm_map_channel(channel* from, channel* to){
}
memset(map + mappings, 0, sizeof(channel_mapping));
mappings++;
+ map[u].from = from;
}
//check whether the target is already mapped
@@ -134,11 +139,52 @@ void fds_free(){
}
int mm_channel_event(channel* c, channel_value v){
- //TODO
- fprintf(stderr, "Stub implementation: Channel on %s at value %f\n", c->instance->name, v.normalised);
+ size_t u, p;
+
+ //find mapped channels
+ for(u = 0; u < mappings; u++){
+ if(map[u].from == c){
+ break;
+ }
+ }
+
+ if(u == mappings){
+ //target-only channel
+ return 0;
+ }
+
+ //resize event structures to fit additional events
+ if(evs + map[u].destinations >= ev_alloc){
+ ev_channel = realloc(ev_channel, (ev_alloc + map[u].destinations) * sizeof(channel*));
+ ev_value = realloc(ev_value, (ev_alloc + map[u].destinations) * sizeof(channel_value));
+
+ if(!ev_channel || !ev_value){
+ fprintf(stderr, "Failed to allocate memory\n");
+ ev_alloc = 0;
+ evs = 0;
+ return 1;
+ }
+
+ ev_alloc += map[u].destinations;
+ }
+
+ //enqueue channel events
+ //FIXME this might lead to one channel being mentioned multiple times in an apply call
+ for(p = 0; p < map[u].destinations; p++){
+ ev_channel[evs + p] = map[u].to[p];
+ ev_value[evs + p] = v;
+ }
+
+ evs += map[u].destinations;
return 0;
}
+void event_free(){
+ free(ev_channel);
+ free(ev_value);
+ ev_alloc = 0;
+}
+
int usage(char* fn){
fprintf(stderr, "MIDIMonster v0.1\n");
fprintf(stderr, "Usage:\n");
@@ -225,7 +271,14 @@ int main(int argc, char** argv){
goto bail;
}
- //TODO push collected events to target backends
+ //push collected events to target backends
+ if(evs && backends_notify(evs, ev_channel, ev_value)){
+ fprintf(stderr, "Backends failed to handle output\n");
+ goto bail;
+ }
+
+ //reset the event count
+ evs = 0;
}
rv = EXIT_SUCCESS;
@@ -237,6 +290,7 @@ bail:
instances_free();
map_free();
fds_free();
+ event_free();
return rv;
}
diff --git a/midimonster.h b/midimonster.h
index bd42d8f..27dcae4 100644
--- a/midimonster.h
+++ b/midimonster.h
@@ -12,7 +12,7 @@ struct _backend_channel;
struct _backend_instance;
struct _managed_fd;
-typedef int (*mmbackend_handle_event)(struct _backend_instance* inst, size_t channels, struct _backend_channel* c, struct _channel_value* v);
+typedef int (*mmbackend_handle_event)(struct _backend_instance* inst, size_t channels, struct _backend_channel** c, struct _channel_value* v);
typedef struct _backend_instance* (*mmbackend_create_instance)();
typedef struct _backend_channel* (*mmbackend_parse_channel)(struct _backend_instance* instance, char* spec);
typedef void (*mmbackend_free_channel)(struct _backend_channel* c);
diff --git a/monster.cfg b/monster.cfg
index 3ff2e3f..1da33c6 100644
--- a/monster.cfg
+++ b/monster.cfg
@@ -9,9 +9,11 @@ net = 0
[midi bcf]
read = BCF
+write = BCF
[midi lc1]
read = Launch Control
+write = Launch Control
[midi xlate]
@@ -24,9 +26,11 @@ output = true
net = 0
[map]
-net1.255 = lc1.cc0.1
-net1.256 = lc1.note0.9
-net1.257 = bcf.cc0.81
+bcf.cc0.81 = lc1.cc0.1
+lc1.cc0.1 = bcf.cc0.81
+bcf.cc0.82 = lc1.note0.9
+;net1.256 = lc1.note0.9
+;net1.257 = bcf.cc0.81
;net1.231 = foo.1
;net1.255 = lc1.cc0.1
;net1.231 = osc.f/channel5/ toggle=127