Differenze tra le versioni di "Alsa e Gambas: Invio dati con l'uso di una Classe specifica"

Da Gambas-it.org - Wikipedia.
Riga 16: Riga 16:
 
  Property Tick_o_Tv_sec As Integer
 
  Property Tick_o_Tv_sec As Integer
 
  Property Tv_nsec As Integer
 
  Property Tv_nsec As Integer
  Property Sourceclient As Byte
+
  Property Source_client As Byte
  Property Sourceport As Byte
+
  Property Source_port As Byte
  Property Destclient As Byte
+
  Property Dest_client As Byte
  Property Destport As Byte
+
  Property Dest_port As Byte
 
  Property Channel As Byte
 
  Property Channel As Byte
 
  Property Note As Byte
 
  Property Note As Byte
Riga 34: Riga 34:
 
  Private $Tick_o_Tv_sec As Integer
 
  Private $Tick_o_Tv_sec As Integer
 
  Private $Tv_nsec As Integer
 
  Private $Tv_nsec As Integer
  Private $Sourceclient As Byte
+
  Private $Source_client As Byte
  Private $Sourceport As Byte
+
  Private $Source_port As Byte
  Private $destclient As Byte
+
  Private $Dest_client As Byte
  Private $Destport As Byte
+
  Private $Dest_port As Byte
 
  Private $Channel As Byte
 
  Private $Channel As Byte
 
  Private $Note As Byte
 
  Private $Note As Byte
Riga 77: Riga 77:
 
  End
 
  End
 
   
 
   
  Private Function Tick_o_Tv_Read() As Integer
+
  Private Function Tick_o_Tv_sec_Read() As Integer
   Return $Tick_o_Tv
+
   Return $Tick_o_Tv_sec
 
  End
 
  End
 
   
 
   
  Private Sub Tick_o_Tv_Write(Value As Integer)
+
  Private Sub Tick_o_Tv_sec_Write(Value As Integer)
   $Ticktime = Value
+
   $Tick_o_Tv_sec = Value
 
  End
 
  End
 
   
 
   
Riga 93: Riga 93:
 
  End
 
  End
 
   
 
   
  Private Function Sourceclient_Read() As Byte
+
  Private Function Source_client_Read() As Byte
   Return $Sourceclient
+
   Return $Source_client
 
  End
 
  End
 
   
 
   
  Private Sub Sourceclient_Write(Value As Byte)
+
  Private Sub Source_client_Write(Value As Byte)
   $Sourceclient = Value
+
   $Source_client = Value
 
  End
 
  End
 
   
 
   
  Private Function Sourceport_Read() As Byte
+
  Private Function Source_port_Read() As Byte
   Return $Sourceport
+
   Return $Source_port
 
  End
 
  End
 
   
 
   
  Private Sub Sourceport_Write(Value As Byte)
+
  Private Sub Source_port_Write(Value As Byte)
   $Sourceport = Value
+
   $Source_port = Value
 
  End
 
  End
 
   
 
   
  Private Function Destclient_Read() As Byte
+
  Private Function Dest_client_Read() As Byte
   Return $Destclient
+
   Return $Dest_client
 
  End
 
  End
 
   
 
   
  Private Sub Destclient_Write(Value As Byte)
+
  Private Sub Dest_client_Write(Value As Byte)
   $Destclient = Value
+
   $Dest_client = Value
 
  End
 
  End
 
   
 
   
  Private Function Destport_Read() As Byte
+
  Private Function Dest_port_Read() As Byte
   Return $Destport
+
   Return $Dest_port
 
  End
 
  End
 
   
 
   
  Private Sub Destport_Write(Value As Byte)
+
  Private Sub Dest_port_Write(Value As Byte)
   $Destport = Value
+
   $Dest_port = Value
 
  End
 
  End
 
   
 
   
Riga 161: Riga 161:
 
  End
 
  End
 
   
 
   
  Private Sub param_Write(Value As Integer)
+
  Private Sub Param_Write(Value As Integer)
 
   $Param = Value
 
   $Param = Value
 
  End
 
  End
