[linux-audio-dev] How to use the alsa sequencer?

Stephen Cameron smcameron at yahoo.com
Fri Jun 16 20:24:01 UTC 2006


Hi,

I'm trying to figure out how to use the ALSA sequencer 
with my app.  (to date, I've been just using raw midi).

What I'm supposed to use for the "name" parameter for snd_seq_open
is not exactly clear.  I've been using "hw:0,0" and it returns zero,
but I'm not sure it's right (see aconnect -lio output below.);  That's
my soundcard, however, I'm really trying to send to a softsynth.

[scameron at zuul ~]$ amidi -l
Device    Name
hw:0,0    Audigy MPU-401 (UART)
hw:0,1    Audigy MPU-401 #2
hw:0,2    Emu10k1 Synth MIDI (16 subdevices)
hw:0,3    Emu10k1 Synth MIDI (16 subdevices)
[scameron at zuul ~]$

I have code to open and set up an alsa client port that looks
like this:

        struct midi_handle *midi_open_alsa(unsigned char *name)
        {
                int rc;
                struct midi_handle_alsa *mh;
                unsigned char clientname[255], portname[255];

                sprintf(clientname, "Gneutronica (%d)", getpid());

                mh = (struct midi_handle_alsa *) malloc(sizeof(*mh));
                if (mh == NULL)
                        return NULL;

                rc = snd_seq_open(&mh->seqp, name, SND_SEQ_OPEN_OUTPUT, 0);
                if (rc < 0) {
                        printf("snd_seq_open returns %d\n", rc);
                        free(mh);
                        return NULL;
                }
                rc = snd_seq_set_client_name(mh->seqp, clientname);
                if (rc < 0)
                        printf("snd_seq_set_client_name failed \n");
                sprintf(portname, "Gneutronica output (%d:%d)", getpid(), 0);
                mh->outputport = snd_seq_create_simple_port(mh->seqp, portname,
                                SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
                                SND_SEQ_PORT_TYPE_MIDI_GENERIC);
                if (mh->outputport < 0)
                        printf("snd_seq_create_simple_port failed\n");
                return (struct midi_handle *) mh;
        }

struct midi_handle_alsa is just this:

      struct midi_handle_alsa {
            snd_seq_t *seqp; /* alsa sequencer port */
            int outputport;
      };

This *appears* to work...  When I run my app, I can see this:

        [root at zuul ~]# aconnect -loi
        client 0: 'System' [type=kernel]
            0 'Timer           '
            1 'Announce        '
                Connecting To: 15:0
        client 14: 'Midi Through' [type=kernel]
            0 'Midi Through Port-0'
        client 16: 'Audigy MPU-401 #2' [type=kernel]
            0 'Audigy MPU-401 (UART)'
           32 'Audigy MPU-401 #2'
        client 17: 'Emu10k1 WaveTable' [type=kernel]
            0 'Emu10k1 Port 0  '
            1 'Emu10k1 Port 1  '
            2 'Emu10k1 Port 2  '
            3 'Emu10k1 Port 3  '
        client 128: 'FLUID Synth (6096)' [type=user]
            0 'Synth input port (6096:0)'
        client 129: 'Gneutronica (14693)' [type=user]
            0 'Gneutronica output (14693:0)'

There's my app, client 129, and I can do this:

        [root at zuul ~]# aconnect 129:0 128:0
        [root at zuul ~]# aconnect -loi
        client 0: 'System' [type=kernel]
            0 'Timer           '
            1 'Announce        '
                Connecting To: 15:0
        client 14: 'Midi Through' [type=kernel]
            0 'Midi Through Port-0'
        client 16: 'Audigy MPU-401 #2' [type=kernel]
            0 'Audigy MPU-401 (UART)'
           32 'Audigy MPU-401 #2'
        client 17: 'Emu10k1 WaveTable' [type=kernel]
            0 'Emu10k1 Port 0  '
            1 'Emu10k1 Port 1  '
            2 'Emu10k1 Port 2  '
            3 'Emu10k1 Port 3  '
        client 128: 'FLUID Synth (6096)' [type=user]
            0 'Synth input port (6096:0)'
                Connected From: 129:0
        client 129: 'Gneutronica (14693)' [type=user]
            0 'Gneutronica output (14693:0)'
                Connecting To: 128:0
        [root at zuul ~]#

Which, I think looks correct...  the aconnect makes
client 128:0 subscribe to 129:0, right?

But, when I try to send events from my app, they don't
seem to go through.

Here's the event sending code:

        void midi_noteon_alsa(struct midi_handle *mh,
                unsigned char channel,
                unsigned char value,
                unsigned char volume)
        {
                struct midi_handle_alsa *mha = (struct midi_handle_alsa *) mh;

                snd_seq_event_t ev;

                snd_seq_ev_clear(&ev);
                snd_seq_ev_set_source(&ev, mha->outputport);
                snd_seq_ev_set_subs(&ev);
                snd_seq_ev_set_direct(&ev);

                ev.type = SND_SEQ_EVENT_NOTEON;
                ev.data.note.channel = channel;
                ev.data.note.note = value;
                ev.data.note.velocity = volume;
                ev.data.note.off_velocity = 0;
                ev.data.note.duration = 100; /* it's drums... there is no note off. */

                printf("Sending event to port %d, note=%d, vel=%d, pid=%d\n",
                        mha->outputport, ev.data.note.note, ev.data.note.velocity, getpid());
                snd_seq_event_output(mha->seqp, &ev);
                return;
        }

I get output from my app that looks like:


        Bass Drum
        Sending event to port 0, note=35, vel=100, pid=14693
        Bass Drum
        Sending event to port 0, note=36, vel=100, pid=14693
        Rim Stick
        Sending event to port 0, note=37, vel=100, pid=14693
        Tom Hi
        Sending event to port 0, note=38, vel=100, pid=14693
        Hand Clap
        Sending event to port 0, note=39, vel=100, pid=14693

(The channel is zero.)

If I use raw midi (write to a file descriptor hooked to /dev/snd/midiC2D0
and use snd-virmidi acconnected to Fluidsynth... it works.

I'm obviously missing something, but it's not obvious to me
what it is...

Any ideas?

Thanks,

-- steve


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 



More information about the Linux-audio-dev mailing list