void awaitPcmOutput (PcmDevice *pcm) { int code; if ((code = snd_pcm_playback_flush(pcm->handle)) < 0) { logPcmError(LOG_WARNING, "flush", code); } }
static void flush_qsa(audio_output_t* ao) { qsa_internal_t* userptr; userptr=ao->userptr; if (userptr!=NULL); { snd_pcm_playback_flush(userptr->audio_handle); } }
Error AlsaPMO::Reset(bool user_stop) { if (user_stop) snd_pcm_playback_drain(m_handle); else snd_pcm_playback_flush(m_handle); snd_pcm_playback_prepare(m_handle); return kError_NoErr; }
static void *processTones(void *dummy) { bool done; int error; int length; int index; Tone *tone, *nextTone; snd_pcm_channel_status_t status; //pthread_setname_np(pthread_self(), "tonegen"); // Main loop. Wait for audio driver to need more data while( live ) { pthread_mutex_lock( &toneMutex ); if( tone_count == 0 ) { // Wait for a tone command to come in snd_pcm_playback_flush( playback_handle ); snd_pcm_plugin_prepare( playback_handle, SND_PCM_CHANNEL_PLAYBACK ); pthread_cond_wait( &condvar_newtone, &toneMutex ); } if( tone_count == 0 ) { pthread_mutex_unlock( &toneMutex ); continue; } pthread_mutex_unlock( &toneMutex ); // Send tone data FD_ZERO( &write_handles ); FD_SET( sample_handle, &write_handles ); error = select(sample_handle + 1, NULL, &write_handles, NULL, NULL); if( error < 0 ) { // Select failed. slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "processTones select failed %d (%d)\n", error, errno); pthread_mutex_unlock( &toneMutex ); live = DEAD; break; } length = 0; // This should always be true if( FD_ISSET( sample_handle, &write_handles ) ) { int active_count = 0; for(tone = tones; tone != NULL; tone = tone->next) { done = tone->killed || (tonepos > tone->end); //fprintf (stderr,"processTone::writeTone (before active check) tone %ld tone->end %ld active %d done %d tonepos %ld \n", tone, tone->end, tone->active, done, tonepos); if( !done ) { // Write the tone error = writeTone(tone, (tone != tones)); //error = tone->generator(tone->position, length, sample_frequency, frag_buffer, &tone->data, terminating); if( error != EOK ) { done = true; } active_count++; } tone->active &= !done; //fprintf (stderr,"processTone::writeTone tone %ld tone->end %ld active %d tonepos %ld \n", tone, tone->end, tone->active, tonepos); } for(index = 0; index < frag_samples; index++) { record_buffer[index*2 ] = stage_buffer[index] / stage_samples[index]; record_buffer[index*2+1] = stage_buffer[index] / stage_samples[index]; } pthread_mutex_lock(&fillMutex); if (render_buffer != NULL) { memcpy(render_buffer, record_buffer, frame_size); } pthread_mutex_unlock(&fillMutex); tonepos += frag_samples; if (active_count > 0) { fprintf (stderr,"processTone tonepos %ld \n", tonepos); error = snd_pcm_plugin_write (playback_handle, record_buffer, frame_size); if( error != frame_size ) { memset (&status, 0, sizeof (status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; if ((error = snd_pcm_plugin_status (playback_handle, &status)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "retrieving audio interface status failed (%s)\n", snd_strerror (error)); } else if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN || status.status == SND_PCM_STATUS_CHANGE) { if ((error = snd_pcm_plugin_prepare (playback_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "cannot prepare audio interface for use (%s)\n", snd_strerror (error)); } } else { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "non-underrun write failure (%s)\n", snd_strerror (error)); } // Retry now that we're prepared error = snd_pcm_plugin_write (playback_handle, record_buffer, frame_size); } if( error != frame_size ) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "write to audio interface failed (%s) %d\n", snd_strerror (error), error); } } } else { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unknown file handle activated" ); } pthread_mutex_lock( &toneMutex ); //fprintf (stderr,"processTone::delete tones %lx count %d \n", tones, tone_count); int delete_count; do { delete_count = 0; for(tone = tones; tone != NULL; tone = tone->next) { done = tone->killed || (tonepos > tone->end); if( done || !tone->active ) { // Remove the tone from the list if (tone->prev != NULL) { tone->prev->next = tone->next; } else { tones = tone->next; } if (tone->next != NULL) { tone->next->prev = tone->prev; } tone_count--; free(tone); delete_count++; fprintf (stderr,"processTone::delete tone %lx tones %lx count %d \n", tone, tones, tone_count); break; } } } while (delete_count > 0); pthread_mutex_unlock( &toneMutex ); if (tone_count == 0) { memset(record_buffer, 0, frame_size); } } return NULL; }