The Linux MIDI-HOWTO : MIDI Development.

Next Previous Contents

## 9. MIDI Development.

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.

## 9.1 Example 1

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);
        }
      }
    }

## 9.2 Example 2

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;
    }

## 9.3 Example 3

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;
    }

Next Previous Contents