Riga 194: Riga 194:
 
====Esempio di codice====
 
====Esempio di codice====
 
Mostriamo ora il codice che sarà inserito nel Modulo di avvio principale, dal quale si richiamerà la Classe specifica per la gestione degli Eventi Midi di ALSA, che qui sarà chiamata ''EventoMidiAlsa'':
 
Mostriamo ora il codice che sarà inserito nel Modulo di avvio principale, dal quale si richiamerà la Classe specifica per la gestione degli Eventi Midi di ALSA, che qui sarà chiamata ''EventoMidiAlsa'':
Public ev_midi As EventoMidiAlsa    <FONT color=gray>' ''Dichiara la variabile del tipo della Classe "EventoMidiAlsa"''</font>
 
 
 
  Library "libasound:2"
 
  Library "libasound:2"
 
   
 
   
Riga 251: Riga 249:
 
   Dim handle As Pointer
 
   Dim handle As Pointer
 
   Dim err, id, porta, que As Integer
 
   Dim err, id, porta, que As Integer
 +
  Dim ev_midi As EventoMidiAlsa    <FONT color=gray>' ''Dichiara la variabile del tipo della Classe "EventoMidiAlsa"''</font>
 
   
 
   
 
  <FONT Color=gray>' ''Crea un'istanza della Classe specifica "EventoMidiAlsa", con la quale saranno richiamate e gestite le Proprietà della Classe:''</font>
 
  <FONT Color=gray>' ''Crea un'istanza della Classe specifica "EventoMidiAlsa", con la quale saranno richiamate e gestite le Proprietà della Classe:''</font>
Riga 280: Riga 279:
 
     .Tag = 0
 
     .Tag = 0
 
     .Queue = que
 
     .Queue = que
     .tick_o_tv_sec = 0
+
     .Tick_o_Tv_sec = 0
     .tv_nsec = 0
+
     .Tv_nsec = 0
     .Sourceclient = id
+
     .Source_client = id
     .Sourceport = porta
+
     .Source_port = porta
     .Destclient = SND_SEQ_ADDRESS_SUBSCRIBERS
+
     .Dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS
     .Destport = SND_SEQ_ADDRESS_UNKNOWN
+
     .Dest_port = SND_SEQ_ADDRESS_UNKNOWN
 
     .Channel = 0
 
     .Channel = 0
     .value = 44      <FONT Color=gray>' ''Imposta il suono dello strumento musicale da usare''</font>
+
     .Value = 44      <FONT Color=gray>' ''Imposta il suono dello strumento musicale da usare''</font>
 
   End With
 
   End With
 
   
 
   
Riga 298: Riga 297:
 
     .Tag = 0
 
     .Tag = 0
 
     .Queue = que
 
     .Queue = que
     .tick_o_tv_sec = 0
+
     .Tick_o_Tv_sec = 0
     .tv_nsec = 0
+
     .Tv_nsec = 0
     .Sourceclient = id
+
     .Source_client = id
     .Sourceport = porta
+
     .Source_port = porta
     .Destclient = SND_SEQ_ADDRESS_SUBSCRIBERS
+
     .Dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS
     .Destport = SND_SEQ_ADDRESS_UNKNOWN
+
     .Dest_port = SND_SEQ_ADDRESS_UNKNOWN
 
     .Channel = 0
 
     .Channel = 0
 
     .Note = 64        <FONT Color=gray>' ''Imposta una nota Midi da eseguire''</font>
 
     .Note = 64        <FONT Color=gray>' ''Imposta una nota Midi da eseguire''</font>
Riga 320: Riga 319:
 
     .Tag = 0
 
     .Tag = 0
 
     .Queue = que
 
     .Queue = que
     .tick_o_tv_sec = 0
+
     .Tick_o_Tv_sec = 0
     .tv_nsec = 0
+
     .Tv_nsec = 0
     .Sourceclient = id
+
     .Source_client = id
     .Sourceport = porta
+
     .Source_port = porta
     .Destclient = SND_SEQ_ADDRESS_SUBSCRIBERS
