diff --git a/media/libsydneyaudio/src/sydney_audio_waveapi.c b/media/libsydneyaudio/src/sydney_audio_waveapi.c --- a/media/libsydneyaudio/src/sydney_audio_waveapi.c +++ b/media/libsydneyaudio/src/sydney_audio_waveapi.c @@ -121,16 +121,17 @@ struct sa_stream { }; /** Forward definitions of audio api specific functions */ int allocateBlocks(int size, int count, WAVEHDR** blocks); int freeBlocks(WAVEHDR* blocks); int openAudio(sa_stream_t *s); int closeAudio(sa_stream_t * s); +int writeBlock(sa_stream_t *s, WAVEHDR* current); int writeAudio(sa_stream_t *s, LPSTR data, int bytes); int getSAErrorCode(int waveErrorCode); void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2); /** Normal way to open a PCM device */ int sa_stream_create_pcm(sa_stream_t **s, @@ -320,20 +321,32 @@ int sa_stream_pause(sa_stream_t *s) { status = waveOutPause(s->hWaveOut); HANDLE_WAVE_ERROR(status, "resuming audio playback"); s->playing = 0; return SA_SUCCESS; } + /** Block until all audio has been played */ int sa_stream_drain(sa_stream_t *s) { + int status; + WAVEHDR* current; + ERROR_IF_NO_INIT(s); - + + current = &(s->waveBlocks[s->waveCurrentBlock]); + if (current->dwUser) { + /* We've got pending audio which hasn't been written, we must write it to + the hardware, else it will never be played. */ + status = writeBlock(s, current); + HANDLE_WAVE_ERROR(status, "writing audio to audio device"); + } + if (!s->playing) { return SA_ERROR_INVALID; } /* wait for all blocks to complete */ EnterCriticalSection(&(s->waveCriticalSection)); while(s->waveFreeBlockCount < BLOCK_COUNT) { LeaveCriticalSection(&(s->waveCriticalSection)); @@ -502,16 +515,48 @@ int closeAudio(sa_stream_t * s) { s->playing = 0; DeleteCriticalSection(&(s->waveCriticalSection)); CloseHandle(s->callbackEvent); return result; } + +/** + * \brief - writes a WAVEHDR block of PCM audio samples to hardware. + * \param s - valid handle to opened sydney stream + * \param current - pointer to WAVEHDR storing audio samples to be played + * \return - completion status + */ +int writeBlock(sa_stream_t *s, WAVEHDR* current) { + int status; + ERROR_IF_NO_INIT(s); + + current->dwBufferLength = current->dwUser; + /* write to audio device */ + waveOutPrepareHeader(s->hWaveOut, current, sizeof(WAVEHDR)); + status = waveOutWrite(s->hWaveOut, current, sizeof(WAVEHDR)); + HANDLE_WAVE_ERROR(status, "writing audio to audio device"); + + EnterCriticalSection(&(s->waveCriticalSection)); + s->waveFreeBlockCount--; + LeaveCriticalSection(&(s->waveCriticalSection)); + + /* + * point to the next block + */ + (s->waveCurrentBlock)++; + (s->waveCurrentBlock) %= BLOCK_COUNT; + + s->playing = 1; + + return SA_SUCCESS; +} + /** * \brief - writes PCM audio samples to audio device * \param s - valid handle to opened sydney stream * \param data - pointer to memory storing audio samples to be played * \param nsamples - number of samples in the memory pointed by previous parameter * \return - completion status */ int writeAudio(sa_stream_t *s, LPSTR data, int bytes) { @@ -536,40 +581,27 @@ int writeAudio(sa_stream_t *s, LPSTR dat if(bytes < (int)(BLOCK_SIZE - current->dwUser)) { memcpy(current->lpData + current->dwUser, data, bytes); current->dwUser += bytes; break; } /* remain is even as BLOCK_SIZE and dwUser are even too */ - remain = BLOCK_SIZE - current->dwUser; + remain = BLOCK_SIZE - current->dwUser; memcpy(current->lpData + current->dwUser, data, remain); + current->dwUser += remain; bytes -= remain; data += remain; - current->dwBufferLength = BLOCK_SIZE; - /* write to audio device */ - waveOutPrepareHeader(s->hWaveOut, current, sizeof(WAVEHDR)); - status = waveOutWrite(s->hWaveOut, current, sizeof(WAVEHDR)); + + status = writeBlock(s, current); HANDLE_WAVE_ERROR(status, "writing audio to audio device"); - - EnterCriticalSection(&(s->waveCriticalSection)); - s->waveFreeBlockCount--; - LeaveCriticalSection(&(s->waveCriticalSection)); - - /* - * point to the next block - */ - (s->waveCurrentBlock)++; - (s->waveCurrentBlock) %= BLOCK_COUNT; current = &(s->waveBlocks[s->waveCurrentBlock]); current->dwUser = 0; - - s->playing = 1; } return SA_SUCCESS; } /** * \brief - audio callback function called when next WAVE header is played by audio device */ void CALLBACK waveOutProc(