For those looking to develop MIDI applications, good examples are often needed to get you started.
The following examples were posted to the LAD mailing list in a thread about examples and documentation/tutorials.
Below is a little sequencer routine from Dr. Matthias Nagorni. More examples can be obtained from Matthias's site which is listed in the Links section.
You compile it like so:
[phil@beatbox] $ gcc seqdemo.c -o seqdemo -lasound #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <alsa/asoundlib.h> snd_seq_t *open_seq(); void midi_action(snd_seq_t *seq_handle); snd_seq_t *open_seq() { snd_seq_t *seq_handle; int portid; if (snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, "Error opening ALSA sequencer.\n"); exit(1); } snd_seq_set_client_name(seq_handle, "ALSA Sequencer Demo"); if ((portid = snd_seq_create_simple_port(seq_handle, "ALSA Sequencer Demo", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "Error creating sequencer port.\n"); exit(1); } return(seq_handle); } void midi_action(snd_seq_t *seq_handle) { snd_seq_event_t *ev; do { snd_seq_event_input(seq_handle, &ev); switch (ev->type) { case SND_SEQ_EVENT_CONTROLLER: fprintf(stderr, "Control event on Channel %2d: %5d \r", ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_PITCHBEND: fprintf(stderr, "Pitchbender event on Channel %2d: %5d \r", ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_NOTEON: fprintf(stderr, "Note On event on Channel %2d: %5d \r", ev->data.control.channel, ev->data.note.note); break; case SND_SEQ_EVENT_NOTEOFF: fprintf(stderr, "Note Off event on Channel %2d: %5d \r", ev->data.control.channel, ev->data.note.note); break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); } int main(int argc, char *argv[]) { snd_seq_t *seq_handle; int npfd; struct pollfd *pfd; seq_handle = open_seq(); npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN); pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd)); snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN); while (1) { if (poll(pfd, npfd, 100000) > 0) { midi_action(seq_handle); } } }
Below is a ALSA 0.9 MIDI redirector by Nick Dowell.
/* ALSA Sequencer MIDI redirector. Redirects the input to outputs determined by the MIDI channel (as requested by Nathaniel Virgo on Linux-Audio-Dev ;-) based on Dr. Matthias Nagorni's ALSA seq example Nick Dowell <nixx@nixx.org.uk> */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <alsa/asoundlib.h> int main() { snd_seq_t *seq_handle; snd_seq_event_t *ev; int i; int portid; /* input port */ int oportid[16]; /* output ports */ int npfd; struct pollfd *pfd; char txt[20]; if (snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, "Error opening ALSA sequencer.\n"); exit(1); } snd_seq_set_client_name(seq_handle, "MIDI Redirect"); /* open one input port */ if ((portid = snd_seq_create_simple_port (seq_handle, "Input", SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "fatal error: could not open input port.\n"); exit(1); } /* open 16 output ports for the MIDI channels */ for (i=0; i<16; i++){ sprintf( txt, "MIDI Channel %d", i ); if ((oportid[i] = snd_seq_create_simple_port (seq_handle, txt, SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "fatal error: could not open output port.\n"); exit(1); } } npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN); pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd)); snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN); while (1) /* main loop */ if (poll(pfd, npfd, 1000000) > 0){ do { snd_seq_event_input(seq_handle, &ev); snd_seq_ev_set_source( ev, oportid[ev->data.control.channel] ); snd_seq_ev_set_subs( ev ); snd_seq_ev_set_direct( ev ); snd_seq_event_output_direct( seq_handle, ev ); snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); } return 0; }
Below is an example of writing data to the OSS /dev/midi interface by Craig Stuart Sapp.
More examples can be found at Craig's site listed in the Links section.
// // Programmer: Craig Stuart Sapp [craig@ccrma.stanford.edu] // Creation Date: Mon Dec 21 18:00:42 PST 1998 // Last Modified: Mon Dec 21 18:00:42 PST 1998 // Filename: ...linuxmidi/output/method1.c // Syntax: C // $Smake: gcc -O -o devmidiout devmidiout.c && strip devmidiout // #include <linux/soundcard.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> int main(void) { char* device = "/dev/midi" ; unsigned char data[3] = {0x90, 60, 127}; // step 1: open the OSS device for writing int fd = open(device, O_WRONLY, 0); if (fd < 0) { printf("Error: cannot open %s\n", device); exit(1); } // step 2: write the MIDI information to the OSS device write(fd, data, sizeof(data)); // step 3: (optional) close the OSS device close(fd); return 0; }