Differenze tra le versioni di "Creare un semplice Client di Jack con le risorse della libreria libjack"

Da Gambas-it.org - Wikipedia.
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 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
 
 
 
  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()
+
  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'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Button1_Click()
+
  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 !")
 
   
 
   
  client = jack_client_open(nomeClient, JackNullOption, VarPtr(status), Null)
+
  nomeClient = jack_get_client_name(client)
  If IsNull(client) Then Print "Impossibile aprire una sessione del Client con  il server Jack !"
+
  Print "\nNome del Client = "; nomeClient
 
  nomeClient = jack_get_client_name(client)
 
  Print "\nNome del Client = "; nomeClient
 
 
   
 
   
  sample = jack_get_sample_rate(client)
+
  sample = jack_get_sample_rate(client)
  Print "Campionamento = hz "; sample
+
  Print "Campionamento = hz "; sample
 
      
 
      
  Print "\n=========================================\n"
+
  Print "\n=========================================\n"
+
 
+
  input_port = jack_port_register(client, "input_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)
  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)
+
  output_port = jack_port_register(client, "output_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)
  If (input_port = 0) Or (output_port = 0) Then Print "Nessuna porta di Jack disponibile !"
+
  If (input_port == 0) Or (output_port == 0) Then Error.Raise("Nessuna porta di Jack disponibile !")
 
      
 
      
  Invoca_Callback(client, input_port, output_port)
+
  Invoca_Callback(client, input_port, output_port)
 
      
 
      
  err = jack_activate(client)
+
  err = jack_activate(client)
  If err <> 0 Then Print "Impossibile attivare il 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)
+
  ports = jack_get_ports(client, "system:capture_1", Null, JackPortIsPhysical Or JackPortIsOutput)
 
      
 
      
  If ports = 0 Then
+
  If ports == 0 Then
    Print "Impossibile agganciare alcuna porta fisica !"
+
    Print "Impossibile agganciare alcuna porta fisica !"
    Free(Object.Address(Button1))
+
    Free(Object.Address(Button1))
    Quit
+
    Quit
  Endif
+
  Endif
 
      
 
      
  porta = String@(Pointer@(ports))
+
  porta = String@(Pointer@(ports))
 
      
 
      
  nome_porta = jack_port_name(input_port)
+
  nome_porta = jack_port_name(input_port)
  Print porta, nome_porta
+
  Print porta, nome_porta
 
    
 
    
  err = jack_connect(client, porta, nome_porta)
+
  err = jack_connect(client, porta, nome_porta)
+
  If err <> 0 Then Print "Impossibile connettere la porta d'Entrata !"
  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)
+
  ports = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsInput)
  If ports = 0 Then Print "Impossibile agganciare alcuna porta fisica !"
+
  If ports == 0 Then Error.Raise("Impossibile agganciare alcuna porta fisica !")
 
      
 
      
  porta = String@(Pointer@(ports))
+
  porta = String@(Pointer@(ports))
 
      
 
      
  nome_porta = jack_port_name(output_port)
+
  nome_porta = jack_port_name(output_port)
  Print nome_porta, porta
+
  Print nome_porta, porta
 
      
 
      
  err = jack_connect(client, nome_porta, porta)
+
  err = jack_connect(client, nome_porta, porta)
  If err <> 0 Then Print "Impossibile connettere la porta d'Uscita !", err
+
  If err <> 0 Then Print "Impossibile connettere la porta d'Uscita !", err
 
    
 
    
  Print
