Differenze tra le versioni di "Alsa e Gambas: Gestione dei dati Midi in Ricezione"

Da Gambas-it.org - Wikipedia.
(Introduzione)
Riga 22: Riga 22:
 
4) uso del '''''file-device''''' creato dal sistema e che rappresenta la porta virtuale di un dispositivo Midi esterno collegato al computer:
 
4) uso del '''''file-device''''' creato dal sistema e che rappresenta la porta virtuale di un dispositivo Midi esterno collegato al computer:
 
<BR>inseriamo ugualmente questa soluzione, nonostante possa essere definita ''extra ALSA'', in quanto non prevedere per la ''ricezione'' dei messaggi Midi nessuna funzione di ALSA.
 
<BR>inseriamo ugualmente questa soluzione, nonostante possa essere definita ''extra ALSA'', in quanto non prevedere per la ''ricezione'' dei messaggi Midi nessuna funzione di ALSA.
 +
 +
 +
===Organizzazione dei dati di un evento Midi inviati da ALSA all'applicativo===
 +
 +
E' bene precisare sin da ora che ALSA invia gli eventi Midi al Client ricevente con la medesima modalità con la quale li accetta. Ovvero sia ALSA trasmette tutti i dati ''comuni'' agli eventi Midi con l'aggiunta dei dati ''specifici'' dell'evento trasmesso.
 +
<BR>Pertanto, se andassimo a vedere tutti i 28 byte (sui quali si trovano i valori che compongono i vari eventi Midi) di un NoteON (per esempio: canale 0, num. midi Nota 69, velocità 100) trasmesso dalla tastiera esterna, riscontreremmo in console i seguenti valori ricevuti:
 +
 +
<TABLE>
 +
      <TR>
 +
        <TD>'''Valore ricevuto'''</td><TD> - </td><TD>'''Dato corrispondente:'''</td></tr>
 +
      <TR>
 +
        <TD>6</td><TD>=</td><TD>byte n. 0: Type</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 1: Flags</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 2: Tag</td></tr>
 +
      <TR>
 +
        <TD>253</td><TD>=</td><TD> byte n. 3: Queue</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 4: Tick o Tv_sec (Integer)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 5: (Tick o Tv_sec)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 6: (Tick o Tv_sec)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 7: (Tick o Tv_sec)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 8: Tv_nsec (Integer)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 9: (Tv_nsec)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 10: (Tv_nsec)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 11: (Tv_nsec)</td></tr>
 +
      <TR>
 +
        <TD>14</td><TD>=</td><TD> byte n. 12: Id_client source</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 13: Porta_client source</td></tr>
 +
      <TR>
 +
        <TD>128</td><TD>=</td><TD> byte n. 14: Client_dest</td></tr>
 +
      <TR>
 +
        <TD>1</td><TD>=</td><TD> byte n. 15: Porta_dest</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 16: Canale</td></tr>
 +
      <TR>
 +
        <TD>60</td><TD>=</td><TD> byte n. 17: num. midi Nota</td></tr>
 +
      <TR>
 +
        <TD>100</td><TD>=</td><TD> byte n. 18: Velocità</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 19: Off-Velocity</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 20: primoValore (Integer)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 21: (primoValore)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 22: (primoValore)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 23: (primoValore)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 24: secondoValore (Integer)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 25: (secondoValore)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 26: (secondoValore)</td></tr>
 +
      <TR>
 +
        <TD>0</td><TD>=</td><TD> byte n. 27: (secondoValore)</td></tr>
 +
 +
</table>

Versione delle 11:41, 1 ott 2011

Nei capitoli precedenti abbiamo considerato l'argomento dell'Invio dei dati Midi con Gambas 3 ad ALSA; ora prendiamo in considerazione la gestione dei dati in Ricezione da un device esterno al nostro applicativo.

Introduzione

La situazione è la seguente:
Il dispositivo esterno invia un dato alla porta del nostro applicativo, la quale dovrà essere posta dunque in modalità Write (tenuto conto che la si deve pensare "dal punto di vista dell'altro device"). Il dato, giunto alla porta dell'applicativo, non sarà però accolto automaticamente dal programma, ma questo - per poterlo acquisire - dovrà andare a leggere la porta.
Il problema più grosso è che però l'applicativo - ovviamente - non conosce il momento esatto in cui il dato sarà scritto, cioè inviato alla sua porta; e pertanto non sa quando deve leggere la propria porta per acquisire il dato inviato.

