ALSA e Gambas: Connettere due Client mediante la sottoscrizione delle porte
Da Gambas-it.org - Wikipedia.
Mostriamo di seguito un esempio di applicativo che consente la sottoscrizione della connessione delle porte di due Client di Alsa, nonché la successiva disconnessione.
Private seq As Pointer Library "libasound:2.0.0" Private Const SND_SEQ_OPEN_DUPLEX As Integer = 3 Private Const SND_SEQ_PORT_CAP_READ As Integer = 1 Private Const SND_SEQ_PORT_CAP_SUBS_READ As Integer = 32 ' 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_client_id(snd_seq_t * seq) ' Get the client id. Private Extern snd_seq_client_id(handle As Pointer) As Integer ' int snd_seq_parse_address (snd_seq_t *seq, snd_seq_addr_t *addr, const char *str) ' Parse the given string and get the sequencer address. Private Extern snd_seq_parse_address(handle As Pointer, addr As Pointer, charstr As String) As Integer ' int snd_seq_port_subscribe_malloc (snd_seq_port_subscribe_t **ptr) ' Allocate an empty snd_seq_port_subscribe_t using standard malloc. Private Extern snd_seq_port_subscribe_malloc(ptr As Pointer) As Integer ' void snd_seq_port_subscribe_set_sender (snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr) ' Set sender address of a port_subscribe container. Private Extern snd_seq_port_subscribe_set_sender(pinfo As Pointer, addr As Pointer) ' void snd_seq_port_subscribe_set_dest (snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr) ' Set destination address of a port_subscribe container. Private Extern snd_seq_port_subscribe_set_dest(pinfo As Pointer, addr As Pointer) ' void snd_seq_port_subscribe_set_queue (snd_seq_port_subscribe_t *info, int q) ' Set the queue id of a port_subscribe container. Private Extern snd_seq_port_subscribe_set_queue(pinfo As Pointer, qI As Integer) ' void snd_seq_port_subscribe_set_exclusive (snd_seq_port_subscribe_t *info, int val) ' Set the exclusive mode of a port_subscribe container. Private Extern snd_seq_port_subscribe_set_exclusive(pinfo As Pointer, vI As Integer) ' void snd_seq_port_subscribe_set_time_update (snd_seq_port_subscribe_t *info, int val) ' Set the time-update mode of a port_subscribe container. Private Extern snd_seq_port_subscribe_set_time_update(pinfo As Pointer, vI As Integer) ' void snd_seq_port_subscribe_set_time_real (snd_seq_port_subscribe_t *info, int val) ' Set the real-time mode of a port_subscribe container. Private Extern snd_seq_port_subscribe_set_time_real(pinfo As Pointer, vI As Integer) ' int snd_seq_get_port_subscription (snd_seq_t *handle, snd_seq_port_subscribe_t *sub) ' Obtain subscription information. Private Extern snd_seq_get_port_subscription(handle As Pointer, subP As Pointer) As Integer ' int snd_seq_subscribe_port (snd_seq_t *handle, snd_seq_port_subscribe_t *sub) ' Subscribe a port connection. Private Extern snd_seq_subscribe_port(handle As Pointer, subP As Pointer) As Integer ' int snd_seq_unsubscribe_port (snd_seq_t *handle, snd_seq_port_subscribe_t *sub) ' Unsubscribe a connection between ports. Private Extern snd_seq_unsubscribe_port(handle As Pointer, subP As Pointer) As Integer ' const char * snd_strerror (int errnum) ' Returns the message for an error code. Private Extern snd_strerror(err As Integer) As Pointer ' int snd_seq_close (snd_seq_t *handle) ' Close the sequencer. Private Extern snd_seq_close(handle As Pointer) Public Sub Main() inizializza_Alsa() sottoscrizione_Porte() chiude_Alsa() End Private Procedure inizializza_Alsa() Dim err, id As Integer err = snd_seq_open(VarPtr(seq), "default", SND_SEQ_OPEN_DUPLEX, 0) If err < 0 Then Error.Raise("Errore nell'apertura di Alsa: " & snd_strerror(err)) err = snd_seq_set_client_name(seq, "Connessione Porte Client ALSA") If err < 0 Then Error.Raise("Imposibile attribuire un nome al programma: " & snd_strerror(err)) id = snd_seq_client_id(seq) If id < 0 Then Error.Raise("Imposibile ottenere un ID del programma: " & snd_strerror(err)) End Private Procedure sottoscrizione_Porte() Dim err, queue, exclusive As Integer Dim sender, dest, convert_time, convert_real As Integer Dim subs As Pointer ' Imposta la sottoscrizione delle porte: err = snd_seq_parse_address(seq, VarPtr(sender), Application.Args[Application.Args.Count - 2]) If err < 0 Then Error.Raise("Indirizzo non vaido del mittente: " & snd_strerror(err)) err = snd_seq_parse_address(seq, VarPtr(dest), Application.Args[Application.Args.Count - 1]) If err < 0 Then Error.Raise("Indirizzo non vaido del Client destinatario: " & snd_strerror(err)) snd_seq_port_subscribe_malloc(VarPtr(subs)) snd_seq_port_subscribe_set_sender(subs, VarPtr(sender)) snd_seq_port_subscribe_set_dest(subs, VarPtr(dest)) snd_seq_port_subscribe_set_queue(subs, queue) snd_seq_port_subscribe_set_exclusive(subs, exclusive) snd_seq_port_subscribe_set_time_update(subs, convert_time) snd_seq_port_subscribe_set_time_real(subs, convert_real) ' Sottoscrizione e cancellazione della sottoscrizione: If Application.Args[1] = "d" Then err = snd_seq_get_port_subscription(seq, subs) If err < 0 Then Error.Raise("Nessuna sottoscrizione trovata: " & snd_strerror(err)) err = snd_seq_unsubscribe_port(seq, subs) If err < 0 Then Error.Raise("Tentativo di disconnessione fallito: " & snd_strerror(err)) Print "Disconnessione avvenuta !" Else err = snd_seq_get_port_subscription(seq, subs) If err = 0 Then Error.Raise("La connessione è già sottoscritta: " & snd_strerror(err)) err = snd_seq_subscribe_port(seq, subs) If err < 0 Then Error.Raise("Tentativo di connessione fallito: " & snd_strerror(err)) Print "Connessione avvenuta !" Endif End Private Procedure chiude_Alsa() snd_seq_close(seq) End
Per eseguire il suddetto codice, bisognerà creare il relativo eseguibile "a riga di comando". L'eseguibile andrà lanciato da Terminale:
- per connettere due porte: indicare il numero identificativo del Client che invia i dati Midi e quello della sua porta di uscita, e di seguito il numero identificativo del Client ricevente e quello della sua porta di entrata. Esempio:
connettore.gambas 14:0 128:0
- per disconnettere due Client: come il precedente punto premettendo la lettera "d". Esempio:
connettore.gambas d 14:0 128:0