зеркало из https://github.com/mozilla/pjs.git
150 строки
4.5 KiB
Diff
150 строки
4.5 KiB
Diff
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(
|