+
     .Dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS
     .Destport = SND_SEQ_ADDRESS_UNKNOWN
+
     .Dest_port = SND_SEQ_ADDRESS_UNKNOWN
 
     .Channel = 0
 
     .Channel = 0
 
     .Note = 64        <FONT Color=gray>' ''Imposta una nota Midi da eseguire''</font>
 
     .Note = 64        <FONT Color=gray>' ''Imposta una nota Midi da eseguire''</font>

Versione delle 19:34, 21 gen 2022

Introduzione

Per definire e gestire gli Eventi Midi di ALSA si può usare una Classe specifica, fornita di Proprietà in "lettura" e in "scrittura" che potranno essere usate per memorizzare i valori necessari dell'Evento Midi, secondo la Struttura snd_seq_event_t prevista dal protocollo di ALSA.
Dichiarando poi una variabile del tipo di quella Classe per ciascun Evento Midi ALSA, si avrà un'area di memoria utilizzabile.
L'uso di tale Classe specifica sostituisce egregiamente e più dinamicamente la Struttura. [nota 1]


Scrittura dei dati dei messaggi Midi nella Classe specifica dei dati Midi

Impostando e usando le Proprietà della Classe specifica

La Classe modello specifica va creata con tutte le Proprietà necessarie per la definizione di qualunque Evento Midi di ALSA, sarà così organizzata:

' Definisce le Proprietà della Classe specifica:
Property Type As Byte
Property Flags As Byte
Property Tag As Byte
Property Queue As Byte
Property Tick_o_Tv_sec As Integer
Property Tv_nsec As Integer
Property Source_client As Byte
Property Source_port As Byte
Property Dest_client As Byte
Property Dest_port As Byte
Property Channel As Byte
Property Note As Byte
Property Velocity As Byte
Property Off_velocity As Byte
Property Param As Integer
Property Value As Integer

' Definisce i simboli associati alle suddette Proprietà:
Private $Type As Byte
Private $Flags As Byte
Private $Tag As Byte
Private $Queue As Byte
Private $Tick_o_Tv_sec As Integer
Private $Tv_nsec As Integer
Private $Source_client As Byte
Private $Source_port As Byte
Private $Dest_client As Byte
Private $Dest_port As Byte
Private $Channel As Byte
Private $Note As Byte
Private $Velocity As Byte
Private $Off_velocity As Byte
Private $Param As Integer
Private $Value As Integer

Private Function Type_Read() As Byte
  Return $Type
End

Private Sub Type_Write(Value As Byte)
  $Type = Value
End

Private Function Flags_Read() As Byte
  Return $Flags
End

Private Sub Flags_Write(Value As Byte)
  $Flags = Value
End

Private Function Tag_Read() As Byte
  Return $Tag
End

Private Sub Tag_Write(Value As Byte)
  $Tag = Value
End

Private Function Queue_Read() As Byte
  Return $Queue
End

Private Sub Queue_Write(Value As Byte)
  $Queue = Value
End

Private Function Tick_o_Tv_sec_Read() As Integer
  Return $Tick_o_Tv_sec
End

Private Sub Tick_o_Tv_sec_Write(Value As Integer)
  $Tick_o_Tv_sec = Value
End

Private Function Tv_nsec_Read() As Integer
  Return $Tv_nsec
End

Private Sub Tv_nsec_Write(Value As Integer)
  $Tv_nsec = Value
End

Private Function Source_client_Read() As Byte
  Return $Source_client
End

Private Sub Source_client_Write(Value As Byte)
  $Source_client = Value
End

Private Function Source_port_Read() As Byte
  Return $Source_port
End

Private Sub Source_port_Write(Value As Byte)
  $Source_port = Value
End

Private Function Dest_client_Read() As Byte
  Return $Dest_client
End

Private Sub Dest_client_Write(Value As Byte)
  $Dest_client = Value
End

Private Function Dest_port_Read() As Byte
  Return $Dest_port
End

Private Sub Dest_port_Write(Value As Byte)
  $Dest_port = Value
End

Private Function Channel_Read() As Byte
  Return $Channel