Possiamo dire che questa è stato il problema più grosso da superare nello studio da noi compiuto per gestire la "ricezione" dei dati Midi. La soluzione più corretta sarebbe operare mediante un Callback (che in Gambas dovrebbe essere stato finalmente supportato), quando arriva un evento. La funzione Callback dovrebbe semplicemente alzare un evento (RAISE xxx), che poi esegue la lettura da ALSA e gestisce quanto ricevuto. Tale soluzione ottimale non è perseguibile, poiché ALSA purtroppo non è in grado invocare un Callback.

Senza perderci d'animo, siamo giunti al termine di un lungo studio e numerose prove ad individuare e testare positivamente ben quattro soluzioni:

1) uso dei File Descriptors:
la strategia è di interrogare il file descriptor passato direttamente dalle funzioni di ALSA, ma semplicemente per avere un evento _Read(), e leggere quindi i dati giusti ed utili da un'altra funzione di ALSA;

2) uso della funzione Timer:
questa funzione di gambas deve provvedere a scatenare una routine, nella quale avviene la lettura della porta. Si potrebbe esperire anche un ciclo WHILE continuo, in mezzo al quale si porrebbe un Wait per dare modo a Gambas di fare anche altro. Però, tale seconda soluzione, pur probabilmente avendo meno latenza, impegnerebbe eccessivamente la CPU, impedendo così di fatto al programma di compiere fluidamente altre operazioni. Fra le due soluzioni è dunque preferibile il Timer. Purtroppo l'approccio del timer non è del tutto opportuno. Anche pensando a un timer con scadenza molto stretta, per esempio un millisecondo, l'idea non è conveniente, anche se più o meno può funzionare. La soluzione più corretta sarebbe operare mediante un Callback (che in Gambas dovrebbe essere stato finalmente supportato), quando arriva un evento.

3) uso di un programma C come supporto:
la strategia è quella di far compiere ad un altro programma scritto in C, che funzionerebbe come demone, la funzione di ricevere i messaggi Midi;

4) uso del file-device creato dal sistema e che rappresenta la porta virtuale di un dispositivo Midi esterno collegato al computer:
inseriamo ugualmente questa soluzione, nonostante possa essere definita extra ALSA, in quanto non prevedere per la ricezione dei messaggi Midi nessuna funzione di ALSA.


Organizzazione dei dati di un evento Midi inviati da ALSA all'applicativo

E' bene precisare sin da ora che ALSA invia gli eventi Midi al Client ricevente con la medesima modalità con la quale li accetta. Ovvero sia ALSA trasmette tutti i dati comuni agli eventi Midi con l'aggiunta dei dati specifici dell'evento trasmesso.
Pertanto, se andassimo a vedere tutti i 28 byte (sui quali si trovano i valori che compongono i vari eventi Midi) di un NoteON (per esempio: canale 0, num. midi Nota 69, velocità 100) trasmesso dalla tastiera esterna, riscontreremmo in console i seguenti valori ricevuti:

Valore ricevuto - Dato corrispondente:
6=byte n. 0: Type
0= byte n. 1: Flags
0= byte n. 2: Tag
253= byte n. 3: Queue
0= byte n. 4: Tick o Tv_sec (Integer)
0= byte n. 5: (Tick o Tv_sec)
0= byte n. 6: (Tick o Tv_sec)
0= byte n. 7: (Tick o Tv_sec)
0= byte n. 8: Tv_nsec (Integer)
0= byte n. 9: (Tv_nsec)
0= byte n. 10: (Tv_nsec)
0= byte n. 11: (Tv_nsec)
14= byte n. 12: Id_client source
0= byte n. 13: Porta_client source
128= byte n. 14: Client_dest
1= byte n. 15: Porta_dest
0= byte n. 16: Canale
60= byte n. 17: num. midi Nota
100= byte n. 18: Velocità
0= byte n. 19: Off-Velocity
0= byte n. 20: primoValore (Integer)
0= byte n. 21: (primoValore)
0= byte n. 22: (primoValore)
0= byte n. 23: (primoValore)
0= byte n. 24: secondoValore (Integer)
0= byte n. 25: (secondoValore)
0= byte n. 26: (secondoValore)
0= byte n. 27: (secondoValore)