|
@@ -27,6 +27,7 @@ |
|
|
#include "../../core/windows/SDL_windows.h" |
|
|
#include <mmsystem.h> |
|
|
|
|
|
#include "SDL_assert.h" |
|
|
#include "SDL_timer.h" |
|
|
#include "SDL_audio.h" |
|
|
#include "../SDL_audio_c.h" |
|
@@ -152,30 +153,83 @@ WINMM_WaitDone(_THIS) |
|
|
} while (left > 0); |
|
|
} |
|
|
|
|
|
static int |
|
|
WINMM_CaptureFromDevice(_THIS, void *buffer, int buflen) |
|
|
{ |
|
|
const int nextbuf = this->hidden->next_buffer; |
|
|
MMRESULT result; |
|
|
|
|
|
SDL_assert(buflen == this->spec.size); |
|
|
|
|
|
/* Wait for an audio chunk to finish */ |
|
|
WaitForSingleObject(this->hidden->audio_sem, INFINITE); |
|
|
|
|
|
/* Copy it to caller's buffer... */ |
|
|
SDL_memcpy(buffer, this->hidden->wavebuf[nextbuf].lpData, this->spec.size); |
|
|
|
|
|
/* requeue the buffer that just finished. */ |
|
|
result = waveInAddBuffer(this->hidden->hin, |
|
|
&this->hidden->wavebuf[nextbuf], |
|
|
sizeof (this->hidden->wavebuf[nextbuf])); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return -1; /* uhoh! Disable the device. */ |
|
|
} |
|
|
|
|
|
/* queue the next buffer in sequence, next time. */ |
|
|
this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS; |
|
|
return this->spec.size; |
|
|
} |
|
|
|
|
|
static void |
|
|
WINMM_FlushCapture(_THIS) |
|
|
{ |
|
|
/* Wait for an audio chunk to finish */ |
|
|
if (WaitForSingleObject(this->hidden->audio_sem, 0) == WAIT_OBJECT_0) { |
|
|
const int nextbuf = this->hidden->next_buffer; |
|
|
/* requeue the buffer that just finished without reading from it. */ |
|
|
waveInAddBuffer(this->hidden->hin, |
|
|
&this->hidden->wavebuf[nextbuf], |
|
|
sizeof (this->hidden->wavebuf[nextbuf])); |
|
|
this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS; |
|
|
} |
|
|
} |
|
|
|
|
|
static void |
|
|
WINMM_CloseDevice(_THIS) |
|
|
{ |
|
|
int i; |
|
|
|
|
|
if (this->hidden->audio_sem) { |
|
|
CloseHandle(this->hidden->audio_sem); |
|
|
} |
|
|
if (this->hidden->hout) { |
|
|
waveOutReset(this->hidden->hout); |
|
|
|
|
|
/* Clean up mixing buffers */ |
|
|
for (i = 0; i < NUM_BUFFERS; ++i) { |
|
|
if (this->hidden->wavebuf[i].dwUser != 0xFFFF) { |
|
|
waveOutUnprepareHeader(this->hidden->hout, |
|
|
&this->hidden->wavebuf[i], |
|
|
sizeof (this->hidden->wavebuf[i])); |
|
|
/* Clean up mixing buffers */ |
|
|
for (i = 0; i < NUM_BUFFERS; ++i) { |
|
|
if (this->hidden->wavebuf[i].dwUser != 0xFFFF) { |
|
|
waveOutUnprepareHeader(this->hidden->hout, |
|
|
&this->hidden->wavebuf[i], |
|
|
sizeof (this->hidden->wavebuf[i])); |
|
|
} |
|
|
} |
|
|
|
|
|
waveOutClose(this->hidden->hout); |
|
|
} |
|
|
|
|
|
if (this->hidden->hin) { |
|
|
waveInReset(this->hidden->hin); |
|
|
|
|
|
/* Clean up mixing buffers */ |
|
|
for (i = 0; i < NUM_BUFFERS; ++i) { |
|
|
if (this->hidden->wavebuf[i].dwUser != 0xFFFF) { |
|
|
waveInUnprepareHeader(this->hidden->hin, |
|
|
&this->hidden->wavebuf[i], |
|
|
sizeof (this->hidden->wavebuf[i])); |
|
|
} |
|
|
} |
|
|
waveInClose(this->hidden->hin); |
|
|
} |
|
|
|
|
|
if (this->hidden->hout) { |
|
|
waveOutClose(this->hidden->hout); |
|
|
if (this->hidden->audio_sem) { |
|
|
CloseHandle(this->hidden->audio_sem); |
|
|
} |
|
|
|
|
|
SDL_free(this->hidden->mixbuf); |
|
@@ -269,32 +323,44 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) |
|
|
result = waveInOpen(&this->hidden->hin, devId, &waveformat, |
|
|
(DWORD_PTR) CaptureSound, (DWORD_PTR) this, |
|
|
CALLBACK_FUNCTION); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveInOpen()", result); |
|
|
} |
|
|
} else { |
|
|
result = waveOutOpen(&this->hidden->hout, devId, &waveformat, |
|
|
(DWORD_PTR) FillSound, (DWORD_PTR) this, |
|
|
CALLBACK_FUNCTION); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveOutOpen()", result); |
|
|
} |
|
|
} |
|
|
|
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveOutOpen()", result); |
|
|
} |
|
|
#ifdef SOUND_DEBUG |
|
|
/* Check the sound device we retrieved */ |
|
|
{ |
|
|
WAVEOUTCAPS caps; |
|
|
|
|
|
result = waveOutGetDevCaps((UINT) this->hidden->hout, |
|
|
&caps, sizeof(caps)); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveOutGetDevCaps()", result); |
|
|
if (iscapture) { |
|
|
WAVEINCAPS caps; |
|
|
result = waveInGetDevCaps((UINT) this->hidden->hout, |
|
|
&caps, sizeof (caps)); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveInGetDevCaps()", result); |
|
|
} |
|
|
printf("Audio device: %s\n", caps.szPname); |
|
|
} else { |
|
|
WAVEOUTCAPS caps; |
|
|
result = waveOutGetDevCaps((UINT) this->hidden->hout, |
|
|
&caps, sizeof(caps)); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveOutGetDevCaps()", result); |
|
|
} |
|
|
printf("Audio device: %s\n", caps.szPname); |
|
|
} |
|
|
printf("Audio device: %s\n", caps.szPname); |
|
|
} |
|
|
#endif |
|
|
|
|
|
/* Create the audio buffer semaphore */ |
|
|
this->hidden->audio_sem = |
|
|
CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); |
|
|
CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL); |
|
|
if (this->hidden->audio_sem == NULL) { |
|
|
return SDL_SetError("Couldn't create semaphore"); |
|
|
} |
|
@@ -312,11 +378,35 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) |
|
|
this->hidden->wavebuf[i].dwFlags = WHDR_DONE; |
|
|
this->hidden->wavebuf[i].lpData = |
|
|
(LPSTR) & this->hidden->mixbuf[i * this->spec.size]; |
|
|
result = waveOutPrepareHeader(this->hidden->hout, |
|
|
&this->hidden->wavebuf[i], |
|
|
sizeof(this->hidden->wavebuf[i])); |
|
|
|
|
|
if (iscapture) { |
|
|
result = waveInPrepareHeader(this->hidden->hin, |
|
|
&this->hidden->wavebuf[i], |
|
|
sizeof(this->hidden->wavebuf[i])); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveInPrepareHeader()", result); |
|
|
} |
|
|
|
|
|
result = waveInAddBuffer(this->hidden->hin, |
|
|
&this->hidden->wavebuf[i], |
|
|
sizeof(this->hidden->wavebuf[i])); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveInAddBuffer()", result); |
|
|
} |
|
|
} else { |
|
|
result = waveOutPrepareHeader(this->hidden->hout, |
|
|
&this->hidden->wavebuf[i], |
|
|
sizeof(this->hidden->wavebuf[i])); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveOutPrepareHeader()", result); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
if (iscapture) { |
|
|
result = waveInStart(this->hidden->hin); |
|
|
if (result != MMSYSERR_NOERROR) { |
|
|
return SetMMerror("waveOutPrepareHeader()", result); |
|
|
return SetMMerror("waveInStart()", result); |
|
|
} |
|
|
} |
|
|
|
|
@@ -334,8 +424,12 @@ WINMM_Init(SDL_AudioDriverImpl * impl) |
|
|
impl->WaitDevice = WINMM_WaitDevice; |
|
|
impl->WaitDone = WINMM_WaitDone; |
|
|
impl->GetDeviceBuf = WINMM_GetDeviceBuf; |
|
|
impl->CaptureFromDevice = WINMM_CaptureFromDevice; |
|
|
impl->FlushCapture = WINMM_FlushCapture; |
|
|
impl->CloseDevice = WINMM_CloseDevice; |
|
|
|
|
|
impl->HasCaptureSupport = SDL_TRUE; |
|
|
|
|
|
return 1; /* this audio target is available. */ |
|
|
} |
|
|
|
|
|