Differenze tra le versioni di "Alsa e Gambas: Client e Porte in Invio dati - Connessione della porta del programma con il Client Softsynth"
(2 versioni intermedie di uno stesso utente non sono mostrate) | |||
Riga 5: | Riga 5: | ||
La connessione delle porte del nostro applicativo con quella del ''Client'' Softsynth <SUP>[[[#Note|nota 1]]]</sup> può essere effettuata mediante la funzione: | La connessione delle porte del nostro applicativo con quella del ''Client'' Softsynth <SUP>[[[#Note|nota 1]]]</sup> può essere effettuata mediante la funzione: | ||
− | + | int [https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_middle.html#gab39e210c5d93e96c241644f334c6c9ca snd_seq_connect_to()] | |
− | |||
Nel nostro codice Gambas la dichiareremo con la consueta funzione Extern: | Nel nostro codice Gambas la dichiareremo con la consueta funzione Extern: | ||
<Font Color= #B22222>''Private '''EXTERN''' snd_seq_connect_to(seq As Pointer, myport As Integer, src_client As Integer, src_port As Integer) As Integer''</Font Color> | <Font Color= #B22222>''Private '''EXTERN''' snd_seq_connect_to(seq As Pointer, myport As Integer, src_client As Integer, src_port As Integer) As Integer''</Font Color> | ||
− | Questa funzione sarà utilizzata in routine come segue: | + | Questa funzione sarà poi utilizzata in routine come segue: |
<Font Color= #B22222> ''err = snd_seq_connect_to(handle, outport, dclient, dport)''</font color> | <Font Color= #B22222> ''err = snd_seq_connect_to(handle, outport, dclient, dport)''</font color> | ||
Riga 32: | Riga 31: | ||
---- | ---- | ||
− | ===Esempio | + | ===Esempio=== |
+ | Nel seguente esempio astratto si prende in considerazione una Struttura in Gambas, dichiarata con i membri analoghi alla Struttura originale di ALSA [https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html snd_seq_event_t], alla quale verranno assegnati alcuni valori che qui interessano. | ||
+ | <BR>Nell'esempio verrà mostrato l'uso della funzione esterna "[https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_middle.html#gab39e210c5d93e96c241644f334c6c9ca snd_seq_connect_to()]" e delle Costanti di indirizzamento generico degli ''Eventi Midi'' sopra citati. Si supporrà che il numero identificativo e della porta del ''SoftSynth, al quale collegarsi in uscita, sia: "128:0". | ||
Library "libasound:2.0.0" | Library "libasound:2.0.0" | ||
− | + | Public Struct <Font Color= #B22222>snd_seq_event_t</font> | |
type As Byte <Font Color= #006400>' '' byte indice n° 0''</font> | type As Byte <Font Color= #006400>' '' byte indice n° 0''</font> | ||
flags As Byte | flags As Byte | ||
Riga 52: | Riga 53: | ||
param As Integer <Font Color= #006400>' ''byte n° 20''</font> | param As Integer <Font Color= #006400>' ''byte n° 20''</font> | ||
value As Integer <Font Color= #006400>' ''byte n° 24''</font> | value As Integer <Font Color= #006400>' ''byte n° 24''</font> | ||
− | + | End Struct | |
Private Const SND_SEQ_OPEN_DUPLEX As Integer = 3 | Private Const SND_SEQ_OPEN_DUPLEX As Integer = 3 | ||
Riga 77: | Riga 78: | ||
' ''Get the client id.''</font> | ' ''Get the client id.''</font> | ||
Private Extern snd_seq_client_id(seq As Pointer) As Integer | Private Extern snd_seq_client_id(seq As Pointer) As Integer | ||
+ | |||
+ | <FONT Color=gray>' ''int snd_seq_alloc_named_queue (snd_seq_t * seq, CONST char * name)'' | ||
+ | ' ''Allocate a queue.''</font> | ||
+ | Private Extern snd_seq_alloc_queue(seq As Pointer, name As String) As Integer | ||
<FONT Color=gray>' ''int snd_seq_connect_to ( snd_seq_t * seq, int myport, int dest_client, int dest_port )'' | <FONT Color=gray>' ''int snd_seq_connect_to ( snd_seq_t * seq, int myport, int dest_client, int dest_port )'' | ||
Riga 82: | Riga 87: | ||
Private Extern <FONT Color=#006400><B>snd_seq_connect_to</b></font>(seq As Pointer, myport As Integer, dest_client As Integer, dest_port As Integer) As Integer | Private Extern <FONT Color=#006400><B>snd_seq_connect_to</b></font>(seq As Pointer, myport As Integer, dest_client As Integer, dest_port As Integer) As Integer | ||
− | + | ...etc... | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Public Sub Main() | |
Dim handle As Pointer | Dim handle As Pointer | ||
− | Dim | + | Dim id, porta, que As Integer |
Dim ev_midi As New Snd_seq_event_t <FONT Color=gray>' ''Dichiara la variabile del tipo della Struttura "snd_seq_event_t"''</font> | Dim ev_midi As New Snd_seq_event_t <FONT Color=gray>' ''Dichiara la variabile del tipo della Struttura "snd_seq_event_t"''</font> | ||
err = snd_seq_open(VarPtr(handle), "default", SND_SEQ_OPEN_DUPLEX, 0) | err = snd_seq_open(VarPtr(handle), "default", SND_SEQ_OPEN_DUPLEX, 0) | ||
− | |||
− | |||
snd_seq_set_client_name(handle, "Test") | snd_seq_set_client_name(handle, "Test") | ||
id = snd_seq_client_id(handle) | id = snd_seq_client_id(handle) | ||
− | |||
porta = snd_seq_create_simple_port(handle, "Uscita", 0, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION) | porta = snd_seq_create_simple_port(handle, "Uscita", 0, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION) | ||
− | |||
− | |||
que = snd_seq_alloc_queue(handle, "queue") | que = snd_seq_alloc_queue(handle, "queue") | ||
− | |||
<FONT Color=gray>' ''Assume che l'ID/porta dell'altro Client (Softsynth) sia 128:0''</font> | <FONT Color=gray>' ''Assume che l'ID/porta dell'altro Client (Softsynth) sia 128:0''</font> | ||
err = <FONT Color=#006400><B>snd_seq_connect_to</b></font>(handle, porta, <FONT Color=darkorange><B>128</b></font>, <FONT Color=darkorange><B>0</b></font>) | err = <FONT Color=#006400><B>snd_seq_connect_to</b></font>(handle, porta, <FONT Color=darkorange><B>128</b></font>, <FONT Color=darkorange><B>0</b></font>) | ||
− | |||
<FONT Color=gray>' '''Program Change'''</font> | <FONT Color=gray>' '''Program Change'''</font> | ||
Riga 139: | Riga 119: | ||
ev_midi.dest_port = <FONT Color=#B22222><B>SND_SEQ_ADDRESS_UNKNOWN</b></font> | ev_midi.dest_port = <FONT Color=#B22222><B>SND_SEQ_ADDRESS_UNKNOWN</b></font> | ||
ev_midi.channel = 0 | ev_midi.channel = 0 | ||
− | ev_midi.value = 44 | + | ev_midi.value = 44 |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ...etc... | |
− | |||
− | + | End | |
Versione attuale delle 14:10, 19 giu 2024
Per essere in grado di inviare dati Midi via ALSA dal nostro applicativo ad un altro programma, è necessario che entrambi i programmi si rapportino ad ALSA come suoi Client. Il sistema ALSA, pertanto, diventa Server dei due suoi Client.
Riferendoci al capitolo che stiamo trattando, quello relativo dell'invio dati Midi ad ALSA, la fattispecie più evidente e probabile è quella dell'invio di dati Midi a un Softsynth, affinché siano emessi i suoni e gli effetti connessi agli eventi Midi prodotti. In tal caso, dunque, anche il programma Softsynth prescelto, per poter ricevere i dati Midi, dovrà diventare un Client di ALSA, e il nostro applicativo, capace di inviare eventi Midi, dovrà connettersi a detto Softsynth.
In vero, la connessione avviene tra le porte dei due Client di ALSA, ed avviene sempre e comunque attraverso il sistema e le risorse di ALSA.
La connessione delle porte del nostro applicativo con quella del Client Softsynth [nota 1] può essere effettuata mediante la funzione:
int snd_seq_connect_to()
Nel nostro codice Gambas la dichiareremo con la consueta funzione Extern:
Private EXTERN snd_seq_connect_to(seq As Pointer, myport As Integer, src_client As Integer, src_port As Integer) As Integer
Questa funzione sarà poi utilizzata in routine come segue:
err = snd_seq_connect_to(handle, outport, dclient, dport)
A questo punto, lanciando da terminale il comando: cat /proc/asound/seq/clients, possiamo verificare:
- il numero identificativo e il nome del nostro Client;
- il numero ed il nome della porta del nostro Client;
- il numero identificativo del device (ad esempio QSynth) e della sua porta (con relativa indicazione delle capacità), al quale il Client si è connesso.
Cercando il nostro Client avremo infatti informazioni simili alle seguenti:
Client 129 : "Nome del nostro applicativo Client" [User] Port 0 : "Nome della Porta" (--e-) Connecting To: 128:0
che ovviamente vanno così interpretate: il Client avente numero identificativo 129 e chiamato "Nome del nostro applicativo Client", è connesso tramite la sua Porta, avente numero identificativo 0 e chiamata "Nome della porta", alla porta avente numero identificativo 0 di un altro Client di ALSA avente numero identificativo 128.
V'è da sottolineare che ai fini pratici dell'invio degli Eventi Midi ALSA la connessione così realizzata mediante la funzione esterna "snd_seq_connect_to()" si rende necessaria se ai membri client e port del membro snd_seq_addr_t dellaa Struttura degli Eventi Midi ALSA snd_seq_event_t sono rispettivamente valorizzati con le Costanti di ALSA:
SND_SEQ_ADDRESS_SUBSCRIBERS = 254 SND_SEQ_ADDRESS_UNKNOWN = 253
Esempio
Nel seguente esempio astratto si prende in considerazione una Struttura in Gambas, dichiarata con i membri analoghi alla Struttura originale di ALSA snd_seq_event_t, alla quale verranno assegnati alcuni valori che qui interessano.
Nell'esempio verrà mostrato l'uso della funzione esterna "snd_seq_connect_to()" e delle Costanti di indirizzamento generico degli Eventi Midi sopra citati. Si supporrà che il numero identificativo e della porta del SoftSynth, al quale collegarsi in uscita, sia: "128:0".
Library "libasound:2.0.0" Public Struct snd_seq_event_t type As Byte ' byte indice n° 0 flags As Byte tag As Byte queue As Byte tick_o_tv_sec As Integer tv_nsec As Integer source_client As Byte source_port As Byte dest_client As Byte dest_port As Byte ' byte n° 15 channel As Byte ' byte n° 16 note As Byte ' byte n° 17 velocity As Byte ' byte n° 18 off_velocity As Byte ' byte n° 19 param As Integer ' byte n° 20 value As Integer ' byte n° 24 End Struct Private Const SND_SEQ_OPEN_DUPLEX As Integer = 3 Private Const SND_SEQ_PORT_TYPE_MIDI_GENERIC As Integer = 2 Private Const SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1048576 Private Const SND_SEQ_ADDRESS_UNKNOWN As Byte = 253 Private Const SND_SEQ_ADDRESS_SUBSCRIBERS As Byte = 254 Private Enum SND_SEQ_EVENT_NOTEON = 6, SND_SEQ_EVENT_NOTEOFF, SND_SEQ_EVENT_KEYPRESS, SND_SEQ_EVENT_CONTROLLER = 10, SND_SEQ_EVENT_PGMCHANGE, SND_SEQ_EVENT_CHANPRESS, SND_SEQ_EVENT_PITCHBEND ' int snd_seq_open (snd_seq_t **seqp, const char * name, int streams, int mode) ' Open the ALSA sequencer. Private Extern snd_seq_open(seqp 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(seq 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) ' Creates a port with the given capability and type bits. Private Extern snd_seq_create_simple_port(seq As Pointer, name As String, caps As Integer, type As Integer) As Integer ' int snd_seq_client_id (snd_seq_t * seq) ' Get the client id. Private Extern snd_seq_client_id(seq As Pointer) As Integer ' int snd_seq_alloc_named_queue (snd_seq_t * seq, CONST char * name) ' Allocate a queue. Private Extern snd_seq_alloc_queue(seq As Pointer, name As String) As Integer ' int snd_seq_connect_to ( snd_seq_t * seq, int myport, int dest_client, int dest_port ) ' Connect from the given receiver port in the current client to the given destination client:port. Private Extern snd_seq_connect_to(seq As Pointer, myport As Integer, dest_client As Integer, dest_port As Integer) As Integer ...etc... Public Sub Main() Dim handle As Pointer Dim id, porta, que As Integer Dim ev_midi As New Snd_seq_event_t ' Dichiara la variabile del tipo della Struttura "snd_seq_event_t" err = snd_seq_open(VarPtr(handle), "default", SND_SEQ_OPEN_DUPLEX, 0) snd_seq_set_client_name(handle, "Test") id = snd_seq_client_id(handle) porta = snd_seq_create_simple_port(handle, "Uscita", 0, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION) que = snd_seq_alloc_queue(handle, "queue") ' Assume che l'ID/porta dell'altro Client (Softsynth) sia 128:0 err = snd_seq_connect_to(handle, porta, 128, 0) ' Program Change ev_midi.type = SND_SEQ_EVENT_PGMCHANGE ev_midi.flags = 0 ev_midi.tag = 0 ev_midi.queue = que ev_midi.tick_o_tv_sec = 0 ev_midi.source_client = id ev_midi.source_port = porta ev_midi.dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS ev_midi.dest_port = SND_SEQ_ADDRESS_UNKNOWN ev_midi.channel = 0 ev_midi.value = 44 ...etc... End
Note
[1] Qualora la connessione sia invece impostata esplicitamente con il subsistema ALSA:
client 14: 'Midi Through' [type=kernel] 0 'Midi Through Port-0'
(solitamente 14:0), bisognerà ricordare, dopo aver lanciato il nostro applicativo, di connettere - ad esempio con il comando aconnect da terminale - il sistema ALSA con il softsynth. In sostanza la catena di connessione risulterà in questo caso essere la seguente: Applicativo-->ALSA-->Softsynth.
[2] Corrispondenza tra "Note MIDI", frequenza sonora e note sul pentragramma