Differenze tra le versioni di "Alsa e Gambas: Un programma con due Client e due porte diverse"

Da Gambas-it.org - Wikipedia.
Riga 32: Riga 32:
 
  Private Extern snd_seq_alloc_named_queue(seq As Pointer, name As String) As Integer
 
  Private Extern snd_seq_alloc_named_queue(seq As Pointer, name As String) As Integer
 
   
 
   
  <FONT color=#006400>' '''''creazione del primo Client con porta avente capacità di "lettura":'''''</font>
+
 +
  <FONT color=gray>' '''''creazione del primo Client con porta avente capacità di "lettura":'''''</font>
 
  '''Public''' Sub alsa_open1()
 
  '''Public''' Sub alsa_open1()
 
   
 
   
 
   Dim err As Integer
 
   Dim err As Integer
 
   
 
   
  err = snd_seq_open(VarPtr(handle1), "default", SND_SEQ_OPEN_OUTPUT, 0)
+
  err = snd_seq_open(VarPtr(handle1), "default", SND_SEQ_OPEN_OUTPUT, 0)
  Select Case err
+
  Select Case err
    Case 0 To 255
+
    Case 0 To 255
      Print "Apertura di Alsa per il Client-1: regolare"
+
      Print "Apertura di Alsa per il Client-1: regolare"
    Case Else
+
    Case Else
       printerr("Apertura di Alsa: ", err)
+
       Error.Raise("Errore nell'apertura di Alsa !")
      error.RAISE("Error opening alsa")
+
  End Select
  End Select
 
 
   
 
   
  snd_seq_set_client_name(handle1, "cliente 1")
+
  snd_seq_set_client_name(handle1, "cliente 1")
 
   
 
   
  id1 = snd_seq_client_id(handle1)
+
  id1 = snd_seq_client_id(handle1)
  Print "ID Client 1 di Alsa = "; id1
+
  Print "ID Client 1 di Alsa = "; id1
 
    
 
    
  err = snd_seq_create_simple_port(handle1, "Seq-Out", SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION)
+
  err = snd_seq_create_simple_port(handle1, "Seq-Out", SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION)
  Print "Porta di Uscita del Client-1  = "; err
+
  Print "Porta di Uscita del Client-1  = "; err
  If err < 0 Then error.Raise("Error creating output port")
+
  If err < 0 Then error.Raise("Errore nella creazione della porta di Uscita del Client !")
  outport = err
+
  outport = err
 
    
 
    
  err = snd_seq_alloc_named_queue(handle1, "outqueue")
+
  outq = snd_seq_alloc_named_queue(handle1, "outqueue")
  printerr("Creazione della coda: ", err)
+
  If outq < 0 Then error.Raise("Errore nella crazione di una code degli eventi in Uscita !")
  If err < 0 Then error.Raise("Error creating out queue")
+
    
   outq = err
 
 
 
  '''End'''
 
  '''End'''
 
   
 
   
 
   
 
   
  <FONT color=#006400>' '''''creazione del secondo Client con porta avente capacità di "scrittura":'''''</font>
+
  <FONT color=gray>' '''''creazione del secondo Client con porta avente capacità di "scrittura":'''''</font>
 
  '''Public''' Sub alsa_open2()
 
  '''Public''' Sub alsa_open2()
 
   
 
   
 
   Dim err As Integer
 
   Dim err As Integer
 
   
 
   
  err = snd_seq_open(VarPtr(handle2), "default", SND_SEQ_OPEN_INPUT, 0)
+
  err = snd_seq_open(VarPtr(handle2), "default", SND_SEQ_OPEN_INPUT, 0)
  Select Case err
+
  Select Case err
    Case 0 To 255
+
    Case 0 To 255
      Print "Apertura di Alsa per il Client-2: regolare"
+
      Print "Apertura di Alsa per il Client-2: regolare"
    Case Else
+
    Case Else
       printerr("Apertura di Alsa: ", err)
+
       Error.Raise("Errore nell'apertura di Alsa")
      error.RAISE("Error opening alsa")
+
  End Select
  End Select
 
 
    
 
    
  snd_seq_set_client_name(handle2, "cliente-2")
