diff options
| -rw-r--r-- | artnet.c | 2 | ||||
| -rw-r--r-- | backend.c | 6 | ||||
| -rw-r--r-- | midi.c | 111 | ||||
| -rw-r--r-- | midi.h | 6 | ||||
| -rw-r--r-- | midimonster.h | 2 | 
5 files changed, 111 insertions, 16 deletions
| @@ -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){ @@ -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"); @@ -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(){ @@ -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. | 
