mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-23 02:25:38 +00:00
WASAPI: all COM functions called in dedicated threads
This commit is contained in:
parent
2c9055d0d3
commit
65416669d3
223
src/wasapi.cpp
223
src/wasapi.cpp
|
@ -1299,8 +1299,8 @@ static void outstream_thread_run(void *arg) {
|
||||||
outstream_thread_deinit(si, os);
|
outstream_thread_deinit(si, os);
|
||||||
|
|
||||||
soundio_os_mutex_lock(osw->mutex);
|
soundio_os_mutex_lock(osw->mutex);
|
||||||
osw->open_complete = true;
|
|
||||||
osw->open_err = err;
|
osw->open_err = err;
|
||||||
|
osw->open_complete = true;
|
||||||
soundio_os_cond_signal(osw->cond, osw->mutex);
|
soundio_os_cond_signal(osw->cond, osw->mutex);
|
||||||
soundio_os_mutex_unlock(osw->mutex);
|
soundio_os_mutex_unlock(osw->mutex);
|
||||||
return;
|
return;
|
||||||
|
@ -1458,6 +1458,14 @@ static int outstream_clear_buffer_wasapi(struct SoundIoPrivate *si, struct Sound
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void instream_thread_deinit(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
|
||||||
|
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
||||||
|
|
||||||
|
if (isw->audio_capture_client)
|
||||||
|
IUnknown_Release(isw->audio_capture_client);
|
||||||
|
if (isw->audio_client)
|
||||||
|
IUnknown_Release(isw->audio_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void instream_destroy_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
static void instream_destroy_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||||
|
@ -1465,31 +1473,25 @@ static void instream_destroy_wasapi(struct SoundIoPrivate *si, struct SoundIoInS
|
||||||
|
|
||||||
if (isw->thread) {
|
if (isw->thread) {
|
||||||
isw->thread_exit_flag.clear();
|
isw->thread_exit_flag.clear();
|
||||||
if (isw->is_raw) {
|
if (isw->h_event)
|
||||||
if (isw->h_event)
|
SetEvent(isw->h_event);
|
||||||
SetEvent(isw->h_event);
|
|
||||||
} else {
|
soundio_os_mutex_lock(isw->mutex);
|
||||||
soundio_os_mutex_lock(isw->mutex);
|
soundio_os_cond_signal(isw->cond, isw->mutex);
|
||||||
soundio_os_cond_signal(isw->cond, isw->mutex);
|
soundio_os_cond_signal(isw->start_cond, isw->mutex);
|
||||||
soundio_os_mutex_unlock(isw->mutex);
|
soundio_os_mutex_unlock(isw->mutex);
|
||||||
}
|
|
||||||
soundio_os_thread_destroy(isw->thread);
|
soundio_os_thread_destroy(isw->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isw->audio_capture_client)
|
|
||||||
IUnknown_Release(isw->audio_capture_client);
|
|
||||||
if (isw->audio_client)
|
|
||||||
IUnknown_Release(isw->audio_client);
|
|
||||||
if (isw->h_event)
|
if (isw->h_event)
|
||||||
CloseHandle(isw->h_event);
|
CloseHandle(isw->h_event);
|
||||||
|
|
||||||
soundio_os_cond_destroy(isw->cond);
|
soundio_os_cond_destroy(isw->cond);
|
||||||
|
soundio_os_cond_destroy(isw->start_cond);
|
||||||
soundio_os_mutex_destroy(isw->mutex);
|
soundio_os_mutex_destroy(isw->mutex);
|
||||||
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||||
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
||||||
SoundIoInStream *instream = &is->pub;
|
SoundIoInStream *instream = &is->pub;
|
||||||
SoundIoDevice *device = instream->device;
|
SoundIoDevice *device = instream->device;
|
||||||
|
@ -1497,30 +1499,9 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
|
||||||
SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi;
|
SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if (FAILED(hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) {
|
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
if (hr == E_OUTOFMEMORY)
|
|
||||||
return SoundIoErrorNoMem;
|
|
||||||
else
|
|
||||||
return SoundIoErrorOpeningDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
isw->is_raw = device->is_raw;
|
|
||||||
|
|
||||||
if (!(isw->cond = soundio_os_cond_create())) {
|
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorNoMem;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(isw->mutex = soundio_os_mutex_create())) {
|
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorNoMem;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAudioClient,
|
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAudioClient,
|
||||||
CLSCTX_ALL, nullptr, (void**)&isw->audio_client)))
|
CLSCTX_ALL, nullptr, (void**)&isw->audio_client)))
|
||||||
{
|
{
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1540,14 +1521,12 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
|
||||||
} else {
|
} else {
|
||||||
WAVEFORMATEXTENSIBLE *mix_format;
|
WAVEFORMATEXTENSIBLE *mix_format;
|
||||||
if (FAILED(hr = IAudioClient_GetMixFormat(isw->audio_client, (WAVEFORMATEX **)&mix_format))) {
|
if (FAILED(hr = IAudioClient_GetMixFormat(isw->audio_client, (WAVEFORMATEX **)&mix_format))) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
wave_format.Format.nSamplesPerSec = mix_format->Format.nSamplesPerSec;
|
wave_format.Format.nSamplesPerSec = mix_format->Format.nSamplesPerSec;
|
||||||
CoTaskMemFree(mix_format);
|
CoTaskMemFree(mix_format);
|
||||||
mix_format = nullptr;
|
mix_format = nullptr;
|
||||||
if (wave_format.Format.nSamplesPerSec != (DWORD)instream->sample_rate) {
|
if (wave_format.Format.nSamplesPerSec != (DWORD)instream->sample_rate) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorIncompatibleDevice;
|
return SoundIoErrorIncompatibleDevice;
|
||||||
}
|
}
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
@ -1564,7 +1543,6 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
|
||||||
{
|
{
|
||||||
if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) {
|
if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) {
|
||||||
if (FAILED(hr = IAudioClient_GetBufferSize(isw->audio_client, &isw->buffer_frame_count))) {
|
if (FAILED(hr = IAudioClient_GetBufferSize(isw->audio_client, &isw->buffer_frame_count))) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
IUnknown_Release(isw->audio_client);
|
IUnknown_Release(isw->audio_client);
|
||||||
|
@ -1572,13 +1550,11 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
|
||||||
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAudioClient,
|
if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAudioClient,
|
||||||
CLSCTX_ALL, nullptr, (void**)&isw->audio_client)))
|
CLSCTX_ALL, nullptr, (void**)&isw->audio_client)))
|
||||||
{
|
{
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
if (!isw->is_raw) {
|
if (!isw->is_raw) {
|
||||||
WAVEFORMATEXTENSIBLE *mix_format;
|
WAVEFORMATEXTENSIBLE *mix_format;
|
||||||
if (FAILED(hr = IAudioClient_GetMixFormat(isw->audio_client, (WAVEFORMATEX **)&mix_format))) {
|
if (FAILED(hr = IAudioClient_GetMixFormat(isw->audio_client, (WAVEFORMATEX **)&mix_format))) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
wave_format.Format.nSamplesPerSec = mix_format->Format.nSamplesPerSec;
|
wave_format.Format.nSamplesPerSec = mix_format->Format.nSamplesPerSec;
|
||||||
|
@ -1597,42 +1573,29 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
|
||||||
buffer_duration, periodicity, (WAVEFORMATEX*)&wave_format, nullptr)))
|
buffer_duration, periodicity, (WAVEFORMATEX*)&wave_format, nullptr)))
|
||||||
{
|
{
|
||||||
if (hr == AUDCLNT_E_UNSUPPORTED_FORMAT) {
|
if (hr == AUDCLNT_E_UNSUPPORTED_FORMAT) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorIncompatibleDevice;
|
return SoundIoErrorIncompatibleDevice;
|
||||||
} else if (hr == E_OUTOFMEMORY) {
|
} else if (hr == E_OUTOFMEMORY) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorNoMem;
|
return SoundIoErrorNoMem;
|
||||||
} else {
|
} else {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (hr == AUDCLNT_E_UNSUPPORTED_FORMAT) {
|
} else if (hr == AUDCLNT_E_UNSUPPORTED_FORMAT) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorIncompatibleDevice;
|
return SoundIoErrorIncompatibleDevice;
|
||||||
} else if (hr == E_OUTOFMEMORY) {
|
} else if (hr == E_OUTOFMEMORY) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorNoMem;
|
return SoundIoErrorNoMem;
|
||||||
} else {
|
} else {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FAILED(hr = IAudioClient_GetBufferSize(isw->audio_client, &isw->buffer_frame_count))) {
|
if (FAILED(hr = IAudioClient_GetBufferSize(isw->audio_client, &isw->buffer_frame_count))) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
if (isw->is_raw)
|
if (isw->is_raw)
|
||||||
instream->software_latency = isw->buffer_frame_count / (double)instream->sample_rate;
|
instream->software_latency = isw->buffer_frame_count / (double)instream->sample_rate;
|
||||||
|
|
||||||
if (isw->is_raw) {
|
if (isw->is_raw) {
|
||||||
isw->h_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
|
||||||
if (!isw->h_event) {
|
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
|
||||||
}
|
|
||||||
if (FAILED(hr = IAudioClient_SetEventHandle(isw->audio_client, isw->h_event))) {
|
if (FAILED(hr = IAudioClient_SetEventHandle(isw->audio_client, isw->h_event))) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1641,19 +1604,16 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
|
||||||
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAudioSessionControl,
|
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAudioSessionControl,
|
||||||
(void **)&isw->audio_session_control)))
|
(void **)&isw->audio_session_control)))
|
||||||
{
|
{
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
if ((err = to_lpwstr(instream->name, strlen(instream->name), &isw->stream_name))) {
|
if ((err = to_lpwstr(instream->name, strlen(instream->name), &isw->stream_name))) {
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (FAILED(hr = IAudioSessionControl_SetDisplayName(isw->audio_session_control,
|
if (FAILED(hr = IAudioSessionControl_SetDisplayName(isw->audio_session_control,
|
||||||
isw->stream_name, nullptr)))
|
isw->stream_name, nullptr)))
|
||||||
{
|
{
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1661,34 +1621,17 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
|
||||||
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAudioCaptureClient,
|
if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAudioCaptureClient,
|
||||||
(void **)&isw->audio_capture_client)))
|
(void **)&isw->audio_capture_client)))
|
||||||
{
|
{
|
||||||
instream_destroy_wasapi(si, is);
|
|
||||||
return SoundIoErrorOpeningDevice;
|
return SoundIoErrorOpeningDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int instream_pause_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
|
static void instream_raw_run(SoundIoInStreamPrivate *is) {
|
||||||
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
|
||||||
HRESULT hr;
|
|
||||||
if (pause && !isw->is_paused) {
|
|
||||||
if (FAILED(hr = IAudioClient_Stop(isw->audio_client)))
|
|
||||||
return SoundIoErrorStreaming;
|
|
||||||
isw->is_paused = true;
|
|
||||||
} else if (!pause && isw->is_paused) {
|
|
||||||
if (FAILED(hr = IAudioClient_Start(isw->audio_client)))
|
|
||||||
return SoundIoErrorStreaming;
|
|
||||||
isw->is_paused = false;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void instream_raw_run(void *arg) {
|
|
||||||
soundio_panic("TODO instream_raw_run");
|
soundio_panic("TODO instream_raw_run");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void instream_shared_run(void *arg) {
|
static void instream_shared_run(SoundIoInStreamPrivate *is) {
|
||||||
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *) arg;
|
|
||||||
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
||||||
SoundIoInStream *instream = &is->pub;
|
SoundIoInStream *instream = &is->pub;
|
||||||
|
|
||||||
|
@ -1720,21 +1663,129 @@ static void instream_shared_run(void *arg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int instream_start_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
static void instream_thread_run(void *arg) {
|
||||||
|
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg;
|
||||||
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
||||||
int err;
|
SoundIoInStream *instream = &is->pub;
|
||||||
|
SoundIoDevice *device = instream->device;
|
||||||
|
SoundIo *soundio = device->soundio;
|
||||||
|
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
|
||||||
|
|
||||||
assert(!isw->thread);
|
int err;
|
||||||
isw->thread_exit_flag.test_and_set();
|
if ((err = instream_do_open(si, is))) {
|
||||||
|
instream_thread_deinit(si, is);
|
||||||
|
|
||||||
|
soundio_os_mutex_lock(isw->mutex);
|
||||||
|
isw->open_err = err;
|
||||||
|
isw->open_complete = true;
|
||||||
|
soundio_os_cond_signal(isw->cond, isw->mutex);
|
||||||
|
soundio_os_mutex_unlock(isw->mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
soundio_os_mutex_lock(isw->mutex);
|
||||||
|
isw->open_complete = true;
|
||||||
|
soundio_os_cond_signal(isw->cond, isw->mutex);
|
||||||
|
for (;;) {
|
||||||
|
if (!isw->thread_exit_flag.test_and_set()) {
|
||||||
|
soundio_os_mutex_unlock(isw->mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isw->started) {
|
||||||
|
soundio_os_mutex_unlock(isw->mutex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
soundio_os_cond_wait(isw->start_cond, isw->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isw->is_raw)
|
||||||
|
instream_raw_run(is);
|
||||||
|
else
|
||||||
|
instream_shared_run(is);
|
||||||
|
|
||||||
|
instream_thread_deinit(si, is);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||||
|
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
||||||
|
SoundIoInStream *instream = &is->pub;
|
||||||
|
SoundIoDevice *device = instream->device;
|
||||||
|
|
||||||
|
// All the COM functions are supposed to be called from the same thread. libsoundio API does not
|
||||||
|
// restrict the calling thread context in this way. Furthermore, the user might have called
|
||||||
|
// CoInitializeEx with a different threading model than Single Threaded Apartment.
|
||||||
|
// So we create a thread to do all the initialization and teardown, and communicate state
|
||||||
|
// via conditions and signals. The thread for initialization and teardown is also used
|
||||||
|
// for the realtime code calls the user write_callback.
|
||||||
|
|
||||||
|
isw->is_raw = device->is_raw;
|
||||||
|
|
||||||
|
if (!(isw->cond = soundio_os_cond_create())) {
|
||||||
|
instream_destroy_wasapi(si, is);
|
||||||
|
return SoundIoErrorNoMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(isw->start_cond = soundio_os_cond_create())) {
|
||||||
|
instream_destroy_wasapi(si, is);
|
||||||
|
return SoundIoErrorNoMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(isw->mutex = soundio_os_mutex_create())) {
|
||||||
|
instream_destroy_wasapi(si, is);
|
||||||
|
return SoundIoErrorNoMem;
|
||||||
|
}
|
||||||
|
|
||||||
if (isw->is_raw) {
|
if (isw->is_raw) {
|
||||||
if ((err = soundio_os_thread_create(instream_raw_run, is, true, &isw->thread)))
|
isw->h_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||||
return err;
|
if (!isw->h_event) {
|
||||||
} else {
|
instream_destroy_wasapi(si, is);
|
||||||
if ((err = soundio_os_thread_create(instream_shared_run, is, true, &isw->thread)))
|
return SoundIoErrorOpeningDevice;
|
||||||
return err;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isw->thread_exit_flag.test_and_set();
|
||||||
|
int err;
|
||||||
|
if ((err = soundio_os_thread_create(instream_thread_run, is, true, &isw->thread))) {
|
||||||
|
instream_destroy_wasapi(si, is);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
soundio_os_mutex_lock(isw->mutex);
|
||||||
|
while (!isw->open_complete)
|
||||||
|
soundio_os_cond_wait(isw->cond, isw->mutex);
|
||||||
|
soundio_os_mutex_unlock(isw->mutex);
|
||||||
|
|
||||||
|
if (isw->open_err) {
|
||||||
|
instream_destroy_wasapi(si, is);
|
||||||
|
return isw->open_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int instream_pause_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
|
||||||
|
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
||||||
|
HRESULT hr;
|
||||||
|
if (pause && !isw->is_paused) {
|
||||||
|
if (FAILED(hr = IAudioClient_Stop(isw->audio_client)))
|
||||||
|
return SoundIoErrorStreaming;
|
||||||
|
isw->is_paused = true;
|
||||||
|
} else if (!pause && isw->is_paused) {
|
||||||
|
if (FAILED(hr = IAudioClient_Start(isw->audio_client)))
|
||||||
|
return SoundIoErrorStreaming;
|
||||||
|
isw->is_paused = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int instream_start_wasapi(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
|
||||||
|
SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
|
||||||
|
|
||||||
|
soundio_os_mutex_lock(isw->mutex);
|
||||||
|
isw->started = true;
|
||||||
|
soundio_os_cond_signal(isw->start_cond, isw->mutex);
|
||||||
|
soundio_os_mutex_unlock(isw->mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ struct SoundIoInStreamWasapi {
|
||||||
SoundIoOsThread *thread;
|
SoundIoOsThread *thread;
|
||||||
SoundIoOsMutex *mutex;
|
SoundIoOsMutex *mutex;
|
||||||
SoundIoOsCond *cond;
|
SoundIoOsCond *cond;
|
||||||
|
SoundIoOsCond *start_cond;
|
||||||
atomic_flag thread_exit_flag;
|
atomic_flag thread_exit_flag;
|
||||||
bool is_raw;
|
bool is_raw;
|
||||||
int readable_frame_count;
|
int readable_frame_count;
|
||||||
|
@ -89,6 +90,9 @@ struct SoundIoInStreamWasapi {
|
||||||
int read_frame_count;
|
int read_frame_count;
|
||||||
HANDLE h_event;
|
HANDLE h_event;
|
||||||
bool is_paused;
|
bool is_paused;
|
||||||
|
bool open_complete;
|
||||||
|
int open_err;
|
||||||
|
bool started;
|
||||||
char *read_buf;
|
char *read_buf;
|
||||||
int read_buf_frames_left;
|
int read_buf_frames_left;
|
||||||
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
|
||||||
|
|
Loading…
Reference in a new issue