+
  snd_seq_set_client_name(handle2, "cliente-2")
 
   
 
   
  id2 = snd_seq_client_id(handle2)
+
  id2 = snd_seq_client_id(handle2)
  Print "ID Client 2 di Alsa = "; id2
+
  Print "ID Client 2 di Alsa = "; id2
 
      
 
      
  err = snd_seq_create_simple_port(handle2, "Seq-In", SND_SEQ_PORT_CAP_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION)
+
  err = snd_seq_create_simple_port(handle2, "Seq-In", SND_SEQ_PORT_CAP_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION)
  Print "Porta di Entrata del Client 2 = "; err
+
  Print "Porta di Entrata del Client 2 = "; err
  If err < 0 Then error.Raise("Error creating alsa port")
+
  If err < 0 Then error.Raise("Errore nella creazione della portadi Entrata del Client !")
  inport = err
+
  inport = err
 +
 
  '''End'''
 
  '''End'''
 
Quindi riportiamo il codice relativo alla parte della connessione:
 
Quindi riportiamo il codice relativo alla parte della connessione:
Riga 93: Riga 91:
 
   
 
   
 
  '''Public''' Sub setdevice(client As Integer, port As Integer)
 
  '''Public''' Sub setdevice(client As Integer, port As Integer)
 +
 
 
   Dim err As Integer
 
   Dim err As Integer
 
    
 
    
  dclient = client
+
  err = snd_seq_connect_to(handle1, outport, 14, port)
  dport = port
+
  If err < 0 Then error.Raise("Errore nella sottoscrizione del dispositivo !")
  err = snd_seq_connect_to(handle1, outport, 14, dport)
 
  printerr("Subscribe outport", err)
 
 
   
 
   
  err = snd_seq_connect_from(handle2, inport, 14, 0)
+
  err = snd_seq_connect_from(handle2, inport, 14, 0)
  printerr("Subscribe inport", err)
+
  If err < 0 Then error.Raise("Errore nella sottoscrizione del dispositivo !")
 
+
  <FONT color=#006400>' ''Se ci si vuole connettere contemporaneamente ad un secondo dispositivo,''
+
  <FONT color=gray>' ''Se ci si vuole connettere contemporaneamente ad un secondo dispositivo,''
 
  ' ''ad esempio ad una tastiera Midi esterna:''</font>
 
  ' ''ad esempio ad una tastiera Midi esterna:''</font>
  err = snd_seq_connect_from(handle2, inport, 24, 0)
+
  err = snd_seq_connect_from(handle2, inport, 24, 0)
  printerr("Subscribe inport", err)
+
  If err < 0 Then error.Raise("Errore nella sottoscrizione del dispositivo !")
 
   
 
   
  If err < 0 Then error.Raise("Errore nella sottoscrizione del dispositivo !")
 
 
  '''End'''
 
  '''End'''

Versione delle 17:29, 9 giu 2014

E' possibile effettuare diversi accessi da un unico programma ad Alsa, poiché questo sistema lo consente.
I vantaggi di avere in un unico programma la creazione e la gestione di due Client indipendenti aventi ciascuna una propria porta indipendente dovrebbero essere i seguenti:

  • Il pool evento nel kernel è indipendente tra i client. Così, anche se il pool del client 1 è pieno, è possibile utilizzare il Client 2;
  • Possono essere impostati in ciascun Client diversi permessi, incrementando la stabilità e la sicurezza.


Con l'apertura di due Client sarà possibile con il primo gestire i normali eventi in Uscita, e con il secondo gestire i controlli (Start, Stop, Continue, Cambio del Tempo Metronomico, etc) sulla coda degli eventi.


Codice esemplificativo

Poniamo l'esempio di voler creare due Client all'interno di un programma, aventi rispettivamente una porta con capacità di lettura, ed una porta con capacità di scrittura. Procederemo innanzitutto ad effettuare una duplice chiamata di aprtura del sistema Alsa. A ciascun Client assegneremo un nome diverso e variabili diverse (qui a mero fine esplicativo mostreremo le parti essenziali del codice):

