aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--artnet.c2
-rw-r--r--backend.c6
-rw-r--r--midi.c111
-rw-r--r--midi.h6
-rw-r--r--midimonster.h2
5 files changed, 111 insertions, 16 deletions
diff --git a/artnet.c b/artnet.c
index 6eef2fe..598fed8 100644
--- a/artnet.c
+++ b/artnet.c
@@ -104,7 +104,7 @@ static channel* artnet_channel(instance* instance, char* spec){
fprintf(stderr, "Invalid ArtNet channel %s\n", spec);
return NULL;
}
- return mm_channel(instance, channel);
+ return mm_channel(instance, channel, 1);
}
static int artnet_set(size_t num, channel* c, channel_value* v){
diff --git a/backend.c b/backend.c
index f49bd91..2eb6fcf 100644
--- a/backend.c
+++ b/backend.c
@@ -9,7 +9,7 @@ static instance** instances = NULL;
static size_t nchannels = 0;
static channel** channels = NULL;
-channel* mm_channel(instance* i, uint64_t ident){
+channel* mm_channel(instance* i, uint64_t ident, uint8_t create){
size_t u;
for(u = 0; u < nchannels; u++){
if(channels[u]->instance == 0 && channels[u]->ident == ident){
@@ -17,6 +17,10 @@ channel* mm_channel(instance* i, uint64_t ident){
}
}
+ if(!create){
+ return NULL;
+ }
+
channel** new_chan = realloc(channels, (nchannels + 1) * sizeof(channel*));
if(!new_chan){
fprintf(stderr, "Failed to allocate memory\n");
diff --git a/midi.c b/midi.c
index 00ff0a4..ca1f66b 100644
--- a/midi.c
+++ b/midi.c
@@ -40,6 +40,10 @@ int midi_init(){
fprintf(stderr, "Failed to register MIDI backend\n");
return 1;
}
+
+ snd_seq_nonblock(sequencer, 1);
+
+ fprintf(stderr, "MIDI client ID is %d\n", snd_seq_client_id(sequencer));
return 0;
}
@@ -57,24 +61,43 @@ static int midi_configure(char* option, char* value){
}
static instance* midi_instance(){
- return mm_instance();
+ instance* inst = mm_instance();
+ if(!inst){
+ return NULL;
+ }
+
+ inst->impl = calloc(1, sizeof(midi_instance_data));
+ if(!inst->impl){
+ fprintf(stderr, "Failed to allocate memory\n");
+ return NULL;
+ }
+
+ return inst;
}
static int midi_configure_instance(instance* instance, char* option, char* value){
- if(!strcmp(option, "device")){
- //open i/o device
- return 0;
- }
- else if(!strcmp(option, "port")){
- //create midi port
+ midi_instance_data* data = (midi_instance_data*) instance->impl;
+
+ //FIXME maybe allow connecting more than one device
+ if(!strcmp(option, "read")){
+ //connect input device
+ if(data->read){
+ fprintf(stderr, "Port already connected to an input device\n");
+ return 1;
+ }
+ data->read = strdup(value);
return 0;
}
- else if(!strcmp(option, "mode")){
- //configure open mode
- //FIXME needed?
+ else if(!strcmp(option, "write")){
+ //connect output device
+ if(data->write){
+ fprintf(stderr, "Port already connected to an output device\n");
+ return 1;
+ }
+ data->write = strdup(value);
return 0;
}
-
+
fprintf(stderr, "Unknown MIDI instance option %s\n", option);
return 1;
}
@@ -124,7 +147,7 @@ static channel* midi_channel(instance* instance, char* spec){
ident.fields.control = strtoul(channel, NULL, 10);
if(ident.label){
- return mm_channel(instance, ident.label);
+ return mm_channel(instance, ident.label, 1);
}
return NULL;
@@ -141,7 +164,69 @@ static int midi_handle(size_t num, int* fd, void** data){
}
static int midi_start(){
- return 0;
+ size_t n, p;
+ int nfds, rv = 1;
+ struct pollfd* pfds = NULL;
+ instance** inst = NULL;
+ midi_instance_data* data = NULL;
+ snd_seq_addr_t addr;
+
+ if(mm_backend_instances(BACKEND_NAME, &n, &inst)){
+ fprintf(stderr, "Failed to fetch instance list\n");
+ return 1;
+ }
+
+ //create all ports
+ for(p = 0; p < n; p++){
+ data = (midi_instance_data*) inst[p]->impl;
+ data->port = snd_seq_create_simple_port(sequencer, inst[p]->name, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
+
+ //make connections
+ if(data->write){
+ fprintf(stderr, "Connecting output of instance %s to MIDI device %s\n", inst[p]->name, data->write);
+ if(snd_seq_parse_address(sequencer, &addr, data->write) == 0){
+ snd_seq_connect_to(sequencer, data->port, addr.client, addr.port);
+ }
+ else{
+ fprintf(stderr, "Failed to get destination device address: %s\n", data->write);
+ }
+ free(data->write);
+ data->write = NULL;
+ }
+
+ if(data->read){
+ fprintf(stderr, "Connecting input from MIDI device %s to instance %s\n", data->read, inst[p]->name);
+ if(snd_seq_parse_address(sequencer, &addr, data->read) == 0){
+ snd_seq_connect_from(sequencer, data->port, addr.client, addr.port);
+ }
+ else{
+ fprintf(stderr, "Failed to get source device address: %s\n", data->read);
+ }
+ free(data->read);
+ data->read = NULL;
+ }
+ }
+
+ //register all fds to core
+ nfds = snd_seq_poll_descriptors_count(sequencer, POLLIN | POLLOUT);
+ pfds = calloc(nfds, sizeof(struct pollfd));
+ if(!pfds){
+ fprintf(stderr, "Failed to allocate memory\n");
+ goto bail;
+ }
+ nfds = snd_seq_poll_descriptors(sequencer, pfds, nfds, POLLIN | POLLOUT);
+
+ fprintf(stderr, "Registering %d descriptors to core\n", nfds);
+ for(p = 0; p < nfds; p++){
+ mm_manage_fd(pfds[p].fd, BACKEND_NAME, 1, NULL);
+ }
+
+ rv = 0;
+
+bail:
+ free(pfds);
+ free(inst);
+ return rv;
}
static int midi_shutdown(){
diff --git a/midi.h b/midi.h
index c83345b..7a13f7c 100644
--- a/midi.h
+++ b/midi.h
@@ -9,3 +9,9 @@ static int midi_set(size_t num, channel* c, channel_value* v);
static int midi_handle(size_t num, int* fd, void** data);
static int midi_start();
static int midi_shutdown();
+
+typedef struct /*_midi_instance_data*/ {
+ int port;
+ char* read;
+ char* write;
+} midi_instance_data;
diff --git a/midimonster.h b/midimonster.h
index 181f1da..d548528 100644
--- a/midimonster.h
+++ b/midimonster.h
@@ -98,7 +98,7 @@ instance* mm_instance();
* For each channel with a non-NULL impl field, the backend
* will receive a call to its channel_free function.
*/
-channel* mm_channel(instance* i, uint64_t ident);
+channel* mm_channel(instance* i, uint64_t ident, uint8_t create);
/*
* Register a file descriptor to be selected on. The backend
* will be notified via the mmbackend_process_fd call.