support stream names (used for PulseAudio)

This commit is contained in:
Andrew Kelley 2015-07-20 20:13:35 -07:00
parent de5bb99d1f
commit be2675e551
6 changed files with 30 additions and 25 deletions

View file

@ -235,6 +235,7 @@ view `coverage/index.html` in a browser.
## Roadmap ## Roadmap
0. implement ALSA (Linux) backend, get examples working 0. implement ALSA (Linux) backend, get examples working
0. ALSA: poll instead of callback
0. fix pulseaudio backend since I broke it 0. fix pulseaudio backend since I broke it
0. pipe record to playback example working with dummy linux, osx, windows 0. pipe record to playback example working with dummy linux, osx, windows
0. pipe record to playback example working with pulseaudio linux 0. pipe record to playback example working with pulseaudio linux

View file

@ -39,15 +39,12 @@ static void playback_thread_run(void *arg) {
SoundIoOutStream *outstream = &os->pub; SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data; SoundIoOutStreamDummy *osd = (SoundIoOutStreamDummy *)os->backend_data;
double start_time = soundio_os_get_time();
long frames_consumed = 0; long frames_consumed = 0;
double start_time = soundio_os_get_time();
double time_per_frame = 1.0 / (double)outstream->sample_rate;
while (osd->abort_flag.test_and_set()) { while (osd->abort_flag.test_and_set()) {
double now = soundio_os_get_time(); double now = soundio_os_get_time();
double total_time = now - start_time; double total_time = now - start_time;
long total_frames = total_time / time_per_frame; long total_frames = total_time * outstream->sample_rate;
int frames_to_kill = total_frames - frames_consumed; int frames_to_kill = total_frames - frames_consumed;
int fill_count = soundio_ring_buffer_fill_count(&osd->ring_buffer); int fill_count = soundio_ring_buffer_fill_count(&osd->ring_buffer);
int frames_in_buffer = fill_count / outstream->bytes_per_frame; int frames_in_buffer = fill_count / outstream->bytes_per_frame;
@ -59,6 +56,9 @@ static void playback_thread_run(void *arg) {
if (frames_left > 0) { if (frames_left > 0) {
outstream->error_callback(outstream, SoundIoErrorUnderflow); outstream->error_callback(outstream, SoundIoErrorUnderflow);
// simulate filling with silence
int free_count = soundio_ring_buffer_free_count(&osd->ring_buffer);
soundio_ring_buffer_advance_write_ptr(&osd->ring_buffer, free_count);
} else if (read_count > 0) { } else if (read_count > 0) {
outstream->write_callback(outstream, read_count); outstream->write_callback(outstream, read_count);
} }

View file

@ -13,6 +13,7 @@
// safe to call from any thread(s) multiple times, but // safe to call from any thread(s) multiple times, but
// must be called at least once before calling any other os functions // must be called at least once before calling any other os functions
// soundio_create calls this function.
void soundio_os_init(void); void soundio_os_init(void);
double soundio_os_get_time(void); double soundio_os_get_time(void);

View file

@ -627,8 +627,7 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
// TODO handle period_duration // TODO handle period_duration
// TODO make this value ("SoundIo") configurable ospa->stream = pa_stream_new(sipa->pulse_context, outstream->name, &sample_spec, &channel_map);
ospa->stream = pa_stream_new(sipa->pulse_context, "SoundIo", &sample_spec, &channel_map);
if (!ospa->stream) { if (!ospa->stream) {
pa_threaded_mainloop_unlock(sipa->main_loop); pa_threaded_mainloop_unlock(sipa->main_loop);
outstream_destroy_pa(si, os); outstream_destroy_pa(si, os);
@ -806,8 +805,7 @@ static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
// TODO handle period_duration // TODO handle period_duration
// TODO make this value ("SoundIo") private ispa->stream = pa_stream_new(sipa->pulse_context, instream->name, &sample_spec, &channel_map);
ispa->stream = pa_stream_new(sipa->pulse_context, "SoundIo", &sample_spec, &channel_map);
if (!ispa->stream) { if (!ispa->stream) {
pa_threaded_mainloop_unlock(sipa->main_loop); pa_threaded_mainloop_unlock(sipa->main_loop);
instream_destroy_pa(si, is); instream_destroy_pa(si, is);

View file

@ -389,6 +389,7 @@ struct SoundIoOutStream *soundio_outstream_create(struct SoundIoDevice *device)
outstream->sample_rate = clamp(device->sample_rate_min, 48000, device->sample_rate_max); outstream->sample_rate = clamp(device->sample_rate_min, 48000, device->sample_rate_max);
outstream->buffer_duration = clamp(device->buffer_duration_min, 1.0, device->buffer_duration_max); outstream->buffer_duration = clamp(device->buffer_duration_min, 1.0, device->buffer_duration_max);
outstream->period_duration = -1.0; outstream->period_duration = -1.0;
outstream->name = "SoundIo";
return outstream; return outstream;
} }
@ -457,6 +458,7 @@ struct SoundIoInStream *soundio_instream_create(struct SoundIoDevice *device) {
instream->sample_rate = clamp(device->sample_rate_min, 48000, device->sample_rate_max); instream->sample_rate = clamp(device->sample_rate_min, 48000, device->sample_rate_max);
instream->buffer_duration = clamp(device->buffer_duration_min, 1.0, device->buffer_duration_max); instream->buffer_duration = clamp(device->buffer_duration_min, 1.0, device->buffer_duration_max);
instream->period_duration = -1.0; instream->period_duration = -1.0;
instream->name = "SoundIo";
return instream; return instream;
} }

View file

@ -16,9 +16,6 @@ extern "C"
{ {
#endif #endif
struct SoundIo;
struct SoundIoDevicesInfo;
enum SoundIoError { enum SoundIoError {
SoundIoErrorNone, SoundIoErrorNone,
SoundIoErrorNoMem, SoundIoErrorNoMem,
@ -197,6 +194,19 @@ struct SoundIoChannelArea {
int step; int step;
}; };
// The size of this struct is not part of the API or ABI.
struct SoundIo {
// Defaults to NULL. Put whatever you want here.
void *userdata;
// Optional callback. Called when the list of devices change. Only called
// during a call to soundio_flush_events or soundio_wait_events.
void (*on_devices_change)(struct SoundIo *);
// Optional callback. Called from an unknown thread that you should not use
// to call any soundio functions. You may use this to signal a condition
// variable to wake up. Called when soundio_wait_events would be woken up.
void (*on_events_signal)(struct SoundIo *);
};
// The size of this struct is not part of the API or ABI. // The size of this struct is not part of the API or ABI.
struct SoundIoDevice { struct SoundIoDevice {
// Read-only. Set automatically. // Read-only. Set automatically.
@ -314,6 +324,9 @@ struct SoundIoOutStream {
void (*error_callback)(struct SoundIoOutStream *, int err); void (*error_callback)(struct SoundIoOutStream *, int err);
void (*write_callback)(struct SoundIoOutStream *, int requested_frame_count); void (*write_callback)(struct SoundIoOutStream *, int requested_frame_count);
// Name of the stream. This is used by PulseAudio. Defaults to "SoundIo".
const char *name;
// computed automatically when you call soundio_outstream_open // computed automatically when you call soundio_outstream_open
int bytes_per_frame; int bytes_per_frame;
int bytes_per_sample; int bytes_per_sample;
@ -347,24 +360,14 @@ struct SoundIoInStream {
void *userdata; void *userdata;
void (*read_callback)(struct SoundIoInStream *); void (*read_callback)(struct SoundIoInStream *);
// Name of the stream. This is used by PulseAudio. Defaults to "SoundIo".
const char *name;
// computed automatically when you call soundio_instream_open // computed automatically when you call soundio_instream_open
int bytes_per_frame; int bytes_per_frame;
int bytes_per_sample; int bytes_per_sample;
}; };
// The size of this struct is not part of the API or ABI.
struct SoundIo {
// Defaults to NULL. Put whatever you want here.
void *userdata;
// Optional callback. Called when the list of devices change. Only called
// during a call to soundio_flush_events or soundio_wait_events.
void (*on_devices_change)(struct SoundIo *);
// Optional callback. Called from an unknown thread that you should not use
// to call any soundio functions. You may use this to signal a condition
// variable to wake up. Called when soundio_wait_events would be woken up.
void (*on_events_signal)(struct SoundIo *);
};
// Main Context // Main Context
// Create a SoundIo context. You may create multiple instances of this to // Create a SoundIo context. You may create multiple instances of this to