ALSA e Gambas: Connettere due Client mediante la sottoscrizione delle porte
Da Gambas-it.org - Wikipedia.
(Reindirizzamento da Connettere due Client mediante la sottoscrizione delle porte)
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