os dejo el código de un Client Alsa Midi demostrativo mínimo, que muestra come crear un simple Client del sistema audio Alsa, capaz de recibir algunos mensajes Midi (se seleccionaron más comunes y importantes) desde un otro Client de Alsa.
Como funciona por ejemplo con un teclado Midi:
- conectar el teclado Midi a el ordenador;
- iniciar el programa;
- abrir el Terminal y detectar el numero del ID Client del programa y aquello del teclado;
- conectar el teclado a el programa Midi con el comando: aconnect
(por ejemplo, si el Id del teclado Midi es 24 y el ID del progama es 128: aconnect 24:0 128:0 )
Public Struct snd_seq_event_t
type As Byte ' |- byte n° 0
flag As Byte ' |
tag As Byte ' |
queue As Byte ' |
timestamp1 As Integer ' |
timestamp2 As Integer ' | datos comunes a totos los mensajes Midi
source_id As Byte ' |
source_porta As Byte ' |
dest_id As Byte ' |
dest_porta As Byte ' |_ byte n° 15
channel As Byte ' byte n° 16 -|
note As Byte ' byte n° 17 |
velocity As Short ' byte n° 18 |< datos pertenecientes a los mensajes MIDI específicos
primoValore As Integer ' byte n° 20 |
secondoValore As Integer ' byte n° 24_|
End Struct
Private seq As Pointer
Library "libasound:2.0.0"
Private Const SND_SEQ_OPEN_INPUT As Integer = 2
Private Const SND_SEQ_PORT_CAP_WRITE As Integer = 2
Private Const SND_SEQ_PORT_CAP_SUBS_WRITE As Integer = 64
Private Const SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1048576
Private Const SND_SEQ_EVENT_NOTEON As Byte = 6
Private Const SND_SEQ_EVENT_NOTEOFF As Byte = 7
Private Const SND_SEQ_EVENT_CONTROLLER As Byte = 10
Private Const SND_SEQ_EVENT_PGMCHANGE As Byte = 11
' const char * snd_strerror(int errnum)
' Returns the message for an error code.
Private Extern snd_strerror(errnum As Integer) As String
' int snd_seq_open (snd_seq_t **handle, const char *name, int streams, int mode)
' Open the ALSA sequencer.
Private Extern snd_seq_open(handle As Pointer, name As String, streams As Integer, mode As Integer) As Integer
' int snd_seq_set_client_name(snd_seq_t* seq, const char* name)
' Set client name.
Private Extern snd_seq_set_client_name(handle As Pointer, name As String) As Integer
' int snd_seq_create_simple_port(snd_seq_t *seq, const char *name, unsigned int caps, unsigned int type)
' Create a port - simple version.
Private Extern snd_seq_create_simple_port(handle As Pointer, name As String, caps As Integer, type As Integer) As Integer
' int snd_seq_event_input(snd_seq_t *handle, snd_seq_event_t **ev)
' Retrieve an event from sequencer
Private Extern snd_seq_event_input(handle As Pointer, ev As Snd_seq_event_t) As Integer
Public Sub Main()
Dim idporta, err As Integer
err = snd_seq_open(VarPtr(seq), "default", SND_SEQ_OPEN_INPUT, 0)
If err < 0 Then Error.Raise("Imposible inizialiciar el subsistema 'seq' de ALSA: " & snd_strerror(err))
err = snd_seq_set_client_name(seq, "Client demostrativo de ALSA")
If err < 0 Then Error.Raise("Imposible asignar un nombre a el Client aplicativo de ALSA: " & snd_strerror(err))
idporta = snd_seq_create_simple_port(seq, "Puerta del Client demostrativo de ALSA", SND_SEQ_PORT_CAP_WRITE Or SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)
If idporta < 0 Then Error.Raise("Imposible crear una puerta del Client aplicativo de ALSA: " & snd_strerror(err))
intercettaMessaggiMidi()
End
Public Procedure intercettaMessaggiMidi()
Dim ev As Pointer
Dim midi@ As Snd_seq_event_t
While True
snd_seq_event_input(seq, VarPtr(ev))
midi@ = ev
Select Case midi@.type
Case SND_SEQ_EVENT_CONTROLLER
Print "Evento 'Control' al canal: "; midi@.channel, midi@.primoValore, midi@.secondoValore
Case SND_SEQ_EVENT_PGMCHANGE
Print "Evento 'Program Change' al canal: "; midi@.channel, midi@.secondoValore
Case SND_SEQ_EVENT_NOTEON
Print "Evento 'NoteOn' al canal: "; midi@.channel, midi@.note, midi@.velocity
Case SND_SEQ_EVENT_NOTEOFF
Print "Evento 'NoteOff' al canal: "; midi@.channel, midi@.note, midi@.velocity
End Select
Wend
Free(pfd)
End
type As Byte ' |- byte n° 0
flag As Byte ' |
tag As Byte ' |
queue As Byte ' |
timestamp1 As Integer ' |
timestamp2 As Integer ' | datos comunes a totos los mensajes Midi
source_id As Byte ' |
source_porta As Byte ' |
dest_id As Byte ' |
dest_porta As Byte ' |_ byte n° 15
channel As Byte ' byte n° 16 -|
note As Byte ' byte n° 17 |
velocity As Short ' byte n° 18 |< datos pertenecientes a los mensajes MIDI específicos
primoValore As Integer ' byte n° 20 |
secondoValore As Integer ' byte n° 24_|
End Struct
Private seq As Pointer
Library "libasound:2.0.0"
Private Const SND_SEQ_OPEN_INPUT As Integer = 2
Private Const SND_SEQ_PORT_CAP_WRITE As Integer = 2
Private Const SND_SEQ_PORT_CAP_SUBS_WRITE As Integer = 64
Private Const SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1048576
Private Const SND_SEQ_EVENT_NOTEON As Byte = 6
Private Const SND_SEQ_EVENT_NOTEOFF As Byte = 7
Private Const SND_SEQ_EVENT_CONTROLLER As Byte = 10
Private Const SND_SEQ_EVENT_PGMCHANGE As Byte = 11
' const char * snd_strerror(int errnum)
' Returns the message for an error code.
Private Extern snd_strerror(errnum As Integer) As String
' int snd_seq_open (snd_seq_t **handle, const char *name, int streams, int mode)
' Open the ALSA sequencer.
Private Extern snd_seq_open(handle As Pointer, name As String, streams As Integer, mode As Integer) As Integer
' int snd_seq_set_client_name(snd_seq_t* seq, const char* name)
' Set client name.
Private Extern snd_seq_set_client_name(handle As Pointer, name As String) As Integer
' int snd_seq_create_simple_port(snd_seq_t *seq, const char *name, unsigned int caps, unsigned int type)
' Create a port - simple version.
Private Extern snd_seq_create_simple_port(handle As Pointer, name As String, caps As Integer, type As Integer) As Integer
' int snd_seq_event_input(snd_seq_t *handle, snd_seq_event_t **ev)
' Retrieve an event from sequencer
Private Extern snd_seq_event_input(handle As Pointer, ev As Snd_seq_event_t) As Integer
Public Sub Main()
Dim idporta, err As Integer
err = snd_seq_open(VarPtr(seq), "default", SND_SEQ_OPEN_INPUT, 0)
If err < 0 Then Error.Raise("Imposible inizialiciar el subsistema 'seq' de ALSA: " & snd_strerror(err))
err = snd_seq_set_client_name(seq, "Client demostrativo de ALSA")
If err < 0 Then Error.Raise("Imposible asignar un nombre a el Client aplicativo de ALSA: " & snd_strerror(err))
idporta = snd_seq_create_simple_port(seq, "Puerta del Client demostrativo de ALSA", SND_SEQ_PORT_CAP_WRITE Or SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)
If idporta < 0 Then Error.Raise("Imposible crear una puerta del Client aplicativo de ALSA: " & snd_strerror(err))
intercettaMessaggiMidi()
End
Public Procedure intercettaMessaggiMidi()
Dim ev As Pointer
Dim midi@ As Snd_seq_event_t
While True
snd_seq_event_input(seq, VarPtr(ev))
midi@ = ev
Select Case midi@.type
Case SND_SEQ_EVENT_CONTROLLER
Print "Evento 'Control' al canal: "; midi@.channel, midi@.primoValore, midi@.secondoValore
Case SND_SEQ_EVENT_PGMCHANGE
Print "Evento 'Program Change' al canal: "; midi@.channel, midi@.secondoValore
Case SND_SEQ_EVENT_NOTEON
Print "Evento 'NoteOn' al canal: "; midi@.channel, midi@.note, midi@.velocity
Case SND_SEQ_EVENT_NOTEOFF
Print "Evento 'NoteOff' al canal: "; midi@.channel, midi@.note, midi@.velocity
End Select
Wend
Free(pfd)
End