SoundIoOutStream, SoundIoInStream: void * -> union

For better cache locality and lower mlock requirements.
This commit is contained in:
Andrew Kelley 2015-07-27 17:06:12 -07:00
parent db1195877a
commit 70decb39f5
11 changed files with 177 additions and 220 deletions

View file

@ -280,8 +280,6 @@ view `coverage/index.html` in a browser.
0. Support PulseAudio proplist properties for main context and streams 0. Support PulseAudio proplist properties for main context and streams
0. custom allocator support 0. custom allocator support
0. mlock memory which is accessed in the real time path 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. Consider testing on FreeBSD
0. make rtprio warning a callback and have existing behavior be the default callback 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 0. write detailed docs on buffer underflows explaining when they occur, what state

View file

@ -8,7 +8,6 @@
#include "alsa.hpp" #include "alsa.hpp"
#include "soundio.hpp" #include "soundio.hpp"
#include <alsa/asoundlib.h>
#include <sys/inotify.h> #include <sys/inotify.h>
#include <math.h> #include <math.h>
@ -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) { static void wakeup_device_poll(SoundIoAlsa *sia) {
ssize_t amt = write(sia->notify_pipe_fd[1], "a", 1); ssize_t amt = write(sia->notify_pipe_fd[1], "a", 1);
if (amt == -1) { if (amt == -1) {
@ -881,9 +847,7 @@ static void wakeup(SoundIoPrivate *si) {
} }
static void outstream_destroy_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { static void outstream_destroy_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
if (!osa)
return;
if (osa->thread) { if (osa->thread) {
osa->thread_exit_flag.clear(); 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->chmap, osa->chmap_size);
deallocate(osa->sample_buffer, osa->sample_buffer_size); deallocate(osa->sample_buffer, osa->sample_buffer_size);
destroy(osa);
os->backend_data = nullptr;
} }
static int xrun_recovery(SoundIoOutStreamPrivate *os, int err) { static int xrun_recovery(SoundIoOutStreamPrivate *os, int err) {
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *)os->backend_data; SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
if (err == -EPIPE) { if (err == -EPIPE) {
err = snd_pcm_prepare(osa->handle); err = snd_pcm_prepare(osa->handle);
if (err >= 0) if (err >= 0)
@ -924,7 +885,7 @@ static int xrun_recovery(SoundIoOutStreamPrivate *os, int err) {
} }
static int instream_xrun_recovery(SoundIoInStreamPrivate *is, 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) { if (err == -EPIPE) {
err = snd_pcm_prepare(isa->handle); err = snd_pcm_prepare(isa->handle);
} else if (err == -ESTRPIPE) { } else if (err == -ESTRPIPE) {
@ -977,7 +938,7 @@ static int instream_wait_for_poll(SoundIoInStreamAlsa *isa) {
void outstream_thread_run(void *arg) { void outstream_thread_run(void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *) arg; SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *) arg;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
int err; int err;
@ -1046,37 +1007,37 @@ void outstream_thread_run(void *arg) {
static void instream_thread_run(void *arg) { static void instream_thread_run(void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *) arg; SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *) arg;
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIoInStreamAlsa *osa = (SoundIoInStreamAlsa *) is->backend_data; SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
int err; int err;
for (;;) { for (;;) {
snd_pcm_state_t state = snd_pcm_state(osa->handle); snd_pcm_state_t state = snd_pcm_state(isa->handle);
switch (state) { switch (state) {
case SND_PCM_STATE_SETUP: 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); instream->error_callback(instream, SoundIoErrorStreaming);
return; return;
} }
continue; continue;
case SND_PCM_STATE_PREPARED: 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); instream->error_callback(instream, SoundIoErrorStreaming);
return; return;
} }
continue; continue;
case SND_PCM_STATE_RUNNING: case SND_PCM_STATE_RUNNING:
{ {
if ((err = instream_wait_for_poll(osa)) < 0) { if ((err = instream_wait_for_poll(isa)) < 0) {
if (!osa->thread_exit_flag.test_and_set()) if (!isa->thread_exit_flag.test_and_set())
return; return;
instream->error_callback(instream, SoundIoErrorStreaming); instream->error_callback(instream, SoundIoErrorStreaming);
return; return;
} }
if (!osa->thread_exit_flag.test_and_set()) if (!isa->thread_exit_flag.test_and_set())
return; 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 (avail < 0) {
if ((err = instream_xrun_recovery(is, avail)) < 0) { if ((err = instream_xrun_recovery(is, avail)) < 0) {
instream->error_callback(instream, SoundIoErrorStreaming); 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) { static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoDevice *device = outstream->device; SoundIoDevice *device = outstream->device;
@ -1123,13 +1085,6 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
if (outstream->prebuf_duration == -1.0) if (outstream->prebuf_duration == -1.0)
outstream->prebuf_duration = outstream->buffer_duration; outstream->prebuf_duration = outstream->buffer_duration;
SoundIoOutStreamAlsa *osa = create<SoundIoOutStreamAlsa>();
if (!osa) {
outstream_destroy_alsa(si, os);
return SoundIoErrorNoMem;
}
os->backend_data = osa;
int ch_count = outstream->layout.channel_count; int ch_count = outstream->layout.channel_count;
osa->chmap_size = sizeof(int) + sizeof(int) * ch_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) { static int outstream_start_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
assert(!osa->thread); assert(!osa->thread);
@ -1302,7 +1257,7 @@ int outstream_begin_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os,
struct SoundIoChannelArea **out_areas, int *frame_count) struct SoundIoChannelArea **out_areas, int *frame_count)
{ {
*out_areas = nullptr; *out_areas = nullptr;
SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
if (osa->access == SND_PCM_ACCESS_RW_INTERLEAVED) { 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) { 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; SoundIoOutStream *outstream = &os->pub;
snd_pcm_sframes_t commitres; 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, static int outstream_clear_buffer_alsa(SoundIoPrivate *si,
SoundIoOutStreamPrivate *os) SoundIoOutStreamPrivate *os)
{ {
SoundIoOutStreamAlsa *osa = (SoundIoOutStreamAlsa *) os->backend_data; SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
int err; int err;
if ((err = snd_pcm_reset(osa->handle)) < 0) if ((err = snd_pcm_reset(osa->handle)) < 0)
return SoundIoErrorStreaming; 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) { 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; int err;
if ((err = snd_pcm_pause(osa->handle, pause)) < 0) if ((err = snd_pcm_pause(osa->handle, pause)) < 0)
return SoundIoErrorIncompatibleDevice; 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) { static void instream_destroy_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *) is->backend_data; SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
if (!isa)
return;
if (isa->thread) { if (isa->thread) {
isa->thread_exit_flag.clear(); 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->poll_fds, isa->poll_fd_count);
deallocate(isa->chmap, isa->chmap_size); deallocate(isa->chmap, isa->chmap_size);
deallocate(isa->sample_buffer, isa->sample_buffer_size); deallocate(isa->sample_buffer, isa->sample_buffer_size);
destroy(isa);
is->backend_data = nullptr;
} }
static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIoDevice *device = instream->device; 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); instream->buffer_duration / 8.0, device->period_duration_max);
} }
SoundIoInStreamAlsa *isa = create<SoundIoInStreamAlsa>();
if (!isa) {
instream_destroy_alsa(si, is);
return SoundIoErrorNoMem;
}
is->backend_data = isa;
int ch_count = instream->layout.channel_count; int ch_count = instream->layout.channel_count;
isa->chmap_size = sizeof(int) + sizeof(int) * ch_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) { static int instream_start_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *) is->backend_data; SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
assert(!isa->thread); assert(!isa->thread);
@ -1586,7 +1530,7 @@ static int instream_begin_read_alsa(SoundIoPrivate *si,
SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count) SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count)
{ {
*out_areas = nullptr; *out_areas = nullptr;
SoundIoInStreamAlsa *isa = (SoundIoInStreamAlsa *) is->backend_data; SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
if (isa->access == SND_PCM_ACCESS_RW_INTERLEAVED) { 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) { 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) { if (isa->access == SND_PCM_ACCESS_RW_INTERLEAVED) {
return 0; 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) { 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; int err;
if ((err = snd_pcm_pause(isa->handle, pause)) < 0) if ((err = snd_pcm_pause(isa->handle, pause)) < 0)
return SoundIoErrorIncompatibleDevice; return SoundIoErrorIncompatibleDevice;

View file

@ -8,9 +8,12 @@
#ifndef SOUNDIO_ALSA_HPP #ifndef SOUNDIO_ALSA_HPP
#define SOUNDIO_ALSA_HPP #define SOUNDIO_ALSA_HPP
#include "soundio.h"
#include "os.hpp" #include "os.hpp"
#include "atomics.hpp" #include "atomics.hpp"
#include <alsa/asoundlib.h>
int soundio_alsa_init(struct SoundIoPrivate *si); int soundio_alsa_init(struct SoundIoPrivate *si);
struct SoundIoDeviceAlsa { struct SoundIoDeviceAlsa {
@ -32,4 +35,37 @@ struct SoundIoAlsa {
struct SoundIoDevicesInfo *ready_devices_info; 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 #endif

View file

@ -7,41 +7,15 @@
#include "dummy.hpp" #include "dummy.hpp"
#include "soundio.hpp" #include "soundio.hpp"
#include "atomics.hpp"
#include "ring_buffer.hpp"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
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) { static void playback_thread_run(void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg; SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
double start_time = soundio_os_get_time(); double start_time = soundio_os_get_time();
osd->playback_start_time = start_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) { static void capture_thread_run(void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg; SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg;
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIoInStreamDummy *isd = (SoundIoInStreamDummy *)is->backend_data; SoundIoInStreamDummy *isd = &is->backend_data.dummy;
long frames_consumed = 0; long frames_consumed = 0;
double start_time = soundio_os_get_time(); 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) { static void outstream_destroy_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
if (!osd)
return;
if (osd->thread) { if (osd->thread) {
osd->abort_flag.clear(); osd->abort_flag.clear();
@ -164,12 +136,10 @@ static void outstream_destroy_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate
osd->cond = nullptr; osd->cond = nullptr;
soundio_ring_buffer_deinit(&osd->ring_buffer); soundio_ring_buffer_deinit(&osd->ring_buffer);
destroy(osd);
os->backend_data = nullptr;
} }
static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoDevice *device = outstream->device; 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); outstream->buffer_duration / 2.0, device->period_duration_max);
} }
SoundIoOutStreamDummy *osd = create<SoundIoOutStreamDummy>();
if (!osd) {
outstream_destroy_dummy(si, os);
return SoundIoErrorNoMem;
}
os->backend_data = osd;
int err; int err;
int buffer_size = outstream->bytes_per_frame * outstream->sample_rate * outstream->buffer_duration; int buffer_size = outstream->bytes_per_frame * outstream->sample_rate * outstream->buffer_duration;
if ((err = soundio_ring_buffer_init(&osd->ring_buffer, buffer_size))) { 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) { 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 (pause) {
if (osd->thread) { if (osd->thread) {
osd->abort_flag.clear(); osd->abort_flag.clear();
@ -242,7 +205,7 @@ static int outstream_begin_write_dummy(SoundIoPrivate *si,
*out_areas = nullptr; *out_areas = nullptr;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
assert(*frame_count >= 0); assert(*frame_count >= 0);
assert(*frame_count <= osd->buffer_frame_count); 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) { 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; SoundIoOutStream *outstream = &os->pub;
int byte_count = frame_count * outstream->bytes_per_frame; int byte_count = frame_count * outstream->bytes_per_frame;
soundio_ring_buffer_advance_write_ptr(&osd->ring_buffer, byte_count); 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) { 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); soundio_ring_buffer_clear(&osd->ring_buffer);
osd->prebuf_frames_left = osd->prebuf_frame_count; osd->prebuf_frames_left = osd->prebuf_frame_count;
return 0; return 0;
} }
static void instream_destroy_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { static void instream_destroy_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamDummy *isd = (SoundIoInStreamDummy *)is->backend_data; SoundIoInStreamDummy *isd = &is->backend_data.dummy;
if (!isd)
return;
if (isd->thread) { if (isd->thread) {
isd->abort_flag.clear(); isd->abort_flag.clear();
@ -300,12 +261,10 @@ static void instream_destroy_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *i
isd->cond = nullptr; isd->cond = nullptr;
soundio_ring_buffer_deinit(&isd->ring_buffer); soundio_ring_buffer_deinit(&isd->ring_buffer);
destroy(isd);
is->backend_data = nullptr;
} }
static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) { static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIoDevice *device = instream->device; 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); instream->buffer_duration / 8.0, instream->device->period_duration_max);
} }
SoundIoInStreamDummy *isd = create<SoundIoInStreamDummy>();
if (!isd) {
instream_destroy_dummy(si, is);
return SoundIoErrorNoMem;
}
is->backend_data = isd;
int err; int err;
int buffer_size = instream->bytes_per_frame * instream->sample_rate * instream->buffer_duration; int buffer_size = instream->bytes_per_frame * instream->sample_rate * instream->buffer_duration;
if ((err = soundio_ring_buffer_init(&isd->ring_buffer, buffer_size))) { 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) { 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 (pause) {
if (isd->thread) { if (isd->thread) {
isd->abort_flag.clear(); isd->abort_flag.clear();
@ -372,7 +324,7 @@ static int instream_begin_read_dummy(SoundIoPrivate *si,
SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count) SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count)
{ {
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIoInStreamDummy *isd = (SoundIoInStreamDummy *)is->backend_data; SoundIoInStreamDummy *isd = &is->backend_data.dummy;
assert(*frame_count >= 0); assert(*frame_count >= 0);
assert(*frame_count <= isd->buffer_frame_count); 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) { 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; SoundIoInStream *instream = &is->pub;
if (isd->hole_size > 0) { if (isd->hole_size > 0) {

View file

@ -8,7 +8,10 @@
#ifndef SOUNDIO_DUMMY_HPP #ifndef SOUNDIO_DUMMY_HPP
#define SOUNDIO_DUMMY_HPP #define SOUNDIO_DUMMY_HPP
#include "soundio.h"
#include "os.hpp" #include "os.hpp"
#include "atomics.hpp"
#include "ring_buffer.hpp"
int soundio_dummy_init(struct SoundIoPrivate *si); 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 #endif

View file

@ -14,11 +14,6 @@
static atomic_flag global_msg_callback_flag = ATOMIC_FLAG_INIT; 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 { struct SoundIoJackPort {
const char *name; const char *name;
int name_len; 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) { static void outstream_destroy_jack(struct SoundIoPrivate *is, struct SoundIoOutStreamPrivate *os) {
SoundIoOutStreamJack *osj = (SoundIoOutStreamJack *) os->backend_data; SoundIoOutStreamJack *osj = &os->backend_data.jack;
if (!osj)
return;
jack_client_close(osj->client); jack_client_close(osj->client);
destroy(osj);
os->backend_data = nullptr;
} }
static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) { static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
SoundIoOutStreamJack *osj = &os->backend_data.jack;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
//TODO SoundIoDevice *device = outstream->device; //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->period_duration = 0.0; // TODO
outstream->prebuf_duration = 0.0; // TODO outstream->prebuf_duration = 0.0; // TODO
SoundIoOutStreamJack *osj = create<SoundIoOutStreamJack>();
if (!osj) {
outstream_destroy_jack(si, os);
return SoundIoErrorNoMem;
}
os->backend_data = osj;
outstream->layout_error = SoundIoErrorIncompatibleBackend; outstream->layout_error = SoundIoErrorIncompatibleBackend;
jack_status_t status; 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) { 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; SoundIoOutStream *outstream = &os->pub;
int err; int err;
if (pause) { if (pause) {

View file

@ -8,6 +8,7 @@
#ifndef SOUNDIO_JACK_HPP #ifndef SOUNDIO_JACK_HPP
#define SOUNDIO_JACK_HPP #define SOUNDIO_JACK_HPP
#include "soundio.h"
#include "os.hpp" #include "os.hpp"
#include <jack/jack.h> #include <jack/jack.h>
@ -29,5 +30,13 @@ struct SoundIoJack {
int buffer_size; int buffer_size;
}; };
#endif struct SoundIoOutStreamJack {
jack_client_t *client;
jack_port_t *ports[SOUNDIO_MAX_CHANNELS];
};
struct SoundIoInStreamJack {
};
#endif

View file

@ -13,21 +13,6 @@
#include <stdio.h> #include <stdio.h>
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, static void subscribe_callback(pa_context *context,
pa_subscription_event_type_t event_bits, uint32_t index, void *userdata) 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; SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio; SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
switch (pa_stream_get_state(stream)) { switch (pa_stream_get_state(stream)) {
case PA_STREAM_UNCONNECTED: case PA_STREAM_UNCONNECTED:
case PA_STREAM_CREATING: 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) { static void outstream_destroy_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
if (!ospa)
return;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_stream *stream = ospa->stream; pa_stream *stream = ospa->stream;
@ -618,21 +601,12 @@ static void outstream_destroy_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os
ospa->stream = nullptr; ospa->stream = nullptr;
} }
destroy(ospa);
os->backend_data = nullptr;
} }
static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamPulseAudio *ospa = create<SoundIoOutStreamPulseAudio>();
if (!ospa) {
outstream_destroy_pa(si, os);
return SoundIoErrorNoMem;
}
os->backend_data = ospa;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
ospa->stream_ready = false; 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) { static int outstream_start_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; 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); pa_threaded_mainloop_lock(sipa->main_loop);
@ -720,7 +694,7 @@ static int outstream_begin_write_pa(SoundIoPrivate *si,
*out_areas = nullptr; *out_areas = nullptr;
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
pa_stream *stream = ospa->stream; pa_stream *stream = ospa->stream;
size_t byte_count = *frame_count * outstream->bytes_per_frame; size_t byte_count = *frame_count * outstream->bytes_per_frame;
if (pa_stream_begin_write(stream, (void**)&ospa->write_ptr, &byte_count)) 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) { static int outstream_end_write_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, int frame_count) {
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
pa_stream *stream = ospa->stream; pa_stream *stream = ospa->stream;
assert(frame_count > 0); assert(frame_count > 0);
size_t byte_count = frame_count * outstream->bytes_per_frame; 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, static int outstream_clear_buffer_pa(SoundIoPrivate *si,
SoundIoOutStreamPrivate *os) SoundIoOutStreamPrivate *os)
{ {
SoundIoOutStreamPulseAudio *ospa = (SoundIoOutStreamPulseAudio *)os->backend_data; SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_stream *stream = ospa->stream; pa_stream *stream = ospa->stream;
pa_threaded_mainloop_lock(sipa->main_loop); 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) { 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; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop); 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) { static void recording_stream_state_callback(pa_stream *stream, void *userdata) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate*)userdata; SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate*)userdata;
SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)is->backend_data; SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIo *soundio = instream->device->soundio; SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)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); instream->read_callback(instream, available_frame_count);
} }
static void instream_destroy_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *instream) { static void instream_destroy_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)instream->backend_data; SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
if (!ispa)
return;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_stream *stream = ispa->stream; pa_stream *stream = ispa->stream;
if (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) { static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIoInStreamPulseAudio *ispa = create<SoundIoInStreamPulseAudio>();
if (!ispa) {
instream_destroy_pa(si, is);
return SoundIoErrorNoMem;
}
is->backend_data = ispa;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
ispa->stream_ready = false; 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) { static int instream_start_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)is->backend_data; SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop); 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) SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count)
{ {
SoundIoInStream *instream = &is->pub; SoundIoInStream *instream = &is->pub;
SoundIoInStreamPulseAudio *ispa = (SoundIoInStreamPulseAudio *)is->backend_data; SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
pa_stream *stream = ispa->stream; pa_stream *stream = ispa->stream;
assert(ispa->stream_ready); 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) { 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; pa_stream *stream = ispa->stream;
if (pa_stream_drop(stream)) if (pa_stream_drop(stream))
return SoundIoErrorStreaming; 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) { 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; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop); pa_threaded_mainloop_lock(sipa->main_loop);

View file

@ -8,6 +8,7 @@
#ifndef SOUNDIO_PULSEAUDIO_HPP #ifndef SOUNDIO_PULSEAUDIO_HPP
#define SOUNDIO_PULSEAUDIO_HPP #define SOUNDIO_PULSEAUDIO_HPP
#include "soundio.h"
#include "atomics.hpp" #include "atomics.hpp"
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
@ -43,4 +44,19 @@ struct SoundIoPulseAudio {
pa_proplist *props; 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 #endif

View file

@ -186,8 +186,6 @@ int soundio_connect_backend(SoundIo *soundio, SoundIoBackend backend) {
if (!fn) if (!fn)
return SoundIoErrorBackendUnavailable; return SoundIoErrorBackendUnavailable;
memset(&si->backend_data, 0, sizeof(SoundIoBackendData));
int err; int err;
if ((err = backend_init_fns[backend](si))) { if ((err = backend_init_fns[backend](si))) {
soundio_disconnect(soundio); soundio_disconnect(soundio);
@ -201,10 +199,12 @@ void soundio_disconnect(struct SoundIo *soundio) {
if (si->destroy) if (si->destroy)
si->destroy(si); si->destroy(si);
memset(&si->backend_data, 0, sizeof(SoundIoBackendData));
soundio->current_backend = SoundIoBackendNone; soundio->current_backend = SoundIoBackendNone;
soundio_destroy_devices_info(si->safe_devices_info); soundio_destroy_devices_info(si->safe_devices_info);
si->safe_devices_info = nullptr; si->safe_devices_info = nullptr;
si->destroy = nullptr; si->destroy = nullptr;

View file

@ -51,6 +51,32 @@ union SoundIoDeviceBackendData {
SoundIoDeviceDummy dummy; 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 { struct SoundIoDevicesInfo {
SoundIoList<SoundIoDevice *> input_devices; SoundIoList<SoundIoDevice *> input_devices;
SoundIoList<SoundIoDevice *> output_devices; SoundIoList<SoundIoDevice *> output_devices;
@ -60,13 +86,13 @@ struct SoundIoDevicesInfo {
}; };
struct SoundIoOutStreamPrivate { struct SoundIoOutStreamPrivate {
struct SoundIoOutStream pub; SoundIoOutStream pub;
void *backend_data; SoundIoOutStreamBackendData backend_data;
}; };
struct SoundIoInStreamPrivate { struct SoundIoInStreamPrivate {
struct SoundIoInStream pub; SoundIoInStream pub;
void *backend_data; SoundIoInStreamBackendData backend_data;
}; };
struct SoundIoPrivate { struct SoundIoPrivate {