Private handle1 As Pointer
Private handle2 As Pointer
Private id1 As Integer
Private id2 As Integer
Private inport As Integer
Private outq As Integer


Library "libasound:2"

Private Const SND_SEQ_OPEN_OUTPUT As Integer = 1
Private Const SND_SEQ_OPEN_INPUT As Integer = 2
Private Const SND_SEQ_PORT_CAP_READ As Integer = 1
Private Const SND_SEQ_PORT_CAP_WRITE As Integer = 2
Private Const SND_SEQ_PORT_TYPE_MIDI_GENERIC As Integer = 2
Private Const SND_SEQ_PORT_TYPE_APPLICATION As Integer = 1048576


Private Extern snd_seq_open(Pseq As Pointer, name As String, streams As Integer, mode As Integer) As Integer
Private Extern snd_seq_set_client_name(seq As Pointer, name As String) As Integer
Private Extern snd_seq_client_id(seq As Pointer) As Integer
Private Extern snd_seq_create_simple_port(seq As Pointer, par1 As String, par2 As Integer, par3 As Integer) As Integer
Private Extern snd_seq_alloc_named_queue(seq As Pointer, name As String) As Integer


' creazione del primo Client con porta avente capacità di "lettura":
Public Sub alsa_open1()

 Dim err As Integer

  err = snd_seq_open(VarPtr(handle1), "default", SND_SEQ_OPEN_OUTPUT, 0)
  Select Case err
    Case 0 To 255
      Print "Apertura di Alsa per il Client-1: regolare"
    Case Else
      Error.Raise("Errore nell'apertura di Alsa !")
  End Select

  snd_seq_set_client_name(handle1, "cliente 1")

  id1 = snd_seq_client_id(handle1)
  Print "ID Client 1 di Alsa = "; id1
 
  err = snd_seq_create_simple_port(handle1, "Seq-Out", SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION)
  Print "Porta di Uscita del Client-1  = "; err
  If err < 0 Then error.Raise("Errore nella creazione della porta di Uscita del Client !")
  outport = err
  
  outq = snd_seq_alloc_named_queue(handle1, "outqueue")
  If outq < 0 Then error.Raise("Errore nella crazione di una code degli eventi in Uscita !")
 
End


' creazione del secondo Client con porta avente capacità di "scrittura":
Public Sub alsa_open2()

 Dim err As Integer

  err = snd_seq_open(VarPtr(handle2), "default", SND_SEQ_OPEN_INPUT, 0)
  Select Case err
    Case 0 To 255
      Print "Apertura di Alsa per il Client-2: regolare"
    Case Else
      Error.Raise("Errore nell'apertura di Alsa")
  End Select
  
  snd_seq_set_client_name(handle2, "cliente-2")

  id2 = snd_seq_client_id(handle2)
  Print "ID Client 2 di Alsa = "; id2
   
  err = snd_seq_create_simple_port(handle2, "Seq-In", SND_SEQ_PORT_CAP_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION)
  Print "Porta di Entrata del Client 2 = "; err
  If err < 0 Then error.Raise("Errore nella creazione della portadi Entrata del Client !")
  inport = err

End

Quindi riportiamo il codice relativo alla parte della connessione:

Private Extern snd_seq_connect_from(seq As Pointer, myport As Integer, src_client As Integer, src_port As Integer) As Integer
Private Extern snd_seq_connect_to(seq As Pointer, myport As Integer, src_client As Integer, src_port As Integer) As Integer

Public Sub setdevice(client As Integer, port As Integer)
 
 Dim err As Integer
 
  err = snd_seq_connect_to(handle1, outport, 14, port)
  If err < 0 Then error.Raise("Errore nella sottoscrizione del dispositivo !")

  err = snd_seq_connect_from(handle2, inport, 14, 0)
  If err < 0 Then error.Raise("Errore nella sottoscrizione del dispositivo !")

' Se ci si vuole connettere contemporaneamente ad un secondo dispositivo,
' ad esempio ad una tastiera Midi esterna:
  err = snd_seq_connect_from(handle2, inport, 24, 0)
  If err < 0 Then error.Raise("Errore nella sottoscrizione del dispositivo !")

End