/* Voice thread message processing */ static enum voice_state voice_message(struct voice_thread_data *td) { if (quiet_counter > 0) queue_wait_w_tmo(&voice_queue, &td->ev, HZ/10); else queue_wait(&voice_queue, &td->ev); switch (td->ev.id) { case Q_VOICE_PLAY: LOGFQUEUE("voice < Q_VOICE_PLAY"); if (quiet_counter == 0) { /* Boost CPU now */ trigger_cpu_boost(); } else { /* Stop any clip still playing */ voice_stop_playback(); } quiet_counter = QUIET_COUNT; /* Copy the clip info */ td->vi = *(struct voice_info *)td->ev.data; /* Be sure audio buffer is initialized */ audio_restore_playback(AUDIO_WANT_VOICE); /* We need nothing more from the sending thread - let it run */ queue_reply(&voice_queue, 1); /* Make audio play more softly and set delay to return to normal playback level */ pcmbuf_soft_mode(true); /* Clean-start the decoder */ td->st = speex_decoder_init(&speex_wb_mode); /* Make bit buffer use our own buffer */ speex_bits_set_bit_buffer(&td->bits, td->vi.start, td->vi.size); speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead); return VOICE_STATE_DECODE; case SYS_TIMEOUT: if (voice_unplayed_frames()) { /* Waiting for PCM to finish */ break; } /* Drop through and stop the first time after clip runs out */ if (quiet_counter-- != QUIET_COUNT) { if (quiet_counter <= 0) pcmbuf_soft_mode(false); break; } /* Fall-through */ case Q_VOICE_STOP: LOGFQUEUE("voice < Q_VOICE_STOP"); cancel_cpu_boost(); voice_stop_playback(); break; /* No default: no other message ids are sent */ } return VOICE_STATE_MESSAGE; }
/* Voice thread message processing */ static void voice_message(struct voice_thread_data *td) { while (1) { switch (td->ev.id) { case Q_VOICE_PLAY: LOGFQUEUE("voice < Q_VOICE_PLAY"); /* Put up a block for completion signal */ voice_done = false; /* Copy the clip info */ td->vi = *(struct voice_info *)td->ev.data; /* Be sure audio buffer is initialized */ audio_restore_playback(AUDIO_WANT_VOICE); /* We need nothing more from the sending thread - let it run */ queue_reply(&voice_queue, 1); if (td->state == TSTATE_STOPPED) { /* Boost CPU now */ trigger_cpu_boost(); } else if (!playback_is_playing()) { /* Just voice, stop any clip still playing */ pcmbuf_play_stop(); } /* Clean-start the decoder */ td->st = speex_decoder_init(&speex_wb_mode); /* Make bit buffer use our own buffer */ speex_bits_set_bit_buffer(&td->bits, td->vi.start, td->vi.size); speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead); td->state = TSTATE_DECODE; return; case Q_VOICE_STOP: LOGFQUEUE("voice < Q_VOICE_STOP: %ld", td->ev.data); if (td->ev.data != 0 && !playback_is_playing()) { /* If not playing, it's just voice so stop pcm playback */ pcmbuf_play_stop(); } /* Cancel boost */ cancel_cpu_boost(); td->state = TSTATE_STOPPED; voice_done = true; break; case Q_VOICE_STATE: LOGFQUEUE("voice < Q_VOICE_STATE"); queue_reply(&voice_queue, td->state); if (td->state == TSTATE_STOPPED) break; /* Not in a playback state */ return; default: /* Default messages get a reply and thread continues with no * state transition */ LOGFQUEUE("voice < default"); if (td->state == TSTATE_STOPPED) break; /* Not in playback state */ queue_reply(&voice_queue, 0); return; } queue_wait(&voice_queue, &td->ev); } }