Differenze tra le versioni di "Creare un semplice Client di Jack con le risorse della libreria libjack"
Riga 11: | Riga 11: | ||
===Creazione di un Client e connessione di tipo ''mono'' al server ''jack''=== | ===Creazione di un Client e connessione di tipo ''mono'' al server ''jack''=== | ||
Viene creato un Client di ''Jack'', e vengono generate connessioni audio di tipo ''mono''. | Viene creato un Client di ''Jack'', e vengono generate connessioni audio di tipo ''mono''. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Private err As Integer | Private err As Integer | ||
Private client As Pointer | Private client As Pointer | ||
Riga 25: | Riga 18: | ||
Library "libjack:0.1.0" | Library "libjack:0.1.0" | ||
+ | |||
+ | Private Const JackNullOption As Byte = 0 | ||
+ | <FONT color=gray>' ''Private Const JACK_DEFAULT_MIDI_TYPE As String = "8 bit raw midi"''</font> | ||
+ | Private Const JACK_DEFAULT_AUDIO_TYPE As String = "32 bit float mono audio" | ||
+ | Private Const JackPortIsInput As Byte = 1 | ||
+ | Private Const JackPortIsOutput As Byte = 2 | ||
+ | Private Const JackPortIsPhysical As Byte = 4 | ||
<FONT color=gray>' ''jack_client_t * jack_client_open (const char *client_name, jack_options_t options, jack_status_t *status,...)'' | <FONT color=gray>' ''jack_client_t * jack_client_open (const char *client_name, jack_options_t options, jack_status_t *status,...)'' | ||
Riga 68: | Riga 68: | ||
− | + | Public Sub Form_Open() | |
<FONT color=gray>' ''Invoca la sotto-procedura per salvare in apposto file .c il codice sorgente della nostra libreria "ad hoc" e per crearla:''</font> | <FONT color=gray>' ''Invoca la sotto-procedura per salvare in apposto file .c il codice sorgente della nostra libreria "ad hoc" e per crearla:''</font> | ||
CreaLibjk() | CreaLibjk() | ||
− | + | End | |
− | + | Public Sub Button1_Click() | |
Dim nomeClient As String = "Client_1" | Dim nomeClient As String = "Client_1" | ||
Riga 84: | Riga 84: | ||
Dim status As Single | Dim status As Single | ||
+ | client = jack_client_open(nomeClient, JackNullOption, VarPtr(status), Null) | ||
+ | If client == 0 Then Error.Raise("Impossibile aprire una sessione del Client con il server Jack !") | ||
− | + | nomeClient = jack_get_client_name(client) | |
− | + | Print "\nNome del Client = "; nomeClient | |
− | |||
− | |||
− | |||
− | + | sample = jack_get_sample_rate(client) | |
− | + | Print "Campionamento = hz "; sample | |
− | + | Print "\n=========================================\n" | |
− | + | ||
− | + | input_port = jack_port_register(client, "input_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0) | |
− | |||
− | + | output_port = jack_port_register(client, "output_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0) | |
− | + | If (input_port == 0) Or (output_port == 0) Then Error.Raise("Nessuna porta di Jack disponibile !") | |
− | + | Invoca_Callback(client, input_port, output_port) | |
− | + | err = jack_activate(client) | |
− | + | If err <> 0 Then Print "Impossibile attivare il Client !" | |
− | + | ||
− | |||
<FONT color=gray>' ''Connette le porte:''</font> | <FONT color=gray>' ''Connette le porte:''</font> | ||
− | + | ports = jack_get_ports(client, "system:capture_1", Null, JackPortIsPhysical Or JackPortIsOutput) | |
− | + | If ports == 0 Then | |
− | + | Print "Impossibile agganciare alcuna porta fisica !" | |
− | + | Free(Object.Address(Button1)) | |
− | + | Quit | |
− | + | Endif | |
− | + | porta = String@(Pointer@(ports)) | |
− | + | nome_porta = jack_port_name(input_port) | |
− | + | Print porta, nome_porta | |
− | + | err = jack_connect(client, porta, nome_porta) | |
− | + | If err <> 0 Then Print "Impossibile connettere la porta d'Entrata !" | |
− | + | ||
− | |||
− | |||
<FONT color=gray>' ''Connette le porte:''</font> | <FONT color=gray>' ''Connette le porte:''</font> | ||
− | + | ports = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsInput) | |
− | + | If ports == 0 Then Error.Raise("Impossibile agganciare alcuna porta fisica !") | |
− | + | porta = String@(Pointer@(ports)) | |
− | + | nome_porta = jack_port_name(output_port) | |
− | + | Print nome_porta, porta | |
− | + | err = jack_connect(client, nome_porta, porta) | |
− | + | If err <> 0 Then Print "Impossibile connettere la porta d'Uscita !", err | |
− | + | Print | |
− | + | End | |
− | + | Private Procedure CreaLibjk() <FONT Color=gray>' ''Salva il codice sorgente della nostra libreria dinamica .so, e poi la crea''</font> | |
− | + | File.Save("/tmp/jk.c", "#include <string.h>\n" & | |
− | + | "#include <jack/jack.h>" & | |
− | + | "\n\n" & | |
− | + | "jack_port_t *input_port;\n" & | |
− | + | "jack_port_t *output_port;\n" & | |
− | + | "jack_client_t *client;" & | |
− | + | "\n\n" & | |
− | + | "int process (jack_nframes_t, void *);" & | |
− | + | "\n\n" & | |
− | + | "void Invoca_Callback (jack_client_t *cl, jack_port_t *it, jack_port_t *ot) {\n" & | |
− | + | " client = cl;\n" & | |
− | + | " input_port = it;\n" & | |
− | + | " output_port = ot;\n\n" & | |
− | + | " jack_set_process_callback (client, process, 0);\n}" & | |
− | + | "\n\n" & | |
− | + | "int process (jack_nframes_t nframes, void *arg) {\n" | |
− | + | " jack_default_audio_sample_t *in, *out;\n" & | |
− | + | " in = jack_port_get_buffer (input_port, nframes);\n" & | |
− | + | " out = jack_port_get_buffer (output_port, nframes);\n\n" & | |
− | + | " memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);\n\n" & | |
− | + | " return 0;\n}\n") | |
− | + | Shell "gcc -o /tmp/libjk.so /tmp/jk.c -shared -fPIC -ljack" Wait | |
− | + | End | |
− | + | Public Sub Button2_Click() | |
− | + | jack_client_close(client) | |
− | + | End | |
Riga 183: | Riga 178: | ||
===Creazione di un Client e connessione di tipo ''stereo'' al server ''jack''=== | ===Creazione di un Client e connessione di tipo ''stereo'' al server ''jack''=== | ||
Vediamo ora un possibile codice per creare un Client ed effettuare una connessione di tipo ''stereo'' al server ''jack'': | Vediamo ora un possibile codice per creare un Client ed effettuare una connessione di tipo ''stereo'' al server ''jack'': | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Private err As Integer | Private err As Integer | ||
Private client As Pointer | Private client As Pointer | ||
Riga 197: | Riga 185: | ||
Library "libjack:0.1.0" | Library "libjack:0.1.0" | ||
+ | |||
+ | Private Const JackNullOption As Byte = 0 | ||
+ | <FONT color=gray>' ''Private Const JACK_DEFAULT_MIDI_TYPE As String = "8 bit raw midi"''</font> | ||
+ | Private Const JACK_DEFAULT_AUDIO_TYPE As String = "32 bit float mono audio" | ||
+ | Private Const JackPortIsInput As Byte = 1 | ||
+ | Private Const JackPortIsOutput As Byte = 2 | ||
+ | Private Const JackPortIsPhysical As Byte = 4 | ||
<FONT color=gray>' ''jack_client_t * jack_client_open (const char *client_name, jack_options_t options, jack_status_t *status,...)'' | <FONT color=gray>' ''jack_client_t * jack_client_open (const char *client_name, jack_options_t options, jack_status_t *status,...)'' | ||
Riga 240: | Riga 235: | ||
− | + | Public Sub Form_Open() | |
<FONT color=gray>' ''Invoca la sotto-procedura per salvare in apposto file .c il codice sorgente della nostra libreria "ad hoc" e per crearla:''</font> | <FONT color=gray>' ''Invoca la sotto-procedura per salvare in apposto file .c il codice sorgente della nostra libreria "ad hoc" e per crearla:''</font> | ||
CreaLibjk() | CreaLibjk() | ||
− | + | End | |
− | + | Public Sub Button1_Click() | |
Dim nomeClient, nome_porta As String | Dim nomeClient, nome_porta As String | ||
Dim porte As Pointer | Dim porte As Pointer | ||
− | |||
Dim sample As Integer | Dim sample As Integer | ||
Dim status As Single | Dim status As Single | ||
+ | |||
+ | nomeClient = "Client_1" | ||
− | + | client = jack_client_open(nomeClient, JackNullOption, VarPtr(status), Null) | |
− | + | If client == 0 Then Error.Raise("Impossibile aprire una sessione del Client con il server Jack !") | |
− | |||
− | |||
− | + | nomeClient = jack_get_client_name(client) | |
− | + | Print "\nNome del Client = "; nomeClient | |
− | + | sample = jack_get_sample_rate(client) | |
− | + | Print "Campionamento = hz "; sample | |
− | + | Print "\n=========================================\n" | |
− | |||
− | |||
− | |||
− | + | For b As Byte = 0 To 1 | |
− | + | nome_porta = "input_" & CStr(b + 1) | |
− | + | porte_input[b] = jack_port_register(client, nome_porta, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0) | |
− | + | nome_porta = "output_" & CStr(b + 1) | |
− | + | porte_output[b] = jack_port_register(client, nome_porta, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0) | |
− | + | If (porte_input[b] == 0) Or (porte_output[b] == 0) Then Error.Raise("Nessuna porta di Jack disponibile !") | |
− | + | Next | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | Invoca_Callback(client, porte_input, porte_output) | ||
+ | err = jack_activate(client) | ||
+ | If err <> 0 Then Print "Impossibile attivare il Client !" | ||
+ | |||
<FONT Color=gray>' ''''''''''''''''''''''''''''''''''</font> | <FONT Color=gray>' ''''''''''''''''''''''''''''''''''</font> | ||
− | + | Print "Connessione delle porte\n" | |
<FONT Color=gray>' ''Connette le porte:''</font> | <FONT Color=gray>' ''Connette le porte:''</font> | ||
− | + | porte = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsOutput) | |
− | + | nome_porta = String@(Pointer@(porte)) | |
− | + | Print nome_porta, "--->", jack_port_name(porte_input[0]) | |
− | + | Print String@(Pointer@(porte + SizeOf(gb.Pointer))), "--->", jack_port_name(porte_input[1]) | |
− | + | Print | |
− | + | If porte == 0 Then | |
− | + | Print "Impossibile ottenere i nomi delle porte !" | |
− | + | Free(Object.Address(Button1)) | |
− | + | Quit | |
− | + | Endif | |
− | + | ||
− | + | For b As Byte = 0 To 1 | |
− | + | err = jack_connect(client, String@(Pointer@(porte + (CInt(b) * SizeOf(gb.Pointer)))), jack_port_name(porte_input[b])) | |
− | + | If err <> 0 Then Print "Impossibile connettere le porte !" | |
+ | Next | ||
+ | porte = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsInput) | ||
+ | nome_porta = String@(Pointer@(porte)) | ||
+ | Print jack_port_name(porte_output[0]), "--->", nome_porta, nome_porta | ||
+ | Print jack_port_name(porte_output[1]), "--->", nome_porta, String@(Pointer@(porte + SizeOf(gb.Pointer))) | ||
+ | If porte == 0 Then | ||
+ | Print "Impossibile ottenere i nomi delle porte !" | ||
+ | Free(Object.Address(Button1)) | ||
+ | Quit | ||
+ | Endif | ||
+ | For b As Byte = 0 To 1 | ||
+ | err = jack_connect(client, jack_port_name(porte_output[b]), String@(Pointer@(porte + (CInt(b) * SizeOf(gb.Pointer))))) | ||
+ | If err <> 0 Then Print "Impossibile connettere le porte !" | ||
+ | Next | ||
− | + | End | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Private Procedure CreaLibjk() <FONT Color=gray>' ''Salva il codice sorgente della nostra libreria dinamica .so, e poi la crea''</font> | |
File.Save("/tmp/jk.c", "#include <string.h>\n" & | File.Save("/tmp/jk.c", "#include <string.h>\n" & | ||
− | + | "#include <jack/jack.h>" & | |
− | + | "\n\n" & | |
− | + | "jack_port_t **input_port;\n" & | |
− | + | "jack_port_t **output_port;\n" & | |
− | + | "jack_client_t *client;" & | |
− | + | "\n\n" & | |
− | + | "int process (jack_nframes_t, void *);" & | |
− | + | "\n\n" & | |
− | + | "int process (jack_nframes_t nframes, void *arg) {\n" | |
− | + | " int i;\n" & | |
− | + | " jack_default_audio_sample_t *in, *out;\n" & | |
− | + | " for (i = 0; i < 2; i++) {\n" & | |
− | + | " in = jack_port_get_buffer (input_port[i], nframes);\n" & | |
− | + | " out = jack_port_get_buffer (output_port[i], nframes);\n\n" & | |
− | + | " memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);\n}\n\n" & | |
− | + | " return 0;\n}\n" & | |
− | + | "\n\n" & | |
− | + | "void Invoca_Callback (jack_client_t *cl, jack_port_t **it, jack_port_t **ot) {\n" & | |
− | + | " client = cl;\n" & | |
− | + | " input_port = it;\n" & | |
− | + | " output_port = ot;\n\n" & | |
− | + | " jack_set_process_callback (client, process, 0);\n}") | |
Shell "gcc -o /tmp/libjk.so /tmp/jk.c -shared -fPIC -ljack" Wait | Shell "gcc -o /tmp/libjk.so /tmp/jk.c -shared -fPIC -ljack" Wait | ||
− | + | End | |
− | + | Public Sub Button2_Click() | |
− | + | jack_client_close(client) | |
− | + | End | |
Versione delle 12:47, 6 giu 2024
JACK Audio Connection Kit è un server audio a bassa latenza sia per dati audio che per dati Midi. Jack consente di connettere svariate applicazioni client ad un dispositivo audio, ed anche con altri client. I Client di Jack possono funzionare sia come applicazioni con processi separati rispetto al server audio, sia come plugin all'interno dello stesso Jack.
Indice
Creare un semplice Client di Jack con Gambas
Per creare in Gambas un semplice Client di Jack, e connettere le sue porte con il server Jack, bisognerà servirsi delle risorse offerte dalla libreria condivisa: "libjack.so.0.1.0 ".
Ogni porta audio in Jack è un canale audio mono in formato Single, quindi a 32-bit.
V'è da precisare che Jack in tal caso prevede una chiamata ad una routine callback, ma Gambas - almeno allo stato attuale - non è in grado di funzionare in un altro thread, causando così il crash dell'applicativo. Pertanto, bisognerà far funzionare la procedura di callback all'interno di una libreria C esterna da noi appositamente creata, che chiameremo ad esempio jk.c . Il codice sorgente di tale nostra apposita libreria dinamica condivisa potrà essere inserito nel codice Gambas; lì sarà prevista anche la riga di comando con Shell per compilare la libreria.
Creazione di un Client e connessione di tipo mono al server jack
Viene creato un Client di Jack, e vengono generate connessioni audio di tipo mono.
Private err As Integer Private client As Pointer Private input_port As Pointer Private output_port As Pointer Library "libjack:0.1.0" Private Const JackNullOption As Byte = 0 ' Private Const JACK_DEFAULT_MIDI_TYPE As String = "8 bit raw midi" Private Const JACK_DEFAULT_AUDIO_TYPE As String = "32 bit float mono audio" Private Const JackPortIsInput As Byte = 1 Private Const JackPortIsOutput As Byte = 2 Private Const JackPortIsPhysical As Byte = 4 ' jack_client_t * jack_client_open (const char *client_name, jack_options_t options, jack_status_t *status,...) ' Open an external client session with a JACK server. Private Extern jack_client_open(client_name As String, options As Integer, status As Pointer, server_name As String) As Pointer ' char * jack_get_client_name (jack_client_t *client) ' Returns a pointer to actual client name. Private Extern jack_get_client_name(jack_client As Pointer) As String ' jack_nframes_t jack_get_sample_rate (jack_client_t *) ' Returns the sample rate of the jack system, as set by the user when jackd was started. Private Extern jack_get_sample_rate(jack_client As Pointer) As Integer ' jack_port_t * jack_port_register (jack_client_t *client, const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size) ' Create a new port for the client. Private Extern jack_port_register(jack_client As Pointer, port_name As String, port_type As String, flags As Integer, buffer_size As Integer) As Pointer ' int jack_activate (jack_client_t *client) ' Tell the Jack server that the program is ready to start processing audio. Private Extern jack_activate(jack_client As Pointer) As Integer ' const char ** jack_get_ports (jack_client_t *, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags) ' Returns a NULL-terminated array of ports that match the specified arguments. Private Extern jack_get_ports(jack_client As Pointer, port_name_pattern As String, type_name_pattern As String, flags As Integer) As Pointer ' const char * jack_port_name (const jack_port_t *port) ' Returns the full name of the jack_port_t (including the "client_name:" prefix). Private Extern jack_port_name(jack_port As Pointer) As String ' int jack_connect (jack_client_t *, const char *source_port, const char *destination_port) ' Establish a connection between two ports. Private Extern jack_connect(jack_client As Pointer, src_port As String, dest_port As String) As Integer ' int jack_client_close (jack_client_t *client) ' Disconnects an external client from a JACK server. Private Extern jack_client_close(jack_client As Pointer) As Integer ' void Invoca_Callback (jack_client_t *cl, jack_port_t *it, jack_port_t *ot) ' Invoca la funzione principale della libreria ad hoc per la funzione "callback" Private Extern Invoca_Callback(Pclient As Pointer, it As Pointer, ot As Pointer) As Integer In "/tmp/libjk" Public Sub Form_Open() ' Invoca la sotto-procedura per salvare in apposto file .c il codice sorgente della nostra libreria "ad hoc" e per crearla: CreaLibjk() End Public Sub Button1_Click() Dim nomeClient As String = "Client_1" Dim ports As Pointer Dim sample As Integer Dim porta, nome_porta As String Dim status As Single client = jack_client_open(nomeClient, JackNullOption, VarPtr(status), Null) If client == 0 Then Error.Raise("Impossibile aprire una sessione del Client con il server Jack !") nomeClient = jack_get_client_name(client) Print "\nNome del Client = "; nomeClient sample = jack_get_sample_rate(client) Print "Campionamento = hz "; sample Print "\n=========================================\n" input_port = jack_port_register(client, "input_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0) output_port = jack_port_register(client, "output_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0) If (input_port == 0) Or (output_port == 0) Then Error.Raise("Nessuna porta di Jack disponibile !") Invoca_Callback(client, input_port, output_port) err = jack_activate(client) If err <> 0 Then Print "Impossibile attivare il Client !" ' Connette le porte: ports = jack_get_ports(client, "system:capture_1", Null, JackPortIsPhysical Or JackPortIsOutput) If ports == 0 Then Print "Impossibile agganciare alcuna porta fisica !" Free(Object.Address(Button1)) Quit Endif porta = String@(Pointer@(ports)) nome_porta = jack_port_name(input_port) Print porta, nome_porta err = jack_connect(client, porta, nome_porta) If err <> 0 Then Print "Impossibile connettere la porta d'Entrata !" ' Connette le porte: ports = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsInput) If ports == 0 Then Error.Raise("Impossibile agganciare alcuna porta fisica !") porta = String@(Pointer@(ports)) nome_porta = jack_port_name(output_port) Print nome_porta, porta err = jack_connect(client, nome_porta, porta) If err <> 0 Then Print "Impossibile connettere la porta d'Uscita !", err Print End Private Procedure CreaLibjk() ' Salva il codice sorgente della nostra libreria dinamica .so, e poi la crea File.Save("/tmp/jk.c", "#include <string.h>\n" & "#include <jack/jack.h>" & "\n\n" & "jack_port_t *input_port;\n" & "jack_port_t *output_port;\n" & "jack_client_t *client;" & "\n\n" & "int process (jack_nframes_t, void *);" & "\n\n" & "void Invoca_Callback (jack_client_t *cl, jack_port_t *it, jack_port_t *ot) {\n" & " client = cl;\n" & " input_port = it;\n" & " output_port = ot;\n\n" & " jack_set_process_callback (client, process, 0);\n}" & "\n\n" & "int process (jack_nframes_t nframes, void *arg) {\n" " jack_default_audio_sample_t *in, *out;\n" & " in = jack_port_get_buffer (input_port, nframes);\n" & " out = jack_port_get_buffer (output_port, nframes);\n\n" & " memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);\n\n" & " return 0;\n}\n") Shell "gcc -o /tmp/libjk.so /tmp/jk.c -shared -fPIC -ljack" Wait End Public Sub Button2_Click() jack_client_close(client) End
Creazione di un Client e connessione di tipo stereo al server jack
Vediamo ora un possibile codice per creare un Client ed effettuare una connessione di tipo stereo al server jack:
Private err As Integer Private client As Pointer Private porte_input As New Pointer[2] Private porte_output As New Pointer[2] Library "libjack:0.1.0" Private Const JackNullOption As Byte = 0 ' Private Const JACK_DEFAULT_MIDI_TYPE As String = "8 bit raw midi" Private Const JACK_DEFAULT_AUDIO_TYPE As String = "32 bit float mono audio" Private Const JackPortIsInput As Byte = 1 Private Const JackPortIsOutput As Byte = 2 Private Const JackPortIsPhysical As Byte = 4 ' jack_client_t * jack_client_open (const char *client_name, jack_options_t options, jack_status_t *status,...) ' Open an external client session with a JACK server. Private Extern jack_client_open(client_name As String, options As Integer, status As Pointer, server_name As String) As Pointer ' char * jack_get_client_name (jack_client_t *client) ' Returns a pointer to actual client name. Private Extern jack_get_client_name(jack_client As Pointer) As String ' jack_nframes_t jack_get_sample_rate (jack_client_t *) ' Returns the sample rate of the jack system, as set by the user when jackd was started. Private Extern jack_get_sample_rate(jack_client As Pointer) As Integer ' jack_port_t * jack_port_register (jack_client_t *client, const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size) ' Create a new port for the client. Private Extern jack_port_register(jack_client As Pointer, port_name As String, port_type As String, flags As Integer, buffer_size As Integer) As Pointer ' int jack_activate (jack_client_t *client) ' Tell the Jack server that the program is ready to start processing audio. Private Extern jack_activate(jack_client As Pointer) As Integer ' const char ** jack_get_ports (jack_client_t *, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags) ' Returns a NULL-terminated array of ports that match the specified arguments. Private Extern jack_get_ports(jack_client As Pointer, port_name_pattern As String, type_name_pattern As String, flags As Integer) As Pointer ' const char * jack_port_name (const jack_port_t *port) ' Returns the full name of the jack_port_t (including the "client_name:" prefix). Private Extern jack_port_name(jack_port As Pointer) As String ' int jack_connect (jack_client_t *, const char *source_port, const char *destination_port) ' Establish a connection between two ports. Private Extern jack_connect(jack_client As Pointer, src_port As String, dest_port As String) As Integer ' int jack_client_close (jack_client_t *client) ' Disconnects an external client from a JACK server. Private Extern jack_client_close(jack_client As Pointer) As Integer ' void Invoca_Callback (jack_client_t *cl, jack_port_t *it, jack_port_t *ot) ' Invoca la funzione principale della libreria ad hoc per la funzione "callback" Private Extern Invoca_Callback(Pclient As Pointer, it As Pointer[], ot As Pointer[]) As Integer In "/tmp/libjk" Public Sub Form_Open() ' Invoca la sotto-procedura per salvare in apposto file .c il codice sorgente della nostra libreria "ad hoc" e per crearla: CreaLibjk() End Public Sub Button1_Click() Dim nomeClient, nome_porta As String Dim porte As Pointer Dim sample As Integer Dim status As Single nomeClient = "Client_1" client = jack_client_open(nomeClient, JackNullOption, VarPtr(status), Null) If client == 0 Then Error.Raise("Impossibile aprire una sessione del Client con il server Jack !") nomeClient = jack_get_client_name(client) Print "\nNome del Client = "; nomeClient sample = jack_get_sample_rate(client) Print "Campionamento = hz "; sample Print "\n=========================================\n" For b As Byte = 0 To 1 nome_porta = "input_" & CStr(b + 1) porte_input[b] = jack_port_register(client, nome_porta, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0) nome_porta = "output_" & CStr(b + 1) porte_output[b] = jack_port_register(client, nome_porta, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0) If (porte_input[b] == 0) Or (porte_output[b] == 0) Then Error.Raise("Nessuna porta di Jack disponibile !") Next Invoca_Callback(client, porte_input, porte_output) err = jack_activate(client) If err <> 0 Then Print "Impossibile attivare il Client !" ' ''''''''''''''''''''''''''''' Print "Connessione delle porte\n" ' Connette le porte: porte = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsOutput) nome_porta = String@(Pointer@(porte)) Print nome_porta, "--->", jack_port_name(porte_input[0]) Print String@(Pointer@(porte + SizeOf(gb.Pointer))), "--->", jack_port_name(porte_input[1]) Print If porte == 0 Then Print "Impossibile ottenere i nomi delle porte !" Free(Object.Address(Button1)) Quit Endif
For b As Byte = 0 To 1 err = jack_connect(client, String@(Pointer@(porte + (CInt(b) * SizeOf(gb.Pointer)))), jack_port_name(porte_input[b])) If err <> 0 Then Print "Impossibile connettere le porte !" Next porte = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsInput) nome_porta = String@(Pointer@(porte)) Print jack_port_name(porte_output[0]), "--->", nome_porta, nome_porta Print jack_port_name(porte_output[1]), "--->", nome_porta, String@(Pointer@(porte + SizeOf(gb.Pointer))) If porte == 0 Then Print "Impossibile ottenere i nomi delle porte !" Free(Object.Address(Button1)) Quit Endif For b As Byte = 0 To 1 err = jack_connect(client, jack_port_name(porte_output[b]), String@(Pointer@(porte + (CInt(b) * SizeOf(gb.Pointer))))) If err <> 0 Then Print "Impossibile connettere le porte !" Next End Private Procedure CreaLibjk() ' Salva il codice sorgente della nostra libreria dinamica .so, e poi la crea File.Save("/tmp/jk.c", "#include <string.h>\n" & "#include <jack/jack.h>" & "\n\n" & "jack_port_t **input_port;\n" & "jack_port_t **output_port;\n" & "jack_client_t *client;" & "\n\n" & "int process (jack_nframes_t, void *);" & "\n\n" & "int process (jack_nframes_t nframes, void *arg) {\n" " int i;\n" & " jack_default_audio_sample_t *in, *out;\n" & " for (i = 0; i < 2; i++) {\n" & " in = jack_port_get_buffer (input_port[i], nframes);\n" & " out = jack_port_get_buffer (output_port[i], nframes);\n\n" & " memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);\n}\n\n" & " return 0;\n}\n" & "\n\n" & "void Invoca_Callback (jack_client_t *cl, jack_port_t **it, jack_port_t **ot) {\n" & " client = cl;\n" & " input_port = it;\n" & " output_port = ot;\n\n" & " jack_set_process_callback (client, process, 0);\n}") Shell "gcc -o /tmp/libjk.so /tmp/jk.c -shared -fPIC -ljack" Wait End Public Sub Button2_Click() jack_client_close(client) End