コード例 #1
0
ファイル: ALSAMidiIn.cpp プロジェクト: AHudon/SOEN6471_LMMS
int ALSAMidiIn::getalsaid()
{
    if(midi_handle) {
        snd_seq_client_info_t *seq_info;
        snd_seq_client_info_malloc(&seq_info);
        snd_seq_get_client_info(midi_handle, seq_info);
        int id = snd_seq_client_info_get_client(seq_info);
        snd_seq_client_info_free(seq_info);
        return id;
    }
    return -1;
}
/*
 * Class:     org_tritonus_lowlevel_alsa_AlsaSeqClientInfo
 * Method:    malloc
 * Signature: ()I
 */
JNIEXPORT jint JNICALL
Java_org_tritonus_lowlevel_alsa_AlsaSeqClientInfo_malloc
(JNIEnv* env, jobject obj)
{
	snd_seq_client_info_t*	handle;
	int			nReturn;

	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaSeqClientInfo_malloc(): begin\n"); }
	nReturn = snd_seq_client_info_malloc(&handle);
	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaSeqClientInfo_malloc(): handle: %p\n", handle); }
	setHandle(env, obj, handle);
	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaSeqClientInfo_malloc(): end\n"); }
	return nReturn;
}
コード例 #3
0
static QString __portName( snd_seq_t * _seq, const snd_seq_addr_t * _addr )
{
	snd_seq_client_info_t * cinfo;
	snd_seq_port_info_t * pinfo;

	snd_seq_client_info_malloc( &cinfo );
	snd_seq_port_info_malloc( &pinfo );

	snd_seq_get_any_port_info( _seq, _addr->client, _addr->port, pinfo );
	snd_seq_get_any_client_info( _seq, _addr->client, cinfo );

	const QString name = __portName( cinfo, pinfo );

	snd_seq_client_info_free( cinfo );
	snd_seq_port_info_free( pinfo );

	return name;
}
コード例 #4
0
static AlsaPort iterateMidiDevices (const bool forInput,
                                    StringArray& deviceNamesFound,
                                    const int deviceIndexToOpen)
{
    AlsaPort port;
    const AlsaClient::Ptr client (globalAlsaSequencer (forInput));

    if (snd_seq_t* const seqHandle = client->get())
    {
        snd_seq_system_info_t* systemInfo = nullptr;
        snd_seq_client_info_t* clientInfo = nullptr;

        if (snd_seq_system_info_malloc (&systemInfo) == 0)
        {
            if (snd_seq_system_info (seqHandle, systemInfo) == 0
                 && snd_seq_client_info_malloc (&clientInfo) == 0)
            {
                int numClients = snd_seq_system_info_get_cur_clients (systemInfo);

                while (--numClients >= 0 && ! port.isValid())
                    if (snd_seq_query_next_client (seqHandle, clientInfo) == 0)
                        port = iterateMidiClient (client, clientInfo, forInput,
                                                  deviceNamesFound, deviceIndexToOpen);

                snd_seq_client_info_free (clientInfo);
            }

            snd_seq_system_info_free (systemInfo);
        }

    }

    deviceNamesFound.appendNumbersToDuplicates (true, true);

    return port;
}
コード例 #5
0
int main(int argc, char **argv)
{
	int i;
	int listen_port = -1;
	char *client_name = "net2alsamidi";
	char *connect_client = NULL;
	int connect_port = -1;

	for (i = 1; i < argc; i++)
	{
		if (strcmp(argv[i], "--port") == 0)
		{
			if (++i == argc) usage(argv[0]);
			listen_port = atoi(argv[i]);
		}
		else if (strcmp(argv[i], "--name") == 0)
		{
			if (++i == argc) usage(argv[0]);
			client_name = argv[i];
		}
		else if (strcmp(argv[i], "--connect") == 0)
		{
			if (++i == argc) usage(argv[0]);
			connect_client = argv[i];
			if (++i == argc) usage(argv[0]);
			connect_port = atoi(argv[i]);
		}
		else
		{
			usage(argv[0]);
		}
	}

	if (listen_port > 0)
	{
		snd_seq_t *seq;
		int port;

		if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0)
		{
			fprintf(stderr, "Cannot open the ALSA sequencer.\n");
			exit(1);
		}

		snd_seq_set_client_name(seq, client_name);
		port = snd_seq_create_simple_port(seq, "from NetMIDI client", SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);

		if ((connect_client != NULL) && (connect_port >= 0))
		{
			int connect_client_id = -1;

			{
				snd_seq_client_info_t *client_info;
				snd_seq_client_info_malloc(&client_info);

				while (snd_seq_query_next_client(seq, client_info) == 0)
				{
					if (strcmp(snd_seq_client_info_get_name(client_info), connect_client) == 0)
					{
						connect_client_id = snd_seq_client_info_get_client(client_info);
						break;
					}
				}

				snd_seq_client_info_free(client_info);
			}

			if (connect_client_id < 0) connect_client_id = atoi(connect_client);
			snd_seq_connect_to(seq, port, connect_client_id, connect_port);
		}

		{
			int server_socket;
			struct sockaddr_in server_address;

			if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
			{
				fprintf(stderr, "Cannot start a NetMIDI server on port %d.\n", listen_port);
				exit(1);
			}

			server_address.sin_family = AF_INET;
			server_address.sin_port = htons(listen_port);
			server_address.sin_addr.s_addr = INADDR_ANY;

			if (bind(server_socket, (struct sockaddr *)(&server_address), sizeof(server_address)) < 0)
			{
				fprintf(stderr, "Cannot start a NetMIDI server on port %d.\n", listen_port);
				exit(1);
			}

			if (listen(server_socket, 1) < 0)
			{
				fprintf(stderr, "Cannot start a NetMIDI server on port %d.\n", listen_port);
				exit(1);
			}

			while (1)
			{
				int socket_to_client;

				if ((socket_to_client = accept(server_socket, NULL, NULL)) >= 0)
				{
					snd_midi_event_t *midi_event_parser;
					snd_seq_event_t *event;
					unsigned char buffer[BUFFER_SIZE];
					int bytes_read;

					{
						char one = 1;
						setsockopt(socket_to_client, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
					}

					snd_midi_event_new(BUFFER_SIZE, &midi_event_parser);

					while ((bytes_read = recv(socket_to_client, buffer, BUFFER_SIZE, 0)) > 0)
					{
						for (i = 0; i < bytes_read; i++)
						{
							if (snd_midi_event_encode_byte(midi_event_parser, buffer[i], event) == 1)
							{
								snd_seq_event_output_direct(seq, event);
							}
						}
					}

					snd_midi_event_free(midi_event_parser);
					close(socket_to_client);
				}
			}

			close(server_socket);
		}

		snd_seq_delete_simple_port(seq, port);
		snd_seq_close(seq);
	}
	else
	{
		usage(argv[0]);
	}

	return 0;
}
コード例 #6
0
ファイル: s_midi_alsa.c プロジェクト: Angeldude/pd
void sys_alsa_do_open_midi(int nmidiin, int *midiinvec,
    int nmidiout, int *midioutvec)
{

    char portname[50];
    int err = 0;
    int client;
    int i;
    snd_seq_client_info_t *alsainfo;

    alsa_nmidiin = 0;
    alsa_nmidiout = 0;

    if (nmidiout == 0 && nmidiin == 0) return;

    if(nmidiin>MAXMIDIINDEV )
      {
        post("midi input ports reduced to maximum %d", MAXMIDIINDEV);
        nmidiin=MAXMIDIINDEV;
      }
    if(nmidiout>MAXMIDIOUTDEV)
      {
        post("midi output ports reduced to maximum %d", MAXMIDIOUTDEV);
        nmidiout=MAXMIDIOUTDEV;
      }

    if (nmidiin>0 && nmidiout>0)
        err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_DUPLEX,0);
    else if (nmidiin > 0)
        err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_INPUT,0);
    else if (nmidiout > 0)
        err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_OUTPUT,0);
    
    if (err!=0)
    {
            sys_setalarm(1000000);
            post("couldn't open alsa sequencer");
            return;
    }
    for (i=0;i<nmidiin;i++)
    {
        int port;
        sprintf(portname,"Pure Data Midi-In %d",i+1);
        port = snd_seq_create_simple_port(midi_handle,portname,
                                          SND_SEQ_PORT_CAP_WRITE |SND_SEQ_PORT_CAP_SUBS_WRITE, 
                                          SND_SEQ_PORT_TYPE_APPLICATION);
        alsa_midiinfd[i] = port;        
        if (port < 0) goto error;        
    }

    for (i=0;i<nmidiout;i++)
    {
        int port;
        sprintf(portname,"Pure Data Midi-Out %d",i+1);
        port = snd_seq_create_simple_port(midi_handle,portname,
                                          SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, 
                                          SND_SEQ_PORT_TYPE_APPLICATION);
        alsa_midioutfd[i] = port;       
        if (port < 0) goto error;        
    }
   
    snd_seq_client_info_malloc(&alsainfo);
    snd_seq_get_client_info(midi_handle,alsainfo);
    snd_seq_client_info_set_name(alsainfo,"Pure Data");
    client = snd_seq_client_info_get_client(alsainfo);
    snd_seq_set_client_info(midi_handle,alsainfo);
    snd_seq_client_info_free(alsainfo);
    post("Opened Alsa Client %d in:%d out:%d",client,nmidiin,nmidiout);
    sys_setalarm(0);
    snd_midi_event_new(ALSA_MAX_EVENT_SIZE,&midiev);
    alsa_nmidiout = nmidiout;
    alsa_nmidiin = nmidiin;

    return;
 error:
    sys_setalarm(1000000);
    post("couldn't open alsa MIDI output device");
    return;
}
コード例 #7
0
void MidiAlsaSeq::updatePortList()
{
	QStringList readablePorts;
	QStringList writablePorts;

	// get input- and output-ports
	snd_seq_client_info_t * cinfo;
	snd_seq_port_info_t * pinfo;

	snd_seq_client_info_malloc( &cinfo );
	snd_seq_port_info_malloc( &pinfo );

	snd_seq_client_info_set_client( cinfo, -1 );

	m_seqMutex.lock();

	while( snd_seq_query_next_client( m_seqHandle, cinfo ) >= 0 )
	{
		int client = snd_seq_client_info_get_client( cinfo );

		snd_seq_port_info_set_client( pinfo, client );
		snd_seq_port_info_set_port( pinfo, -1 );
		while( snd_seq_query_next_port( m_seqHandle, pinfo ) >= 0 )
		{
			// we need both READ and SUBS_READ
			if( ( snd_seq_port_info_get_capability( pinfo )
			     & ( SND_SEQ_PORT_CAP_READ |
					SND_SEQ_PORT_CAP_SUBS_READ ) ) ==
					( SND_SEQ_PORT_CAP_READ |
					  	SND_SEQ_PORT_CAP_SUBS_READ ) )
			{
				readablePorts.push_back( __portName( cinfo, pinfo ) );
			}
			if( ( snd_seq_port_info_get_capability( pinfo )
			     & ( SND_SEQ_PORT_CAP_WRITE |
					SND_SEQ_PORT_CAP_SUBS_WRITE ) ) ==
					( SND_SEQ_PORT_CAP_WRITE |
					  	SND_SEQ_PORT_CAP_SUBS_WRITE ) )
			{
				writablePorts.push_back( __portName( cinfo, pinfo ) );
			}
		}
	}

	m_seqMutex.unlock();


	snd_seq_client_info_free( cinfo );
	snd_seq_port_info_free( pinfo );

	if( m_readablePorts != readablePorts )
	{
		m_readablePorts = readablePorts;
		emit readablePortsChanged();
	}

	if( m_writablePorts != writablePorts )
	{
		m_writablePorts = writablePorts;
		emit writablePortsChanged();
	}
}
コード例 #8
0
ファイル: port.c プロジェクト: Llefjord/jack1
struct a2j_port *
a2j_port_create (alsa_midi_driver_t * driver, int dir, snd_seq_addr_t addr, const snd_seq_port_info_t * info)
{
	struct a2j_port *port;
	int err;
	int client;
	snd_seq_client_info_t * client_info_ptr;
	int jack_caps;
	struct a2j_stream * stream_ptr;

	stream_ptr = &driver->stream[dir];

	if ((err = snd_seq_client_info_malloc (&client_info_ptr)) != 0) {
		a2j_error("Failed to allocate client info");
		goto fail;
	}

	client = snd_seq_port_info_get_client (info);

	err = snd_seq_get_any_client_info (driver->seq, client, client_info_ptr);
	if (err != 0) {
		a2j_error("Failed to get client info");
		goto fail_free_client_info;
	}

	a2j_debug ("client name: '%s'", snd_seq_client_info_get_name(client_info_ptr));
	a2j_debug ("port name: '%s'", snd_seq_port_info_get_name(info));

	port = calloc (1, sizeof(struct a2j_port));
	if (!port) {
		goto fail_free_client_info;
	}

	port->driver_ptr = driver;
	port->jack_port = JACK_INVALID_PORT;
	port->remote = addr;

	a2j_port_fill_name (port, dir, client_info_ptr, info, false);

	/* Add port to list early, before registering to JACK, so map functionality is guaranteed to work during port registration */
	list_add_tail (&port->siblings, &stream_ptr->list);
	
	if (dir == A2J_PORT_CAPTURE) {
		jack_caps = JackPortIsOutput;
	} else {
		jack_caps = JackPortIsInput;
	}

	/* mark anything that looks like a hardware port as physical&terminal */
	if (snd_seq_port_info_get_type (info) & (SND_SEQ_PORT_TYPE_HARDWARE|SND_SEQ_PORT_TYPE_PORT|SND_SEQ_PORT_TYPE_SPECIFIC)) {
		jack_caps |= JackPortIsPhysical|JackPortIsTerminal;
	}

	port->jack_port = jack_port_register (driver->jack_client, port->name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0);
	if (port->jack_port == JACK_INVALID_PORT) {
		a2j_error("jack_port_register() failed for '%s'", port->name);
		goto fail_free_port;
	}

	if (dir == A2J_PORT_CAPTURE) {
		err = a2j_alsa_connect_from (driver, port->remote.client, port->remote.port);
	} else {
		err = snd_seq_connect_to (driver->seq, driver->port_id, port->remote.client, port->remote.port);
	}

	if (err) {
		a2j_debug("port skipped: %s", port->name);
		goto fail_free_port;
	}

	port->inbound_events = jack_ringbuffer_create(MAX_EVENT_SIZE*16);

	a2j_debug("port created: %s", port->name);
	return port;

  fail_free_port:
	list_del (&port->siblings);

	a2j_port_free (port);

  fail_free_client_info:
	snd_seq_client_info_free (client_info_ptr);

  fail:
	return NULL;
}
コード例 #9
0
ファイル: midi_hardware.cpp プロジェクト: EQ4/genesis
int create_midi_hardware(GenesisContext *context,
        const char *client_name,
        void (*events_signal)(struct MidiHardware *),
        void (*on_devices_change)(struct MidiHardware *),
        void *userdata,
        struct MidiHardware **out_midi_hardware)
{
    *out_midi_hardware = nullptr;

