• Non ci sono risultati.

4.6 Implementazione Riproduttore di Suoni

4.6.2 NXTSoundGetState - NXTSoundSetState

Le due chiamate a sistema di cui si tratterà in questa sottosezione non provocano, come facevano, invece, le due viste in precedenza, la riproduzione di un contributo sonoro, ma agiscono sulle variabili interne dell'oggetto sCond, il quale, come detto in precedenza, è un'istanza della classe SoundCondition e contiene informazioni sullo “stato” del riproduttore di suoni durante una simulazione. Tale “stato” viene specificato principalmente mediante due valori: i campi state e flags.

Il campo state (stato) è un valore numerico che specifica, appunto, in che 'stato' si trova il riproduttore di suoni in un dato istante; in totale vi sono quattro distinti stati in cui esso può trovarsi, ossia i seguenti:

0: SOUND_IDLE - il riproduttore di suoni è 'idle', cioè non sta riproducendo

alcun suono;

2: SOUND_FILE - il riproduttore di suoni sta riproducendo un file audio (nel

formato .RSO);

3: SOUND_TONE - il riproduttore di suoni sta riproducendo una nota

musicale;

4: SOUND_STOP - al riproduttore di suoni è stata appena inoltrata una

Il campo flags (flag) è un campo di due bit utile per specificare quali delle seguenti condizioni sussistono per il riproduttore di suoni: è 'idle', ha una richiesta di riproduzione audio pendente, sta riproducendo qualcosa. I valori che i suddetti bit (il cui bit più significativo è quello più a sinistra) possono assumere sono i seguenti:

00: SOUND_FLAGS_IDLE: il riproduttore di suoni è 'idle', cioè non sta

riproducendo alcun suono e non ha alcuna richiesta di riproduzione pendente;

01: SOUND_FLAGS_UPDATE: il riproduttore di suoni ha una richiesta di

riproduzione pendente;

10: SOUND_FLAGS_RUNNING: il riproduttore di suoni sta riproducendo un

file audio od una nota musicale;

11: il riproduttore di suoni sta riproducendo un file audio od una nota

musicale, ed ha anche una richiesta di riproduzione pendente.

Vediamo ora l'effettivo utilizzo dei campi appena presentati, nel contesto del riproduttore di suoni.

Quando in un programma per il robot LEGO® si desidera riprodurre un file audio od una nota musicale, vengono invocate, come specificato in precedenza, rispettivamente le syscall NXTSoundPlayFile o NXTSoundPlayTone. L'invocazione di queste ultime, però, come da specifiche firmware, è talvolta seguita da una (o più) chiamata a NXTSoundGetState (per chiarimenti a riguardo consultare la sottosezione 4.6.4). L'esecuzione di questa chiamata serve per controllare lo “stato” del riproduttore di suoni.

Appena si invoca all'interno di un programma .RXE la syscall NXTSoundGetState, la classe Execution del simulatore, come si evince dal listato di codice riportato a pagina 64, non fa altro che lanciare il metodo soundGetState() dell'oggetto sCond, fornendogli in ingresso i parametri di cui necessita. Questo metodo implementa poi effettivamente le funzionalità della syscall NXTSoundGetState.

public synchronized int soundGetState(DSTOC [] table, int source2){ . . .

int valFlags = 1 * flags[1] + 2 * flags[0]; //Converte campo di bit 'flags' in decimale table[source2+2].setValDefault(valFlags); //Ritorna in uscita il valore di 'flags'

. . .

table[source2+1].setValDefault(state); //Ritorna in uscita il valore di 'state' return state;

}

Come si nota dall'analisi del codice sopra riportato, il metodo in questione non fa altro che salvare in uscita, negli appositi spazi riservati nel cluster di parametri relativo alla syscall NXTSoundGetState, i valori di flags e state richiesti.

Quando in un programma per il robot LEGO® si desidera modificare lo “stato” del riproduttore di suoni, ossia si vogliono assegnare nuovi valori ai campi state e flags, viene invocata la syscall NXTSoundSetState. Quest'ultima tuttavia, nella versione 1.28 del firmware, è utilizzata soltanto per imporre l'interruzione dell'eventuale riproduzione audio in corso. Da ciò ne deriva il fatto che è possibile assegnare soltanto il valore '4' al campo state (SOUND_STOP) ed il valore '0' (entrambi i bit a '0') al campo flags (SOUND_FLAGS_IDLE).

Appena si invoca all'interno di un programma .RXE la chiamata a sistema di cui sopra, la classe Execution di NXTSimulator, come si nota nell'estratto di codice sorgente riportato a pagina 64, lancia il metodo soundSetState() dell'oggetto sCond, fornendogli in ingresso i parametri di cui necessita. Tale metodo esegue poi effettivamente le funzionalità della syscall NXTSoundSetState.

Segue il codice sorgente di soundSetState().

public synchronized int soundSetState(DSTOC [] table, int source2){

state = (int)table[source2+2].getValDefault(); //Assegnazione valore al campo 'state' switch((int)table[source2+3].getValDefault()){ //Assegnazione valore al campo di bit 'flags' case 0: flags[0] = 0; flags[1] = 0; break;

case 1: flags[0] = 0; flags[1] = 1; break; case 2: flags[0] = 1; flags[1] = 0; break; case 3: flags[0] = 1; flags[1] = 1; break; }

table[source2+1].setValDefault(state); //Ritorna in uscita il valore di 'state' setStop(); //Invoca metodo per fermare l'eventuale riproduzione audio corrente return state;

Il metodo in questione, come prima cosa, legge i valori da assegnare a state e flags, i quali sono forniti in ingresso nel cluster di parametri della chiamata a sistema NXTSoundSetState, e li assegna poi ai suddetti campi di sCond. Fatto ciò, viene salvato nell'apposito spazio del cluster della syscall il valore attuale del campo state, e viene invocato il metodo setStop(): quest'ultimo è incaricato di comandare l'interruzione dell'eventuale riproduzione audio in corso da parte del riproduttore di suoni. Tale metodo, infatti, chiama il metodo stopAll(), di classe SoundReproducer, sull'oggetto denominato lastLaunched, il quale è un riferimento che sCond mantiene all'ultimo thread di classe SoundReproducer che è stato lanciato. Di seguito viene proposto il codice sorgente relativo a stopAll().

public void stopAll(){

if(player.isPlaying()){ //Riproduzione nota musicale attualmente in corso player.stop();

synchronized(NXTSView.sCond){ NXTSView.sCond.state = 0; NXTSView.sCond.setActualPriority(); //Aggiorna priorità al valore successivo NXTSView.sCond.notifyAll();

}

}else if((auline != null) && (auline.isActive())){ //Riproduzione file musicale in corso auline.stop(); synchronized(NXTSView.sCond){ NXTSView.sCond.state = 0; NXTSView.sCond.setActualPriority(); NXTSView.sCond.notifyAll(); } } }

Dal listato di codice sopra riportato si nota che viene dapprima verificato se sia in corso o meno la riproduzione di una nota musicale o di un file audio e, in caso affermativo, la si sospende con l'apposito comando di stop() dato rispettivamente all'oggetto player o ad auline. Fatto ciò, viene acquisito il lock [3t] sull'oggetto

sCond, in modo da impostare il nuovo valore del campo state, il quale viene

aggiornato a '0' (SOUND_IDLE), giacché l'eventuale riproduzione audio in corso è stata abortita. Viene, infine, aggiornato il valore di priorità della successiva syscall audio da mandare eventualmente in esecuzione, e sono notificati eventuali “ascoltatori” dell'avvenuto aggiornamento dell'oggetto sCond medesimo.