End

Private Sub Channel_Write(Value As Byte)
  $Channel = Value
End

Private Function Note_Read() As Byte
  Return $Note
End

Private Sub Note_Write(Value As Byte)
  $Note = Value
End

Private Function Velocity_Read() As Byte
  Return $Velocity
End

Private Sub Velocity_Write(Value As Byte)
  $Velocity = Value
End

Private Function Off_velocity_Read() As Byte
  Return $Off_velocity
End

Private Sub Off_velocity_Write(Value As Byte)
  $Off_velocity = Value
End

Private Function Param_Read() As Integer
  Return $Param
End

Private Sub Param_Write(Value As Integer)
  $Param = Value
End

Private Function Value_Read() As Integer
  Return $Value
End

Private Sub Value_Write(Value As Integer)
  $Value = Value
End


I messaggi Midi specifici

Scrivendo il codice Gambas, si dovrà ricordare che nella dichiarazione con Extern della funzione esterna di ALSA "snd_seq_event_output()" bisognerà inserire come secondo parametro il nome identificativo della predetta Classe modello per la creazione degli Eventi Midi di ALSA:

Private Extern snd_seq_event_output(handle As Pointer, variabile As Classe_Eventi_Midi) As Integer

mentre all'interno delle routine, quando essa viene chiamata ed effettivamente utilizzata, va inserito ovviamente il nome della sua variabile istanziata.

Gruppo messaggi: NoteON - NoteOFF - Polyphonic Aftertouch

Questi tre messaggi Midi hanno tra loro in comune tre Proprietà della Classe specifica modello: ".Channel", ".Note" e ".Velocity"
Dunque per questi tre tipi di Messaggi Midi si valorizzeranno le suddette Proprietà della Classe specifica.

Ovviamente le prime sette Proprietà sono comuni a tutti Messaggi Midi.

Gruppo messaggi: Program Change - Channel Aftertouch (Key Pressure)

Questi due messaggi Midi hanno tra loro in comune due Proprietà: ".Channel" e ".Value".

Gruppo messaggi: Control Change - Pitch Bend (Pitch Wheel)

Questi due messaggi Midi hanno tra loro in comune tre Proprietà della Classe specifica, che abbiamo chiamato: ".Channel", ".Param" e ".Value".


Esempio di codice

Mostriamo ora il codice che sarà inserito nel Modulo di avvio principale, dal quale si richiamerà la Classe specifica per la gestione degli Eventi Midi di ALSA, che qui sarà chiamata EventoMidiAlsa:

Library "libasound:2"

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_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

' 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_event_output (snd_seq_t * seq, snd_seq_event_t *ev)
' Output an event.
Private Extern snd_seq_event_output(seq As Pointer, ev As EventoMidiAlsa) As Integer

' int snd_seq_drain_output (snd_seq_t * seq)
' Drain output buffer to sequencer.
Private Extern snd_seq_drain_output(seq As Pointer) As Integer

' const char * snd_strerror (int errnum)
' Returns the message for an error code.
Private Extern snd_strerror(errnum As Integer) As String

' int snd_seq_close (snd_seq_t * seq)
' Close the sequencer.
Private Extern snd_seq_close(seq As Pointer) As Integer


Public Sub Main()

 Dim handle As Pointer
 Dim err, id, porta, que As Integer
 Dim ev_midi As EventoMidiAlsa    ' Dichiara la variabile del tipo della Classe "EventoMidiAlsa"

' Crea un'istanza della Classe specifica "EventoMidiAlsa", con la quale saranno richiamate e gestite le Proprietà della Classe:
 ev_midi = New EventoMidiAlsa

 err = snd_seq_open(VarPtr(handle), "default", SND_SEQ_OPEN_DUPLEX, 0)
 Print "Apertura del subsistema 'seq' di ALSA = "; err
 If err < 0 Then error.RAISE("Errore: " & snd_strerror(err))

 snd_seq_set_client_name(handle, "Test")
 id = snd_seq_client_id(handle)
 Print "Alsa ClientID = "; id

 porta = snd_seq_create_simple_port(handle, "Uscita", 0, SND_SEQ_PORT_TYPE_MIDI_GENERIC + SND_SEQ_PORT_TYPE_APPLICATION) 
 Print "Porta del programma = "; porta
 If porta < 0 Then error.Raise("Errore: " & snd_strerror(porta))

 que = snd_seq_alloc_queue(handle, "queue")
 If que < 0 Then error.Raise("Errore: " & snd_strerror(que))

