ALSA e Gambas - L'accodamento degli eventi

Da Gambas-it.org - Wikipedia.

ALSA, per processare uno o più Eventi Midi, ha bisogno che sia creata una Coda di Eventi Midi temporizzati.
Come sappiamo, la temporizzazione degli Eventi Midi avviene mediante l'assegnazione per ciascun Evento da parte dell'applicazione Midi di una marcatura temporale: il Timestamp.
Una Coda di Eventi Midi ALSA riceverà messaggi di temporizzazione, con i quali cercherà di adattare l'invio degli Eventi Midi a questa temporizzazione.
L'Evento Midi, temporizzato con il proprio valore timestamp, viene innanzitutto inserito nella coda di priorità, ed indirizzato al proprio client di destinazione subito o successivamente a seconda di quanto stabilito dal timestamp.

Creare e allocare la Coda degli Eventi Midi di ALSA

Per creare una Coda bisognerà utilizzare la funzione di ALSA:

int snd_seq_alloc_queue()

La funzione ritorna il valore identificativo della Coda, che potrà essere uguale o superiore a zero. Se la funzione, però, ritorna un valore minore di zero, riporterà un errore.
L'identificativo della Coda sarà poi utilizzato sia nella Struttura costitutiva di ciascun Evento Midi ALSA, sia nella funzione esterna "snd_seq_control_queue()" per far partire o arrestare la coda medesima.

Questa funzione, come ormai ben sappiamo, andrà dichiarata in Gambas con la consueta parola-chiave Extern:

Private Extern snd_seq_alloc_queue(seq As Pointer) As Integer

E' possibile dare anche un nome alla Coda sostituendo la suddetta funzione con la seguente funzione esterna di ALSA:

err = snd_seq_alloc_named_queue()

che sarà così dichiarata con Extern:

Private Extern snd_seq_alloc_named_queue(seq as Pointer, nome_coda As String) As Integer

Avvio ed arresto della Coda degli Eventi Midi di ALSA

Dopo aver allocato la Coda di Eventi Midi temporizzati, sarà necessario avviarla.
Se quest'azione non avviene, non vi sarà il processo di sequenziazione degli Eventi Midi temporizzati e, quindi, non vi sarà esecuzione audio.
Ciò sarà compiuto mediante la funzione esterna di ALSA:

snd_seq_control_queue(seq, q, type, value, 0, ev)

Laddove:

  • seq è l'handle del sequencer ALSA;
  • q è l'identificativo della coda da avviare (o da fermare);
  • type è il tipo di evento (Start, Stop oppure Continue);
  • value è il valore relativo all'evento;
  • ev è un istanza dell'evento.

In particolare per avviare la coda, si imposterà nel parametro "type" la Costante di ALSA:

SND_SEQ_EVENT_START = 30

Se, invece, intendiamo fermare la coda utilizzeremo la medesima funzione cambiando, però il terzo parametro con la Costante:

SND_SEQ_EVENT_STOP = 32

In Gambas dichiareremo le suddette Costanti come segue:

Private Const SND_SEQ_EVENT_START As Integer = 30
Private Const SND_SEQ_EVENT_STOP As Integer = 32

e saranno ad esempio così utilizzate:

Private Extern snd_seq_control_queue(seq As Pointer, id_queue As integer, type_queue As Integer, val_queue As Integer, ev_queue As Integer) As Integer

Public Sub Avvia_la_Coda()

 Dim err As Integer

 err = snd_seq_control_queue(handle, id_coda, SND_SEQ_EVENT_START, 0, 0)

End


Public Sub Arresta_la_Coda()

 Dim err As Integer

 err = snd_seq_control_queue(handle, id_coda, SND_SEQ_EVENT_STOP, 0, 0)

End


Fasi successive alla creazione della coda

Dopo la creazione sia della Coda che degli Eventi Midi ALSA, come esposto nelle pagine precedenti del presente Capitolo ALSA e Gambas - Gestione dei Messaggi Midi standard, gli Eventi Midi devono essere accodati nel buffer di ALSA.
Ciò deve avvire subito dopo la impostazione di tutti i parametri necessari alla definizione dell'Evento Midi ALSA, previsti nella Struttura snd_seq_event_t, a mezzo della funzione esterna:

snd_seq_event_output_buffer()

L'invio finale ad ALSA della Coda degli Eventi Midi, memorizzati nel buffer predetto, avviene attraverso la funzione esterna:

snd_seq_drain_output()

Quest'ultimo atto determina il processamento degli Eventi Midi da parte del sistema ALSA e l'esecuzione musicale.

L'arresto della Coda degli Eventi Midi, e quindi del loro processamento, avviene nella modalità già vista sopra, mediante l'uso della funzione esterna:

snd_seq_control_queue()

alla quale va passata al suo 3° argomento la Costante "SND_SEQ_EVENT_STOP".