+
  Print
 
   
 
   
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Private''' Procedure CreaLibjk()  <FONT Color=gray>' ''Salva il codice sorgente della nostra libreria dinamica .so, e poi la crea''</font>
+
  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>" &
+
          "#include <jack/jack.h>" &
            "\n\n" &
+
          "\n\n" &
            "jack_port_t *input_port;\n" &
+
          "jack_port_t *input_port;\n" &
            "jack_port_t  *output_port;\n" &
+
          "jack_port_t  *output_port;\n" &
            "jack_client_t *client;" &
+
          "jack_client_t *client;" &
            "\n\n" &
+
          "\n\n" &
            "int process (jack_nframes_t, void *);" &
+
          "int process (jack_nframes_t, void *);" &
            "\n\n" &
+
          "\n\n" &
          "void Invoca_Callback (jack_client_t *cl, jack_port_t *it, jack_port_t *ot) {\n" &
+
          "void Invoca_Callback (jack_client_t *cl, jack_port_t *it, jack_port_t *ot) {\n" &
            "  client = cl;\n" &
+
          "  client = cl;\n" &
            "  input_port = it;\n" &
+
          "  input_port = it;\n" &
            "  output_port = ot;\n\n" &
+
          "  output_port = ot;\n\n" &
            "  jack_set_process_callback (client, process, 0);\n}" &
+
          "  jack_set_process_callback (client, process, 0);\n}" &
            "\n\n" &
+
          "\n\n" &
          "int process (jack_nframes_t nframes, void *arg) {\n"
+
          "int process (jack_nframes_t nframes, void *arg) {\n"
            "  jack_default_audio_sample_t *in, *out;\n" &
+
          "  jack_default_audio_sample_t *in, *out;\n" &
            "  in = jack_port_get_buffer (input_port, nframes);\n" &
+
          "  in = jack_port_get_buffer (input_port, nframes);\n" &
            "  out = jack_port_get_buffer (output_port, nframes);\n\n" &
+
          "  out = jack_port_get_buffer (output_port, nframes);\n\n" &
            "  memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);\n\n" &
+
          "  memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);\n\n" &
            "  return 0;\n}\n")
+
          "  return 0;\n}\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'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Button2_Click()
+
  Public Sub Button2_Click()
 
   
 
   
  jack_client_close(client)
+
  jack_client_close(client)
 
   
 
   
  '''End'''
+
  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 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
 
 
 
  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()
+
  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'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Button1_Click()
+
  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 b As Byte
 
 
   Dim sample As Integer
 
   Dim sample As Integer
 
   Dim status As Single
 
   Dim status As Single
 +
 +
  nomeClient = "Client_1"
 
    
 
    
  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 !")
  client = jack_client_open(nomeClient, JackNullOption, VarPtr(status), Null)
 
  If IsNull(client) Then Print "Impossibile aprire una sessione del Client con  il server Jack !"
 
 
   
 
   
  nomeClient = jack_get_client_name(client)
+
  nomeClient = jack_get_client_name(client)
  Print "\nNome del Client = "; nomeClient
+
  Print "\nNome del Client = "; nomeClient
 
   
 
   
  sample = jack_get_sample_rate(client)
+
  sample = jack_get_sample_rate(client)
  Print "Campionamento = hz "; sample
+
  Print "Campionamento = hz "; sample
 
      
 
      
  Print "\n=========================================\n"
+
  Print "\n=========================================\n"
 
 
  For b = 0 To 1
 
 
    
 
    
    nome_porta = "input_" & CStr(b + 1)
+
  For b As Byte = 0 To 1
    porte_input[b] = jack_port_register(client, nome_porta, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)
+
    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)
+
    nome_porta = "output_" & CStr(b + 1)
    porte_output[b] = jack_port_register(client, nome_porta, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)
+
    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 !")
    If (porte_input[b] = 0) Or (porte_output[b] = 0) Then Print "Nessuna porta di Jack disponibile !"
+
  Next
   
 
  Next
 
 
 
  Invoca_Callback(client, porte_input, porte_output)
 
 
 
  err = jack_activate(client)
 
  If err <> 0 Then Print "Impossibile attivare il Client !"
 
 
    
 
    
 +
  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"
+
  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)
+
  porte = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsOutput)
  nome_porta = String@(Pointer@(porte))
+
  nome_porta = String@(Pointer@(porte))
  Print nome_porta, "--->", jack_port_name(porte_input[0])
+
  Print nome_porta, "--->", jack_port_name(porte_input[0])
  Print String@(Pointer@(porte + SizeOf(gb.Pointer))), "--->", jack_port_name(porte_input[1])
+
  Print String@(Pointer@(porte + SizeOf(gb.Pointer))), "--->", jack_port_name(porte_input[1])
  Print
+
  Print
  If porte = 0 Then
+
  If porte == 0 Then
    Print "Impossibile ottenere i nomi delle porte !"
+
    Print "Impossibile ottenere i nomi delle porte !"
    Free(Object.Address(Button1))
+
    Free(Object.Address(Button1))
    Quit
+
    Quit
  Endif
+
  Endif
  For b = 0 To 1
+
 
    err = jack_connect(client, String@(Pointer@(porte + (CInt(b) * SizeOf(gb.Pointer)))), jack_port_name(porte_input[b]))
+
  For b As Byte = 0 To 1
    If err <> 0 Then Print "Impossibile connettere le porte !"
+
    err = jack_connect(client, String@(Pointer@(porte + (CInt(b) * SizeOf(gb.Pointer)))), jack_port_name(porte_input[b]))
  Next
+
    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
 
    
 
    
  porte = jack_get_ports(client, Null, Null, JackPortIsPhysical Or JackPortIsInput)
+
  End
  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 = 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>
+
  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>" &
+
            "#include <jack/jack.h>" &
          "\n\n" &
+
            "\n\n" &
          "jack_port_t **input_port;\n" &
+
            "jack_port_t **input_port;\n" &
          "jack_port_t **output_port;\n" &
+
            "jack_port_t **output_port;\n" &
          "jack_client_t *client;" &
+
            "jack_client_t *client;" &
          "\n\n" &
+
            "\n\n" &
          "int process (jack_nframes_t, void *);" &
+
            "int process (jack_nframes_t, void *);" &
          "\n\n" &
+
            "\n\n" &
        "int process (jack_nframes_t nframes, void *arg) {\n"
+
            "int process (jack_nframes_t nframes, void *arg) {\n"
          "  int i;\n" &
+
            "  int i;\n" &
          "  jack_default_audio_sample_t *in, *out;\n" &
+
            "  jack_default_audio_sample_t *in, *out;\n" &
          "  for (i = 0; i < 2; i++) {\n" &
+
            "  for (i = 0; i < 2; i++) {\n" &
          "  in = jack_port_get_buffer (input_port[i], nframes);\n" &
+
            "  in = jack_port_get_buffer (input_port[i], nframes);\n" &
          "  out = jack_port_get_buffer (output_port[i], nframes);\n\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" &
+
            "  memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);\n}\n\n" &
          "  return 0;\n}\n" &
+
            "  return 0;\n}\n" &
          "\n\n" &
+
            "\n\n" &
        "void Invoca_Callback (jack_client_t *cl, jack_port_t **it, jack_port_t **ot) {\n" &
+
            "void Invoca_Callback (jack_client_t *cl, jack_port_t **it, jack_port_t **ot) {\n" &
          "  client = cl;\n" &
+
            "  client = cl;\n" &
          "  input_port = it;\n" &
+
            "  input_port = it;\n" &
          "  output_port = ot;\n\n" &
+
            "  output_port = ot;\n\n" &
          "  jack_set_process_callback (client, process, 0);\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'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Button2_Click()
+
  Public Sub Button2_Click()
 
   
 
   
  jack_client_close(client)
+
  jack_client_close(client)
 
   
 
   
  '''End'''
+
  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.


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


Riferimenti