From 70decb39f5362afc9581980b3d488b449491898a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jul 2015 17:06:12 -0700 Subject: [PATCH] SoundIoOutStream, SoundIoInStream: void * -> union For better cache locality and lower mlock requirements. --- README.md | 2 - src/alsa.cpp | 104 +++++++++++---------------------------------- src/alsa.hpp | 36 ++++++++++++++++ src/dummy.cpp | 74 ++++++-------------------------- src/dummy.hpp | 27 ++++++++++++ src/jack.cpp | 22 ++-------- src/jack.hpp | 11 ++++- src/pulseaudio.cpp | 67 +++++++---------------------- src/pulseaudio.hpp | 16 +++++++ src/soundio.cpp | 4 +- src/soundio.hpp | 34 +++++++++++++-- 11 files changed, 177 insertions(+), 220 deletions(-) diff --git a/README.md b/README.md index 29af981..ea6b037 100644 --- a/README.md +++ b/README.md @@ -280,8 +280,6 @@ view `coverage/index.html` in a browser. 0. Support PulseAudio proplist properties for main context and streams 0. custom allocator support 0. mlock memory which is accessed in the real time path - 0. instead of `void *backend_data` use a union for better cache locality - and smaller mlock requirements 0. Consider testing on FreeBSD 0. make rtprio warning a callback and have existing behavior be the default callback 0. write detailed docs on buffer underflows explaining when they occur, what state diff --git a/src/alsa.cpp b/src/alsa.cpp index 3f89687..3db26b5 100644 --- a/src/alsa.cpp +++ b/src/alsa.cpp @@ -8,7 +8,6 @@ #include "alsa.hpp" #include "soundio.hpp" -#include #include #include @@ -23,39 +22,6 @@ static snd_pcm_access_t prioritized_access_types[] = { }; -struct SoundIoOutStreamAlsa { - snd_pcm_t *handle; - snd_pcm_chmap_t *chmap; - int chmap_size; - snd_pcm_uframes_t offset; - snd_pcm_access_t access; - int sample_buffer_size; - char *sample_buffer; - int poll_fd_count; - struct pollfd *poll_fds; - SoundIoOsThread *thread; - atomic_flag thread_exit_flag; - int period_size; - SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; -}; - -struct SoundIoInStreamAlsa { - snd_pcm_t *handle; - snd_pcm_chmap_t *chmap; - int chmap_size; - snd_pcm_uframes_t offset; - snd_pcm_access_t access; - int sample_buffer_size; - char *sample_buffer; - int poll_fd_count; - struct pollfd *poll_fds; - SoundIoOsThread *thread; - atomic_flag thread_exit_flag; - int period_size; - int read_frame_count; - SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; -}; - static void wakeup_device_poll(SoundIoAlsa *sia) { ssize_t amt = write(sia->notify_pipe_fd[1], "a", 1); if (amt == -1) { @@ -881,9 +847,7 @@ static void wakeup(SoundIoPrivate *si) { } static void outstream_destroy_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { - SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; - if (!osa) - return; + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; if (osa->thread) { osa->thread_exit_flag.clear(); @@ -898,14 +862,11 @@ static void outstream_destroy_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate * deallocate(osa->chmap, osa->chmap_size); deallocate(osa->sample_buffer, osa->sample_buffer_size); - - destroy(osa); - os->backend_data = nullptr; } static int xrun_recovery(SoundIoOutStreamPrivate *os, int err) { SoundIoOutStream *outstream = &os->pub; - SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *)os->backend_data; + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; if (err == -EPIPE) { err = snd_pcm_prepare(osa->handle); if (err >= 0) @@ -924,7 +885,7 @@ static int xrun_recovery(SoundIoOutStreamPrivate *os, int err) { } static int instream_xrun_recovery(SoundIoInStreamPrivate *is, int err) { - SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *)is->backend_data; + SoundIoInStreamAlsa *isa = &is->backend_data.alsa; if (err == -EPIPE) { err = snd_pcm_prepare(isa->handle); } else if (err == -ESTRPIPE) { @@ -977,7 +938,7 @@ static int instream_wait_for_poll(SoundIoInStreamAlsa *isa) { void outstream_thread_run(void *arg) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *) arg; SoundIoOutStream *outstream = &os->pub; - SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; int err; @@ -1046,37 +1007,37 @@ void outstream_thread_run(void *arg) { static void instream_thread_run(void *arg) { SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *) arg; SoundIoInStream *instream = &is->pub; - SoundIoInStreamAlsa *osa = (SoundIoInStreamAlsa *) is->backend_data; + SoundIoInStreamAlsa *isa = &is->backend_data.alsa; int err; for (;;) { - snd_pcm_state_t state = snd_pcm_state(osa->handle); + snd_pcm_state_t state = snd_pcm_state(isa->handle); switch (state) { case SND_PCM_STATE_SETUP: - if ((err = snd_pcm_prepare(osa->handle)) < 0) { + if ((err = snd_pcm_prepare(isa->handle)) < 0) { instream->error_callback(instream, SoundIoErrorStreaming); return; } continue; case SND_PCM_STATE_PREPARED: - if ((err = snd_pcm_start(osa->handle)) < 0) { + if ((err = snd_pcm_start(isa->handle)) < 0) { instream->error_callback(instream, SoundIoErrorStreaming); return; } continue; case SND_PCM_STATE_RUNNING: { - if ((err = instream_wait_for_poll(osa)) < 0) { - if (!osa->thread_exit_flag.test_and_set()) + if ((err = instream_wait_for_poll(isa)) < 0) { + if (!isa->thread_exit_flag.test_and_set()) return; instream->error_callback(instream, SoundIoErrorStreaming); return; } - if (!osa->thread_exit_flag.test_and_set()) + if (!isa->thread_exit_flag.test_and_set()) return; - snd_pcm_sframes_t avail = snd_pcm_avail_update(osa->handle); + snd_pcm_sframes_t avail = snd_pcm_avail_update(isa->handle); if (avail < 0) { if ((err = instream_xrun_recovery(is, avail)) < 0) { instream->error_callback(instream, SoundIoErrorStreaming); @@ -1111,6 +1072,7 @@ static void instream_thread_run(void *arg) { } static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; SoundIoOutStream *outstream = &os->pub; SoundIoDevice *device = outstream->device; @@ -1123,13 +1085,6 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) if (outstream->prebuf_duration == -1.0) outstream->prebuf_duration = outstream->buffer_duration; - SoundIoOutStreamAlsa *osa = create(); - if (!osa) { - outstream_destroy_alsa(si, os); - return SoundIoErrorNoMem; - } - os->backend_data = osa; - int ch_count = outstream->layout.channel_count; osa->chmap_size = sizeof(int) + sizeof(int) * ch_count; @@ -1284,7 +1239,7 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) } static int outstream_start_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { - SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; assert(!osa->thread); @@ -1302,7 +1257,7 @@ int outstream_begin_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, struct SoundIoChannelArea **out_areas, int *frame_count) { *out_areas = nullptr; - SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; SoundIoOutStream *outstream = &os->pub; if (osa->access == SND_PCM_ACCESS_RW_INTERLEAVED) { @@ -1345,7 +1300,7 @@ int outstream_begin_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, } static int outstream_end_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, int frame_count) { - SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; SoundIoOutStream *outstream = &os->pub; snd_pcm_sframes_t commitres; @@ -1373,7 +1328,7 @@ static int outstream_end_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate static int outstream_clear_buffer_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { - SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; int err; if ((err = snd_pcm_reset(osa->handle)) < 0) return SoundIoErrorStreaming; @@ -1381,7 +1336,7 @@ static int outstream_clear_buffer_alsa(SoundIoPrivate *si, } static int outstream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) { - SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; + SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; int err; if ((err = snd_pcm_pause(osa->handle, pause)) < 0) return SoundIoErrorIncompatibleDevice; @@ -1389,9 +1344,7 @@ static int outstream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoOutStre } static void instream_destroy_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { - SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *) is->backend_data; - if (!isa) - return; + SoundIoInStreamAlsa *isa = &is->backend_data.alsa; if (isa->thread) { isa->thread_exit_flag.clear(); @@ -1404,12 +1357,10 @@ static void instream_destroy_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is deallocate(isa->poll_fds, isa->poll_fd_count); deallocate(isa->chmap, isa->chmap_size); deallocate(isa->sample_buffer, isa->sample_buffer_size); - - destroy(isa); - is->backend_data = nullptr; } static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { + SoundIoInStreamAlsa *isa = &is->backend_data.alsa; SoundIoInStream *instream = &is->pub; SoundIoDevice *device = instream->device; @@ -1420,13 +1371,6 @@ static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { instream->buffer_duration / 8.0, device->period_duration_max); } - SoundIoInStreamAlsa *isa = create(); - if (!isa) { - instream_destroy_alsa(si, is); - return SoundIoErrorNoMem; - } - is->backend_data = isa; - int ch_count = instream->layout.channel_count; isa->chmap_size = sizeof(int) + sizeof(int) * ch_count; @@ -1568,7 +1512,7 @@ static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { } static int instream_start_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { - SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *) is->backend_data; + SoundIoInStreamAlsa *isa = &is->backend_data.alsa; assert(!isa->thread); @@ -1586,7 +1530,7 @@ static int instream_begin_read_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count) { *out_areas = nullptr; - SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *) is->backend_data; + SoundIoInStreamAlsa *isa = &is->backend_data.alsa; SoundIoInStream *instream = &is->pub; if (isa->access == SND_PCM_ACCESS_RW_INTERLEAVED) { @@ -1646,7 +1590,7 @@ static int instream_begin_read_alsa(SoundIoPrivate *si, } static int instream_end_read_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { - SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *) is->backend_data; + SoundIoInStreamAlsa *isa = &is->backend_data.alsa; if (isa->access == SND_PCM_ACCESS_RW_INTERLEAVED) { return 0; @@ -1665,7 +1609,7 @@ static int instream_end_read_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is } static int instream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) { - SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *) is->backend_data; + SoundIoInStreamAlsa *isa = &is->backend_data.alsa; int err; if ((err = snd_pcm_pause(isa->handle, pause)) < 0) return SoundIoErrorIncompatibleDevice; diff --git a/src/alsa.hpp b/src/alsa.hpp index 0311d84..b48d4c1 100644 --- a/src/alsa.hpp +++ b/src/alsa.hpp @@ -8,9 +8,12 @@ #ifndef SOUNDIO_ALSA_HPP #define SOUNDIO_ALSA_HPP +#include "soundio.h" #include "os.hpp" #include "atomics.hpp" +#include + int soundio_alsa_init(struct SoundIoPrivate *si); struct SoundIoDeviceAlsa { @@ -32,4 +35,37 @@ struct SoundIoAlsa { struct SoundIoDevicesInfo *ready_devices_info; }; +struct SoundIoOutStreamAlsa { + snd_pcm_t *handle; + snd_pcm_chmap_t *chmap; + int chmap_size; + snd_pcm_uframes_t offset; + snd_pcm_access_t access; + int sample_buffer_size; + char *sample_buffer; + int poll_fd_count; + struct pollfd *poll_fds; + SoundIoOsThread *thread; + atomic_flag thread_exit_flag; + int period_size; + SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; +}; + +struct SoundIoInStreamAlsa { + snd_pcm_t *handle; + snd_pcm_chmap_t *chmap; + int chmap_size; + snd_pcm_uframes_t offset; + snd_pcm_access_t access; + int sample_buffer_size; + char *sample_buffer; + int poll_fd_count; + struct pollfd *poll_fds; + SoundIoOsThread *thread; + atomic_flag thread_exit_flag; + int period_size; + int read_frame_count; + SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; +}; + #endif diff --git a/src/dummy.cpp b/src/dummy.cpp index 9cad6b6..7cc9333 100644 --- a/src/dummy.cpp +++ b/src/dummy.cpp @@ -7,41 +7,15 @@ #include "dummy.hpp" #include "soundio.hpp" -#include "atomics.hpp" -#include "ring_buffer.hpp" #include #include #include -struct SoundIoOutStreamDummy { - struct SoundIoOsThread *thread; - struct SoundIoOsCond *cond; - atomic_flag abort_flag; - int buffer_frame_count; - struct SoundIoRingBuffer ring_buffer; - int prebuf_frame_count; - int prebuf_frames_left; - long frames_consumed; - double playback_start_time; - SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; -}; - -struct SoundIoInStreamDummy { - struct SoundIoOsThread *thread; - struct SoundIoOsCond *cond; - atomic_flag abort_flag; - int read_frame_count; - int buffer_frame_count; - struct SoundIoRingBuffer ring_buffer; - int hole_size; - SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; -}; - static void playback_thread_run(void *arg) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg; SoundIoOutStream *outstream = &os->pub; - SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; + SoundIoOutStreamDummy *osd = &os->backend_data.dummy; double start_time = soundio_os_get_time(); osd->playback_start_time = start_time; @@ -90,7 +64,7 @@ static void playback_thread_run(void *arg) { static void capture_thread_run(void *arg) { SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg; SoundIoInStream *instream = &is->pub; - SoundIoInStreamDummy *isd = (SoundIoInStreamDummy *)is->backend_data; + SoundIoInStreamDummy *isd = &is->backend_data.dummy; long frames_consumed = 0; double start_time = soundio_os_get_time(); @@ -150,9 +124,7 @@ static void wakeup(SoundIoPrivate *si) { } static void outstream_destroy_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { - SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; - if (!osd) - return; + SoundIoOutStreamDummy *osd = &os->backend_data.dummy; if (osd->thread) { osd->abort_flag.clear(); @@ -164,12 +136,10 @@ static void outstream_destroy_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate osd->cond = nullptr; soundio_ring_buffer_deinit(&osd->ring_buffer); - - destroy(osd); - os->backend_data = nullptr; } static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { + SoundIoOutStreamDummy *osd = &os->backend_data.dummy; SoundIoOutStream *outstream = &os->pub; SoundIoDevice *device = outstream->device; @@ -180,13 +150,6 @@ static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) outstream->buffer_duration / 2.0, device->period_duration_max); } - SoundIoOutStreamDummy *osd = create(); - if (!osd) { - outstream_destroy_dummy(si, os); - return SoundIoErrorNoMem; - } - os->backend_data = osd; - int err; int buffer_size = outstream->bytes_per_frame * outstream->sample_rate * outstream->buffer_duration; if ((err = soundio_ring_buffer_init(&osd->ring_buffer, buffer_size))) { @@ -212,7 +175,7 @@ static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) } static int outstream_pause_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) { - SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; + SoundIoOutStreamDummy *osd = &os->backend_data.dummy; if (pause) { if (osd->thread) { osd->abort_flag.clear(); @@ -242,7 +205,7 @@ static int outstream_begin_write_dummy(SoundIoPrivate *si, *out_areas = nullptr; SoundIoOutStream *outstream = &os->pub; - SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; + SoundIoOutStreamDummy *osd = &os->backend_data.dummy; assert(*frame_count >= 0); assert(*frame_count <= osd->buffer_frame_count); @@ -264,7 +227,7 @@ static int outstream_begin_write_dummy(SoundIoPrivate *si, } static int outstream_end_write_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, int frame_count) { - SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; + SoundIoOutStreamDummy *osd = &os->backend_data.dummy; SoundIoOutStream *outstream = &os->pub; int byte_count = frame_count * outstream->bytes_per_frame; soundio_ring_buffer_advance_write_ptr(&osd->ring_buffer, byte_count); @@ -279,16 +242,14 @@ static int outstream_end_write_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate } static int outstream_clear_buffer_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { - SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; + SoundIoOutStreamDummy *osd = &os->backend_data.dummy; soundio_ring_buffer_clear(&osd->ring_buffer); osd->prebuf_frames_left = osd->prebuf_frame_count; return 0; } static void instream_destroy_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { - SoundIoInStreamDummy *isd = (SoundIoInStreamDummy *)is->backend_data; - if (!isd) - return; + SoundIoInStreamDummy *isd = &is->backend_data.dummy; if (isd->thread) { isd->abort_flag.clear(); @@ -300,12 +261,10 @@ static void instream_destroy_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *i isd->cond = nullptr; soundio_ring_buffer_deinit(&isd->ring_buffer); - - destroy(isd); - is->backend_data = nullptr; } static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { + SoundIoInStreamDummy *isd = &is->backend_data.dummy; SoundIoInStream *instream = &is->pub; SoundIoDevice *device = instream->device; @@ -316,13 +275,6 @@ static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { instream->buffer_duration / 8.0, instream->device->period_duration_max); } - SoundIoInStreamDummy *isd = create(); - if (!isd) { - instream_destroy_dummy(si, is); - return SoundIoErrorNoMem; - } - is->backend_data = isd; - int err; int buffer_size = instream->bytes_per_frame * instream->sample_rate * instream->buffer_duration; if ((err = soundio_ring_buffer_init(&isd->ring_buffer, buffer_size))) { @@ -344,7 +296,7 @@ static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { } static int instream_pause_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is, bool pause) { - SoundIoInStreamDummy *isd = (SoundIoInStreamDummy *)is->backend_data; + SoundIoInStreamDummy *isd = &is->backend_data.dummy; if (pause) { if (isd->thread) { isd->abort_flag.clear(); @@ -372,7 +324,7 @@ static int instream_begin_read_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count) { SoundIoInStream *instream = &is->pub; - SoundIoInStreamDummy *isd = (SoundIoInStreamDummy *)is->backend_data; + SoundIoInStreamDummy *isd = &is->backend_data.dummy; assert(*frame_count >= 0); assert(*frame_count <= isd->buffer_frame_count); @@ -403,7 +355,7 @@ static int instream_begin_read_dummy(SoundIoPrivate *si, } static int instream_end_read_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { - SoundIoInStreamDummy *isd = (SoundIoInStreamDummy *)is->backend_data; + SoundIoInStreamDummy *isd = &is->backend_data.dummy; SoundIoInStream *instream = &is->pub; if (isd->hole_size > 0) { diff --git a/src/dummy.hpp b/src/dummy.hpp index f10827d..c1f2aae 100644 --- a/src/dummy.hpp +++ b/src/dummy.hpp @@ -8,7 +8,10 @@ #ifndef SOUNDIO_DUMMY_HPP #define SOUNDIO_DUMMY_HPP +#include "soundio.h" #include "os.hpp" +#include "atomics.hpp" +#include "ring_buffer.hpp" int soundio_dummy_init(struct SoundIoPrivate *si); @@ -22,4 +25,28 @@ struct SoundIoDeviceDummy { }; +struct SoundIoOutStreamDummy { + struct SoundIoOsThread *thread; + struct SoundIoOsCond *cond; + atomic_flag abort_flag; + int buffer_frame_count; + struct SoundIoRingBuffer ring_buffer; + int prebuf_frame_count; + int prebuf_frames_left; + long frames_consumed; + double playback_start_time; + SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; +}; + +struct SoundIoInStreamDummy { + struct SoundIoOsThread *thread; + struct SoundIoOsCond *cond; + atomic_flag abort_flag; + int read_frame_count; + int buffer_frame_count; + struct SoundIoRingBuffer ring_buffer; + int hole_size; + SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; +}; + #endif diff --git a/src/jack.cpp b/src/jack.cpp index fdfbcd3..62f6c1b 100644 --- a/src/jack.cpp +++ b/src/jack.cpp @@ -14,11 +14,6 @@ static atomic_flag global_msg_callback_flag = ATOMIC_FLAG_INIT; -struct SoundIoOutStreamJack { - jack_client_t *client; - jack_port_t *ports[SOUNDIO_MAX_CHANNELS]; -}; - struct SoundIoJackPort { const char *name; int name_len; @@ -80,17 +75,13 @@ static int outstream_process_callback(jack_nframes_t nframes, void *arg) { } static void outstream_destroy_jack(struct SoundIoPrivate *is, struct SoundIoOutStreamPrivate *os) { - SoundIoOutStreamJack *osj = (SoundIoOutStreamJack *) os->backend_data; - if (!osj) - return; + SoundIoOutStreamJack *osj = &os->backend_data.jack; jack_client_close(osj->client); - - destroy(osj); - os->backend_data = nullptr; } static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) { + SoundIoOutStreamJack *osj = &os->backend_data.jack; SoundIoOutStream *outstream = &os->pub; //TODO SoundIoDevice *device = outstream->device; @@ -98,13 +89,6 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea outstream->period_duration = 0.0; // TODO outstream->prebuf_duration = 0.0; // TODO - SoundIoOutStreamJack *osj = create(); - if (!osj) { - outstream_destroy_jack(si, os); - return SoundIoErrorNoMem; - } - os->backend_data = osj; - outstream->layout_error = SoundIoErrorIncompatibleBackend; jack_status_t status; @@ -145,7 +129,7 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea } static int outstream_pause_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) { - SoundIoOutStreamJack *osj = (SoundIoOutStreamJack *) os->backend_data; + SoundIoOutStreamJack *osj = &os->backend_data.jack; SoundIoOutStream *outstream = &os->pub; int err; if (pause) { diff --git a/src/jack.hpp b/src/jack.hpp index 52a8f97..12fa167 100644 --- a/src/jack.hpp +++ b/src/jack.hpp @@ -8,6 +8,7 @@ #ifndef SOUNDIO_JACK_HPP #define SOUNDIO_JACK_HPP +#include "soundio.h" #include "os.hpp" #include @@ -29,5 +30,13 @@ struct SoundIoJack { int buffer_size; }; -#endif +struct SoundIoOutStreamJack { + jack_client_t *client; + jack_port_t *ports[SOUNDIO_MAX_CHANNELS]; +}; +struct SoundIoInStreamJack { + +}; + +#endif diff --git a/src/pulseaudio.cpp b/src/pulseaudio.cpp index 84e82e4..c7cd5b3 100644 --- a/src/pulseaudio.cpp +++ b/src/pulseaudio.cpp @@ -13,21 +13,6 @@ #include -struct SoundIoOutStreamPulseAudio { - pa_stream *stream; - atomic_bool stream_ready; - pa_buffer_attr buffer_attr; - char *write_ptr; - SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; -}; - -struct SoundIoInStreamPulseAudio { - pa_stream *stream; - atomic_bool stream_ready; - pa_buffer_attr buffer_attr; - SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; -}; - static void subscribe_callback(pa_context *context, pa_subscription_event_type_t event_bits, uint32_t index, void *userdata) { @@ -570,7 +555,7 @@ static void playback_stream_state_callback(pa_stream *stream, void *userdata) { SoundIo *soundio = outstream->device->soundio; SoundIoPrivate *si = (SoundIoPrivate *)soundio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; - SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; + SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; switch (pa_stream_get_state(stream)) { case PA_STREAM_UNCONNECTED: case PA_STREAM_CREATING: @@ -598,9 +583,7 @@ static void playback_stream_write_callback(pa_stream *stream, size_t nbytes, voi } static void outstream_destroy_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { - SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; - if (!ospa) - return; + SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; pa_stream *stream = ospa->stream; @@ -618,21 +601,12 @@ static void outstream_destroy_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os ospa->stream = nullptr; } - - destroy(ospa); - os->backend_data = nullptr; } static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { + SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; SoundIoOutStream *outstream = &os->pub; - SoundIoOutStreamPulseAudio *ospa = create(); - if (!ospa) { - outstream_destroy_pa(si, os); - return SoundIoErrorNoMem; - } - os->backend_data = ospa; - SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; ospa->stream_ready = false; @@ -686,7 +660,7 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { static int outstream_start_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { SoundIoOutStream *outstream = &os->pub; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; - SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; + SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; pa_threaded_mainloop_lock(sipa->main_loop); @@ -720,7 +694,7 @@ static int outstream_begin_write_pa(SoundIoPrivate *si, *out_areas = nullptr; SoundIoOutStream *outstream = &os->pub; - SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; + SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; pa_stream *stream = ospa->stream; size_t byte_count = *frame_count * outstream->bytes_per_frame; if (pa_stream_begin_write(stream, (void**)&ospa->write_ptr, &byte_count)) @@ -739,7 +713,7 @@ static int outstream_begin_write_pa(SoundIoPrivate *si, static int outstream_end_write_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, int frame_count) { SoundIoOutStream *outstream = &os->pub; - SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; + SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; pa_stream *stream = ospa->stream; assert(frame_count > 0); size_t byte_count = frame_count * outstream->bytes_per_frame; @@ -752,7 +726,7 @@ static int outstream_end_write_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *o static int outstream_clear_buffer_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { - SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; + SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; pa_stream *stream = ospa->stream; pa_threaded_mainloop_lock(sipa->main_loop); @@ -765,7 +739,7 @@ static int outstream_clear_buffer_pa(SoundIoPrivate *si, } static int outstream_pause_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, bool pause) { - SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; + SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; pa_threaded_mainloop_lock(sipa->main_loop); @@ -784,7 +758,7 @@ static int outstream_pause_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, b static void recording_stream_state_callback(pa_stream *stream, void *userdata) { SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate*)userdata; - SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)is->backend_data; + SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio; SoundIoInStream *instream = &is->pub; SoundIo *soundio = instream->device->soundio; SoundIoPrivate *si = (SoundIoPrivate *)soundio; @@ -814,11 +788,8 @@ static void recording_stream_read_callback(pa_stream *stream, size_t nbytes, voi instream->read_callback(instream, available_frame_count); } -static void instream_destroy_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *instream) { - SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)instream->backend_data; - if (!ispa) - return; - +static void instream_destroy_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { + SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; pa_stream *stream = ispa->stream; if (stream) { @@ -836,15 +807,9 @@ static void instream_destroy_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *inst } static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { + SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio; SoundIoInStream *instream = &is->pub; - SoundIoInStreamPulseAudio *ispa = create(); - if (!ispa) { - instream_destroy_pa(si, is); - return SoundIoErrorNoMem; - } - is->backend_data = ispa; - SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; ispa->stream_ready = false; @@ -889,7 +854,7 @@ static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { static int instream_start_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { SoundIoInStream *instream = &is->pub; - SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)is->backend_data; + SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; pa_threaded_mainloop_lock(sipa->main_loop); @@ -918,7 +883,7 @@ static int instream_begin_read_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count) { SoundIoInStream *instream = &is->pub; - SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)is->backend_data; + SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio; pa_stream *stream = ispa->stream; assert(ispa->stream_ready); @@ -948,7 +913,7 @@ static int instream_begin_read_pa(SoundIoPrivate *si, } static int instream_end_read_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { - SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)is->backend_data; + SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio; pa_stream *stream = ispa->stream; if (pa_stream_drop(stream)) return SoundIoErrorStreaming; @@ -957,7 +922,7 @@ static int instream_end_read_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) } static int instream_pause_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, bool pause) { - SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)is->backend_data; + SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; pa_threaded_mainloop_lock(sipa->main_loop); diff --git a/src/pulseaudio.hpp b/src/pulseaudio.hpp index 986fe07..03953fd 100644 --- a/src/pulseaudio.hpp +++ b/src/pulseaudio.hpp @@ -8,6 +8,7 @@ #ifndef SOUNDIO_PULSEAUDIO_HPP #define SOUNDIO_PULSEAUDIO_HPP +#include "soundio.h" #include "atomics.hpp" #include @@ -43,4 +44,19 @@ struct SoundIoPulseAudio { pa_proplist *props; }; +struct SoundIoOutStreamPulseAudio { + pa_stream *stream; + atomic_bool stream_ready; + pa_buffer_attr buffer_attr; + char *write_ptr; + SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; +}; + +struct SoundIoInStreamPulseAudio { + pa_stream *stream; + atomic_bool stream_ready; + pa_buffer_attr buffer_attr; + SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS]; +}; + #endif diff --git a/src/soundio.cpp b/src/soundio.cpp index d89875f..9202d57 100644 --- a/src/soundio.cpp +++ b/src/soundio.cpp @@ -186,8 +186,6 @@ int soundio_connect_backend(SoundIo *soundio, SoundIoBackend backend) { if (!fn) return SoundIoErrorBackendUnavailable; - memset(&si->backend_data, 0, sizeof(SoundIoBackendData)); - int err; if ((err = backend_init_fns[backend](si))) { soundio_disconnect(soundio); @@ -201,10 +199,12 @@ void soundio_disconnect(struct SoundIo *soundio) { if (si->destroy) si->destroy(si); + memset(&si->backend_data, 0, sizeof(SoundIoBackendData)); soundio->current_backend = SoundIoBackendNone; soundio_destroy_devices_info(si->safe_devices_info); + si->safe_devices_info = nullptr; si->destroy = nullptr; diff --git a/src/soundio.hpp b/src/soundio.hpp index 9c545a0..4b4bb85 100644 --- a/src/soundio.hpp +++ b/src/soundio.hpp @@ -51,6 +51,32 @@ union SoundIoDeviceBackendData { SoundIoDeviceDummy dummy; }; +union SoundIoOutStreamBackendData { +#ifdef SOUNDIO_HAVE_JACK + SoundIoOutStreamJack jack; +#endif +#ifdef SOUNDIO_HAVE_PULSEAUDIO + SoundIoOutStreamPulseAudio pulseaudio; +#endif +#ifdef SOUNDIO_HAVE_ALSA + SoundIoOutStreamAlsa alsa; +#endif + SoundIoOutStreamDummy dummy; +}; + +union SoundIoInStreamBackendData { +#ifdef SOUNDIO_HAVE_JACK + SoundIoInStreamJack jack; +#endif +#ifdef SOUNDIO_HAVE_PULSEAUDIO + SoundIoInStreamPulseAudio pulseaudio; +#endif +#ifdef SOUNDIO_HAVE_ALSA + SoundIoInStreamAlsa alsa; +#endif + SoundIoInStreamDummy dummy; +}; + struct SoundIoDevicesInfo { SoundIoList input_devices; SoundIoList output_devices; @@ -60,13 +86,13 @@ struct SoundIoDevicesInfo { }; struct SoundIoOutStreamPrivate { - struct SoundIoOutStream pub; - void *backend_data; + SoundIoOutStream pub; + SoundIoOutStreamBackendData backend_data; }; struct SoundIoInStreamPrivate { - struct SoundIoInStream pub; - void *backend_data; + SoundIoInStream pub; + SoundIoInStreamBackendData backend_data; }; struct SoundIoPrivate {