' Assume che l'ID/porta dell'altro Client (Softsynth) sia 128:0
 err = snd_seq_connect_to(handle, porta, 128, 0)
 If err < 0 Then error.Raise("Errore: " & snd_strerror(err))

' Program Change
 With ev_midi
   .Type = SND_SEQ_EVENT_PGMCHANGE
   .Flags = 0
   .Tag = 0
   .Queue = que
   .Tick_o_Tv_sec = 0
   .Tv_nsec = 0
   .Source_client = id
   .Source_port = porta
   .Dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS
   .Dest_port = SND_SEQ_ADDRESS_UNKNOWN
   .Channel = 0
   .Value = 44       ' Imposta il suono dello strumento musicale da usare
 End With

 InviaEventoMidi(handle, ev_midi)

' Note ON
 With ev_midi
   .Type = SND_SEQ_EVENT_NOTEON
   .Flags = 0
   .Tag = 0
   .Queue = que
   .Tick_o_Tv_sec = 0
   .Tv_nsec = 0
   .Source_client = id
   .Source_port = porta
   .Dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS
   .Dest_port = SND_SEQ_ADDRESS_UNKNOWN
   .Channel = 0
   .Note = 64        ' Imposta una nota Midi da eseguire
   .Velocity = 100   ' Imposta la velocità di tocco
 End With

 InviaEventoMidi(handle, ev_midi)

' Imposta la durata dell'esecuzione della nota:
 Wait 3

' Note OFF
 With ev_midi
   .Type = SND_SEQ_EVENT_NOTEOFF
   .Flags = 0
   .Tag = 0
   .Queue = que
   .Tick_o_Tv_sec = 0
   .Tv_nsec = 0
   .Source_client = id
   .Source_port = porta
   .Dest_client = SND_SEQ_ADDRESS_SUBSCRIBERS
   .Dest_port = SND_SEQ_ADDRESS_UNKNOWN
   .Channel = 0
   .Note = 64        ' Imposta una nota Midi da eseguire
   .Velocity = 0     ' Imposta la velocità di tocco
 End With

 InviaEventoMidi(handle, ev_midi)

' Va in Chiusura:
 snd_seq_close(handle)

End

Private Procedure InviaEventoMidi(p As Pointer, ev_midi As EventoMidiAlsa)

 Dim err As Integer

 err = snd_seq_event_output(p, ev_midi)
 If err < 0 Then error.Raise("Errore: " & snd_strerror(err))

 err = snd_seq_drain_output(p)
 If err < 0 Then error.Raise("Errore: " & snd_strerror(err))

End


Impostando e usando solo variabili Globali per ciascun dato della Classe specifica

La Classe specifica della gestione degli Eventi Midi di ALSA può anche solo contenere singole variabili di tipo Globale, ciascuna delle quali rappresenta un membro:

Public type As Byte
Public flag As Byte
Public tag As Byte
Public queue As Byte
Public tick_o_tv_sec As Integer
Public tv_nsec As Integer
Public source_client As Byte
Public source_port As Byte
Public dest_client As Byte
Public dest_port As Byte
Public channel As Byte
Public note As Byte
Public velocity As Byte
Public off_velocity As Byte
Public param As Integer
Public value As Integer

Ovviamente nel codice pricipale di Gambas si creerà un Oggetto (istanza) della Classe specifica degli Eventi Midi ALSA, così costituita, e le predette variabili globali saranno richiamate nel modo consueto attraverso la variabile identificatrice della Classe specifica.


Note

[1] In Gambas una "Struttura " può anche essere sostituita con una Classe avente solo Proprietà (dunque senza Metodi né Eventi).