winmm: Implemented audio capture support.
parent
4499e5bcc6
commit
51d1523380
|
@ -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. */
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue