mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2025-01-03 17:15:47 +00:00
parent
c88e79cb7b
commit
c14d61fa32
|
@ -186,6 +186,11 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"'p\\n' - pause\n"
|
||||
"'u\\n' - unpause\n"
|
||||
"'c\\n' - clear buffer\n"
|
||||
"'q\\n' - quit\n");
|
||||
fprintf(stderr, "Output device: %s\n", device->name);
|
||||
|
||||
if (device->probe_error) {
|
||||
|
|
|
@ -973,12 +973,17 @@ SOUNDIO_EXPORT int soundio_outstream_end_write(struct SoundIoOutStream *outstrea
|
|||
|
||||
/// Clears the output stream buffer.
|
||||
/// This function can be called from any thread.
|
||||
/// This function can be called regardless of whether the outstream is paused
|
||||
/// or not.
|
||||
/// Some backends do not support clearing the buffer. On these backends this
|
||||
/// function will return SoundIoErrorIncompatibleBackend.
|
||||
/// Some devices do not support clearing the buffer. On these devices this
|
||||
/// function might return SoundIoErrorIncompatibleDevice.
|
||||
/// Possible errors:
|
||||
///
|
||||
/// * #SoundIoErrorStreaming
|
||||
/// * #SoundIoErrorIncompatibleBackend
|
||||
/// * #SoundIoErrorIncompatibleDevice
|
||||
SOUNDIO_EXPORT int soundio_outstream_clear_buffer(struct SoundIoOutStream *outstream);
|
||||
|
||||
/// If the underlying device supports pausing, this pauses the stream.
|
||||
|
|
|
@ -1138,6 +1138,7 @@ static void instream_thread_run(void *arg) {
|
|||
}
|
||||
continue;
|
||||
case SND_PCM_STATE_RUNNING:
|
||||
case SND_PCM_STATE_PAUSED:
|
||||
{
|
||||
if ((err = instream_wait_for_poll(is)) < 0) {
|
||||
if (!isa->thread_exit_flag.test_and_set())
|
||||
|
@ -1176,7 +1177,6 @@ static void instream_thread_run(void *arg) {
|
|||
continue;
|
||||
case SND_PCM_STATE_OPEN:
|
||||
case SND_PCM_STATE_DRAINING:
|
||||
case SND_PCM_STATE_PAUSED:
|
||||
case SND_PCM_STATE_DISCONNECTED:
|
||||
instream->error_callback(instream, SoundIoErrorStreaming);
|
||||
return;
|
||||
|
|
|
@ -1246,6 +1246,38 @@ void outstream_shared_run(SoundIoOutStreamPrivate *os) {
|
|||
return;
|
||||
}
|
||||
soundio_os_mutex_unlock(osw->mutex);
|
||||
bool reset_buffer = false;
|
||||
if (!osw->clear_buffer_flag.test_and_set()) {
|
||||
if (!osw->is_paused) {
|
||||
if (FAILED(hr = IAudioClient_Stop(osw->audio_client))) {
|
||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||
return;
|
||||
}
|
||||
osw->is_paused = true;
|
||||
}
|
||||
if (FAILED(hr = IAudioClient_Reset(osw->audio_client))) {
|
||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||
return;
|
||||
}
|
||||
osw->pause_resume_flag.clear();
|
||||
reset_buffer = true;
|
||||
}
|
||||
if (!osw->pause_resume_flag.test_and_set()) {
|
||||
bool pause = osw->desired_pause_state.load();
|
||||
if (pause && !osw->is_paused) {
|
||||
if (FAILED(hr = IAudioClient_Stop(osw->audio_client))) {
|
||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||
return;
|
||||
}
|
||||
osw->is_paused = true;
|
||||
} else if (!pause && osw->is_paused) {
|
||||
if (FAILED(hr = IAudioClient_Start(osw->audio_client))) {
|
||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||
return;
|
||||
}
|
||||
osw->is_paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr = IAudioClient_GetCurrentPadding(osw->audio_client, &frames_used))) {
|
||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||
|
@ -1253,7 +1285,7 @@ void outstream_shared_run(SoundIoOutStreamPrivate *os) {
|
|||
}
|
||||
osw->writable_frame_count = osw->buffer_frame_count - frames_used;
|
||||
if (osw->writable_frame_count > 0) {
|
||||
if (frames_used == 0)
|
||||
if (frames_used == 0 && !reset_buffer)
|
||||
outstream->underflow_callback(outstream);
|
||||
outstream->write_callback(outstream, 0, osw->writable_frame_count);
|
||||
}
|
||||
|
@ -1277,6 +1309,22 @@ void outstream_raw_run(SoundIoOutStreamPrivate *os) {
|
|||
WaitForSingleObject(osw->h_event, INFINITE);
|
||||
if (!osw->thread_exit_flag.test_and_set())
|
||||
return;
|
||||
if (!osw->pause_resume_flag.test_and_set()) {
|
||||
bool pause = osw->desired_pause_state.load();
|
||||
if (pause && !osw->is_paused) {
|
||||
if (FAILED(hr = IAudioClient_Stop(osw->audio_client))) {
|
||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||
return;
|
||||
}
|
||||
osw->is_paused = true;
|
||||
} else if (!pause && osw->is_paused) {
|
||||
if (FAILED(hr = IAudioClient_Start(osw->audio_client))) {
|
||||
outstream->error_callback(outstream, SoundIoErrorStreaming);
|
||||
return;
|
||||
}
|
||||
osw->is_paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
outstream->write_callback(outstream, osw->buffer_frame_count, osw->buffer_frame_count);
|
||||
}
|
||||
|
@ -1331,6 +1379,10 @@ static int outstream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStr
|
|||
SoundIoDevice *device = outstream->device;
|
||||
SoundIo *soundio = &si->pub;
|
||||
|
||||
osw->pause_resume_flag.test_and_set();
|
||||
osw->clear_buffer_flag.test_and_set();
|
||||
osw->desired_pause_state.store(false);
|
||||
|
||||
// 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.
|
||||
|
@ -1385,19 +1437,19 @@ static int outstream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStr
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int outstream_pause_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
|
||||
SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
|
||||
HRESULT hr;
|
||||
if (pause && !osw->is_paused) {
|
||||
if (FAILED(hr = IAudioClient_Stop(osw->audio_client)))
|
||||
return SoundIoErrorStreaming;
|
||||
osw->is_paused = true;
|
||||
} else if (!pause && osw->is_paused) {
|
||||
if (FAILED(hr = IAudioClient_Start(osw->audio_client)))
|
||||
return SoundIoErrorStreaming;
|
||||
osw->is_paused = false;
|
||||
|
||||
osw->desired_pause_state.store(pause);
|
||||
osw->pause_resume_flag.clear();
|
||||
if (osw->h_event) {
|
||||
SetEvent(osw->h_event);
|
||||
} else {
|
||||
soundio_os_mutex_lock(osw->mutex);
|
||||
soundio_os_cond_signal(osw->cond, osw->mutex);
|
||||
soundio_os_mutex_unlock(osw->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1450,9 +1502,15 @@ static int outstream_end_write_wasapi(struct SoundIoPrivate *si, struct SoundIoO
|
|||
|
||||
static int outstream_clear_buffer_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
|
||||
SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = IAudioClient_Reset(osw->audio_client)))
|
||||
return SoundIoErrorStreaming;
|
||||
|
||||
if (osw->h_event) {
|
||||
return SoundIoErrorIncompatibleDevice;
|
||||
} else {
|
||||
osw->clear_buffer_flag.clear();
|
||||
soundio_os_mutex_lock(osw->mutex);
|
||||
soundio_os_cond_signal(osw->cond, osw->mutex);
|
||||
soundio_os_mutex_unlock(osw->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -67,6 +67,9 @@ struct SoundIoOutStreamWasapi {
|
|||
UINT32 buffer_frame_count;
|
||||
int write_frame_count;
|
||||
HANDLE h_event;
|
||||
atomic_bool desired_pause_state;
|
||||
atomic_flag pause_resume_flag;
|
||||
atomic_flag clear_buffer_flag;
|
||||
bool is_paused;
|
||||
bool open_complete;
|
||||
int open_err;
|
||||
|
|
Loading…
Reference in a new issue