    struct MidiHardware *midi_hardware = create_zero<MidiHardware>();
    if (!midi_hardware) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorNoMem;
    }
    midi_hardware->context = context;
    midi_hardware->on_buffer_overrun = default_on_buffer_overrun;
    midi_hardware->events_signal = events_signal;
    midi_hardware->on_devices_change = on_devices_change;
    midi_hardware->userdata = userdata;

    if (!(midi_hardware->mutex = os_mutex_create())) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorNoMem;
    }

    if (snd_seq_open(&midi_hardware->seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    if (snd_seq_set_client_name(midi_hardware->seq, client_name) < 0) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    snd_seq_client_info_malloc(&midi_hardware->client_info);
    snd_seq_port_info_malloc(&midi_hardware->port_info);

    if (!midi_hardware->client_info || !midi_hardware->port_info) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorNoMem;
    }

    if (snd_seq_create_simple_port(midi_hardware->seq, "genesis",
                SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
                SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION) < 0)
    {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    int err = midi_hardware_refresh(midi_hardware);
    if (err) {
        destroy_midi_hardware(midi_hardware);
        return err;
    }

    if (!midi_hardware->system_announce_device) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    if (snd_seq_connect_from(midi_hardware->seq, 0,
                midi_hardware->system_announce_device->client_id,
                midi_hardware->system_announce_device->port_id) < 0)
    {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    if (snd_seq_get_client_info(midi_hardware->seq, midi_hardware->client_info) < 0) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    midi_hardware->client_id = snd_seq_client_info_get_client(midi_hardware->client_info);
    if (snd_seq_connect_from(midi_hardware->seq, 0, midi_hardware->client_id, 0) < 0) {
        destroy_midi_hardware(midi_hardware);
        return GenesisErrorOpeningMidiHardware;
    }

    if ((err = os_thread_create(midi_thread, midi_hardware, false, &midi_hardware->thread))) {
        destroy_midi_hardware(midi_hardware);
        return err;
    }

    *out_midi_hardware = midi_hardware;
    return 0;
}
コード例 #10
0
//==============================================================================
static snd_seq_t* iterateDevices (const bool forInput,
                                  StringArray& deviceNamesFound,
                                  const int deviceIndexToOpen)
{
    snd_seq_t* returnedHandle = 0;
    snd_seq_t* seqHandle;

    if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
                                                      : SND_SEQ_OPEN_OUTPUT, 0) == 0)
    {
        snd_seq_system_info_t* systemInfo;
        snd_seq_client_info_t* clientInfo;

        if (snd_seq_system_info_malloc (&systemInfo) == 0)
        {
            if (snd_seq_system_info (seqHandle, systemInfo) == 0
                 && snd_seq_client_info_malloc (&clientInfo) == 0)
            {
                int numClients = snd_seq_system_info_get_cur_clients (systemInfo);

                while (--numClients >= 0 && returnedHandle == 0)
                {
                    if (snd_seq_query_next_client (seqHandle, clientInfo) == 0)
                    {
                        snd_seq_port_info_t* portInfo;
                        if (snd_seq_port_info_malloc (&portInfo) == 0)
                        {
                            int numPorts = snd_seq_client_info_get_num_ports (clientInfo);
                            const int client = snd_seq_client_info_get_client (clientInfo);

                            snd_seq_port_info_set_client (portInfo, client);
                            snd_seq_port_info_set_port (portInfo, -1);

                            while (--numPorts >= 0)
                            {
                                if (snd_seq_query_next_port (seqHandle, portInfo) == 0
                                     && (snd_seq_port_info_get_capability (portInfo)
                                           & (forInput ? SND_SEQ_PORT_CAP_READ
                                                       : SND_SEQ_PORT_CAP_WRITE)) != 0)
                                {
                                    deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo));

                                    if (deviceNamesFound.size() == deviceIndexToOpen + 1)
                                    {
                                        const int sourcePort = snd_seq_port_info_get_port (portInfo);
                                        const int sourceClient = snd_seq_client_info_get_client (clientInfo);

                                        if (sourcePort != -1)
                                        {
                                            snd_seq_set_client_name (seqHandle,
                                                                     forInput ? "Juce Midi Input"
                                                                              : "Juce Midi Output");

                                            const int portId
                                                = snd_seq_create_simple_port (seqHandle,
                                                                              forInput ? "Juce Midi In Port"
                                                                                       : "Juce Midi Out Port",
                                                                              forInput ? (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);

                                            snd_seq_connect_from (seqHandle, portId, sourceClient, sourcePort);

                                            returnedHandle = seqHandle;
                                        }
                                    }
                                }
                            }

                            snd_seq_port_info_free (portInfo);
                        }
                    }
                }

                snd_seq_client_info_free (clientInfo);
            }

            snd_seq_system_info_free (systemInfo);
        }

        if (returnedHandle == 0)
            snd_seq_close (seqHandle);
    }

    deviceNamesFound.appendNumbersToDuplicates (true, true);

    return returnedHandle;
}
コード例 #11
0
int main(int argc, char **argv)
{
	int i;
	char *connect_client = NULL;
	int connect_port = -1;

	for (i = 1; i < argc; i++)
	{
		if (strcmp(argv[i], "--prefix") == 0)
		{
			if (++i == argc) usage(argv[0]);
			prefix = argv[i];
		}
		else if (strcmp(argv[i], "--timeout") == 0)
		{
			if (++i == argc) usage(argv[0]);
			timeout = atoi(argv[i]);
		}
		else if (strcmp(argv[i], "--confirmation") == 0)
		{
			if (++i == argc) usage(argv[0]);
			confirmation_command_pattern = argv[i];
		}
		else if (strcmp(argv[i], "--connect") == 0)
		{
			if (++i == argc) usage(argv[0]);
			connect_client = argv[i];
			if (++i == argc) usage(argv[0]);
			connect_port = atoi(argv[i]);
		}
		else
		{
			usage(argv[0]);
		}
	}

	{
		snd_seq_t *seq;
		int port;

		if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_INPUT, 0) < 0)
		{
			fprintf(stderr, "Cannot open the ALSA sequencer.\n");
			exit(1);
		}

		snd_seq_set_client_name(seq, "Brainstorm");
		port = snd_seq_create_simple_port(seq, "Brainstorm recording port", SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);

		if ((connect_client != NULL) && (connect_port >= 0))
		{
			int connect_client_id = -1;

			{
				snd_seq_client_info_t *client_info;
				snd_seq_client_info_malloc(&client_info);

				while (snd_seq_query_next_client(seq, client_info) == 0)
				{
					if (strcmp(snd_seq_client_info_get_name(client_info), connect_client) == 0)
					{
						connect_client_id = snd_seq_client_info_get_client(client_info);
						break;
					}
				}

				snd_seq_client_info_free(client_info);
			}

			if (connect_client_id < 0) connect_client_id = atoi(connect_client);
			snd_seq_connect_from(seq, port, connect_client_id, connect_port);
		}

		signal(SIGALRM, alarm_handler);

		{
			snd_seq_event_t *event;

			while (snd_seq_event_input(seq, &event) >= 0)
			{
				switch (event->type)
				{
					case SND_SEQ_EVENT_NOTEOFF:
					{
						alarm(timeout);
						create_midi_file_for_first_event();
						MidiFileTrack_createNoteOffEvent(track, get_tick(), event->data.note.channel, event->data.note.note, event->data.note.velocity);
						break;
					}
					case SND_SEQ_EVENT_NOTEON:
					{
						alarm(timeout);
						create_midi_file_for_first_event();
						MidiFileTrack_createNoteOnEvent(track, get_tick(), event->data.note.channel, event->data.note.note, event->data.note.velocity);
						break;
					}
					case SND_SEQ_EVENT_KEYPRESS:
					{
						alarm(timeout);
						create_midi_file_for_first_event();
						MidiFileTrack_createKeyPressureEvent(track, get_tick(), event->data.note.channel, event->data.note.note, event->data.note.velocity);
						break;
					}
					case SND_SEQ_EVENT_CONTROLLER:
					{
						alarm(timeout);
						create_midi_file_for_first_event();
						MidiFileTrack_createControlChangeEvent(track, get_tick(), event->data.control.channel, event->data.control.param, event->data.control.value);
						break;
					}
					case SND_SEQ_EVENT_PGMCHANGE:
					{
						alarm(timeout);
						create_midi_file_for_first_event();
						MidiFileTrack_createProgramChangeEvent(track, get_tick(), event->data.control.channel, event->data.control.value);
						break;
					}
					case SND_SEQ_EVENT_CHANPRESS:
					{
						alarm(timeout);
						create_midi_file_for_first_event();
						MidiFileTrack_createChannelPressureEvent(track, get_tick(), event->data.control.channel, event->data.control.value);
						break;
					}
					case SND_SEQ_EVENT_PITCHBEND:
					{
						alarm(timeout);
						create_midi_file_for_first_event();
						MidiFileTrack_createPitchWheelEvent(track, get_tick(), event->data.control.channel, event->data.control.value);
						break;
					}
					default:
					{
						/* I'm ignoring the pseudoevents which ALSA provides as convenience features (SND_SEQ_EVENT_NOTE, SND_SEQ_EVENT_CONTROL14, SND_SEQ_EVENT_NONREGPARAM, and SND_SEQ_EVENT_REGPARAM).  Hopefully I can find some way to convince ALSA to normalize them into true MIDI events. */
						break;
					}
				}
			}
		}
	}

	return 0;
}