2015-07-01 08:02:44 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015 Andrew Kelley
|
|
|
|
*
|
|
|
|
* This file is part of libsoundio, which is MIT licensed.
|
|
|
|
* See http://opensource.org/licenses/MIT
|
|
|
|
*/
|
|
|
|
|
2015-07-01 08:20:26 +00:00
|
|
|
#include "soundio.hpp"
|
2015-07-01 08:02:44 +00:00
|
|
|
#include "util.hpp"
|
|
|
|
#include "dummy.hpp"
|
2015-07-02 09:53:08 +00:00
|
|
|
#include "os.hpp"
|
2015-07-02 10:48:27 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#ifdef SOUNDIO_HAVE_PULSEAUDIO
|
|
|
|
#include "pulseaudio.hpp"
|
|
|
|
#endif
|
2015-07-01 08:02:44 +00:00
|
|
|
|
2015-07-07 09:55:32 +00:00
|
|
|
#ifdef SOUNDIO_HAVE_ALSA
|
|
|
|
#include "alsa.hpp"
|
|
|
|
#endif
|
|
|
|
|
2015-07-01 09:37:51 +00:00
|
|
|
#include <string.h>
|
2015-07-01 08:02:44 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
2015-07-10 09:21:47 +00:00
|
|
|
const char *soundio_strerror(int error) {
|
2015-07-01 08:24:57 +00:00
|
|
|
switch ((enum SoundIoError)error) {
|
|
|
|
case SoundIoErrorNone: return "(no error)";
|
|
|
|
case SoundIoErrorNoMem: return "out of memory";
|
|
|
|
case SoundIoErrorInitAudioBackend: return "unable to initialize audio backend";
|
|
|
|
case SoundIoErrorSystemResources: return "system resource not available";
|
|
|
|
case SoundIoErrorOpeningDevice: return "unable to open device";
|
|
|
|
}
|
2015-07-01 20:24:47 +00:00
|
|
|
soundio_panic("invalid error enum value: %d", error);
|
2015-07-01 08:24:57 +00:00
|
|
|
}
|
2015-07-01 08:02:44 +00:00
|
|
|
|
2015-07-10 09:21:47 +00:00
|
|
|
int soundio_get_bytes_per_sample(enum SoundIoFormat format) {
|
|
|
|
switch (format) {
|
|
|
|
case SoundIoFormatU8: return 1;
|
|
|
|
case SoundIoFormatS8: return 1;
|
|
|
|
case SoundIoFormatS16LE: return 2;
|
|
|
|
case SoundIoFormatS16BE: return 2;
|
|
|
|
case SoundIoFormatU16LE: return 2;
|
|
|
|
case SoundIoFormatU16BE: return 2;
|
|
|
|
case SoundIoFormatS24LE: return 4;
|
|
|
|
case SoundIoFormatS24BE: return 4;
|
|
|
|
case SoundIoFormatU24LE: return 4;
|
|
|
|
case SoundIoFormatU24BE: return 4;
|
|
|
|
case SoundIoFormatS32LE: return 4;
|
|
|
|
case SoundIoFormatS32BE: return 4;
|
|
|
|
case SoundIoFormatU32LE: return 4;
|
|
|
|
case SoundIoFormatU32BE: return 4;
|
|
|
|
case SoundIoFormatFloat32LE: return 4;
|
|
|
|
case SoundIoFormatFloat32BE: return 4;
|
|
|
|
case SoundIoFormatFloat64LE: return 8;
|
|
|
|
case SoundIoFormatFloat64BE: return 8;
|
|
|
|
|
|
|
|
case SoundIoFormatInvalid:
|
|
|
|
soundio_panic("invalid sample format");
|
2015-07-01 08:02:44 +00:00
|
|
|
}
|
2015-07-01 20:24:47 +00:00
|
|
|
soundio_panic("invalid sample format");
|
2015-07-01 08:02:44 +00:00
|
|
|
}
|
|
|
|
|
2015-07-10 09:21:47 +00:00
|
|
|
const char * soundio_format_string(enum SoundIoFormat format) {
|
|
|
|
switch (format) {
|
|
|
|
case SoundIoFormatU8: return "signed 8-bit";
|
|
|
|
case SoundIoFormatS8: return "unsigned 8-bit";
|
|
|
|
case SoundIoFormatS16LE: return "signed 16-bit LE";
|
|
|
|
case SoundIoFormatS16BE: return "signed 16-bit BE";
|
|
|
|
case SoundIoFormatU16LE: return "unsigned 16-bit LE";
|
|
|
|
case SoundIoFormatU16BE: return "unsigned 16-bit LE";
|
|
|
|
case SoundIoFormatS24LE: return "signed 24-bit LE";
|
|
|
|
case SoundIoFormatS24BE: return "signed 24-bit BE";
|
|
|
|
case SoundIoFormatU24LE: return "unsigned 24-bit LE";
|
|
|
|
case SoundIoFormatU24BE: return "unsigned 24-bit BE";
|
|
|
|
case SoundIoFormatS32LE: return "signed 32-bit LE";
|
|
|
|
case SoundIoFormatS32BE: return "signed 32-bit BE";
|
|
|
|
case SoundIoFormatU32LE: return "unsigned 32-bit LE";
|
|
|
|
case SoundIoFormatU32BE: return "unsigned 32-bit BE";
|
|
|
|
case SoundIoFormatFloat32LE: return "float 32-bit LE";
|
|
|
|
case SoundIoFormatFloat32BE: return "float 32-bit BE";
|
|
|
|
case SoundIoFormatFloat64LE: return "float 64-bit LE";
|
|
|
|
case SoundIoFormatFloat64BE: return "float 64-bit BE";
|
|
|
|
|
|
|
|
case SoundIoFormatInvalid:
|
|
|
|
return "(invalid sample format)";
|
2015-07-01 08:02:44 +00:00
|
|
|
}
|
2015-07-10 07:46:03 +00:00
|
|
|
return "(invalid sample format)";
|
2015-07-01 08:02:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char *soundio_backend_name(enum SoundIoBackend backend) {
|
|
|
|
switch (backend) {
|
2015-07-01 09:53:53 +00:00
|
|
|
case SoundIoBackendNone: return "(none)";
|
2015-07-01 08:02:44 +00:00
|
|
|
case SoundIoBackendPulseAudio: return "PulseAudio";
|
2015-07-07 09:55:32 +00:00
|
|
|
case SoundIoBackendAlsa: return "ALSA";
|
2015-07-01 08:02:44 +00:00
|
|
|
case SoundIoBackendDummy: return "Dummy";
|
|
|
|
}
|
2015-07-01 20:24:47 +00:00
|
|
|
soundio_panic("invalid backend enum value: %d", (int)backend);
|
2015-07-01 08:02:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void soundio_destroy(struct SoundIo *soundio) {
|
|
|
|
if (!soundio)
|
|
|
|
return;
|
|
|
|
|
2015-07-01 09:53:53 +00:00
|
|
|
soundio_disconnect(soundio);
|
2015-07-01 08:02:44 +00:00
|
|
|
|
|
|
|
destroy(soundio);
|
|
|
|
}
|
|
|
|
|
2015-07-04 10:37:50 +00:00
|
|
|
static void default_on_devices_change(struct SoundIo *) { }
|
2015-07-04 21:20:52 +00:00
|
|
|
static void default_on_events_signal(struct SoundIo *) { }
|
2015-07-04 10:37:50 +00:00
|
|
|
|
2015-07-01 09:53:53 +00:00
|
|
|
struct SoundIo * soundio_create(void) {
|
2015-07-02 09:53:08 +00:00
|
|
|
soundio_os_init();
|
2015-07-01 08:02:44 +00:00
|
|
|
struct SoundIo *soundio = create<SoundIo>();
|
|
|
|
if (!soundio) {
|
|
|
|
soundio_destroy(soundio);
|
2015-07-01 09:53:53 +00:00
|
|
|
return NULL;
|
2015-07-01 08:02:44 +00:00
|
|
|
}
|
2015-07-04 10:37:50 +00:00
|
|
|
soundio->on_devices_change = default_on_devices_change;
|
2015-07-04 21:20:52 +00:00
|
|
|
soundio->on_events_signal = default_on_events_signal;
|
2015-07-01 09:53:53 +00:00
|
|
|
return soundio;
|
|
|
|
}
|
2015-07-01 08:02:44 +00:00
|
|
|
|
2015-07-01 09:53:53 +00:00
|
|
|
int soundio_connect(struct SoundIo *soundio) {
|
2015-07-01 08:02:44 +00:00
|
|
|
int err;
|
|
|
|
|
2015-07-02 10:48:27 +00:00
|
|
|
#ifdef SOUNDIO_HAVE_PULSEAUDIO
|
2015-07-01 09:53:53 +00:00
|
|
|
soundio->current_backend = SoundIoBackendPulseAudio;
|
2015-07-01 08:02:44 +00:00
|
|
|
err = soundio_pulseaudio_init(soundio);
|
2015-07-04 21:20:52 +00:00
|
|
|
if (!err)
|
|
|
|
return 0;
|
2015-07-01 08:02:44 +00:00
|
|
|
if (err != SoundIoErrorInitAudioBackend) {
|
2015-07-01 09:53:53 +00:00
|
|
|
soundio_disconnect(soundio);
|
2015-07-01 08:02:44 +00:00
|
|
|
return err;
|
|
|
|
}
|
2015-07-02 10:48:27 +00:00
|
|
|
#endif
|
2015-07-01 08:02:44 +00:00
|
|
|
|
2015-07-07 09:55:32 +00:00
|
|
|
#ifdef SOUNDIO_HAVE_ALSA
|
|
|
|
soundio->current_backend = SoundIoBackendAlsa;
|
|
|
|
err = soundio_alsa_init(soundio);
|
|
|
|
if (!err)
|
|
|
|
return 0;
|
|
|
|
if (err != SoundIoErrorInitAudioBackend) {
|
|
|
|
soundio_disconnect(soundio);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-01 09:53:53 +00:00
|
|
|
soundio->current_backend = SoundIoBackendDummy;
|
2015-07-01 08:02:44 +00:00
|
|
|
err = soundio_dummy_init(soundio);
|
|
|
|
if (err) {
|
2015-07-01 09:53:53 +00:00
|
|
|
soundio_disconnect(soundio);
|
2015-07-01 08:02:44 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-01 09:53:53 +00:00
|
|
|
void soundio_disconnect(struct SoundIo *soundio) {
|
|
|
|
if (soundio->destroy)
|
|
|
|
soundio->destroy(soundio);
|
|
|
|
assert(!soundio->backend_data);
|
|
|
|
|
|
|
|
soundio->current_backend = SoundIoBackendNone;
|
|
|
|
|
2015-07-07 09:55:32 +00:00
|
|
|
soundio_destroy_devices_info(soundio->safe_devices_info);
|
|
|
|
soundio->safe_devices_info = nullptr;
|
2015-07-01 09:53:53 +00:00
|
|
|
|
|
|
|
soundio->destroy = nullptr;
|
|
|
|
soundio->flush_events = nullptr;
|
|
|
|
soundio->wait_events = nullptr;
|
|
|
|
soundio->wakeup = nullptr;
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
soundio->out_stream_init = nullptr;
|
|
|
|
soundio->out_stream_destroy = nullptr;
|
|
|
|
soundio->out_stream_start = nullptr;
|
|
|
|
soundio->out_stream_free_count = nullptr;
|
|
|
|
soundio->out_stream_begin_write = nullptr;
|
|
|
|
soundio->out_stream_write = nullptr;
|
|
|
|
soundio->out_stream_clear_buffer = nullptr;
|
|
|
|
|
|
|
|
soundio->in_stream_init = nullptr;
|
|
|
|
soundio->in_stream_destroy = nullptr;
|
|
|
|
soundio->in_stream_start = nullptr;
|
|
|
|
soundio->in_stream_peek = nullptr;
|
|
|
|
soundio->in_stream_drop = nullptr;
|
|
|
|
soundio->in_stream_clear_buffer = nullptr;
|
2015-07-01 09:53:53 +00:00
|
|
|
}
|
|
|
|
|
2015-07-01 08:02:44 +00:00
|
|
|
void soundio_flush_events(struct SoundIo *soundio) {
|
2015-07-04 21:20:52 +00:00
|
|
|
assert(soundio->flush_events);
|
2015-07-01 08:02:44 +00:00
|
|
|
if (soundio->flush_events)
|
|
|
|
soundio->flush_events(soundio);
|
|
|
|
}
|
2015-07-01 08:20:26 +00:00
|
|
|
|
|
|
|
int soundio_get_input_device_count(struct SoundIo *soundio) {
|
2015-07-04 21:20:52 +00:00
|
|
|
soundio_flush_events(soundio);
|
2015-07-01 08:20:26 +00:00
|
|
|
assert(soundio->safe_devices_info);
|
|
|
|
return soundio->safe_devices_info->input_devices.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
int soundio_get_output_device_count(struct SoundIo *soundio) {
|
2015-07-04 21:20:52 +00:00
|
|
|
soundio_flush_events(soundio);
|
2015-07-01 08:20:26 +00:00
|
|
|
assert(soundio->safe_devices_info);
|
|
|
|
return soundio->safe_devices_info->output_devices.length;
|
|
|
|
}
|
2015-07-01 08:24:57 +00:00
|
|
|
|
|
|
|
int soundio_get_default_input_device_index(struct SoundIo *soundio) {
|
2015-07-04 21:20:52 +00:00
|
|
|
soundio_flush_events(soundio);
|
2015-07-01 08:24:57 +00:00
|
|
|
assert(soundio->safe_devices_info);
|
|
|
|
return soundio->safe_devices_info->default_input_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
int soundio_get_default_output_device_index(struct SoundIo *soundio) {
|
2015-07-04 21:20:52 +00:00
|
|
|
soundio_flush_events(soundio);
|
2015-07-01 08:24:57 +00:00
|
|
|
assert(soundio->safe_devices_info);
|
|
|
|
return soundio->safe_devices_info->default_output_index;
|
|
|
|
}
|
2015-07-01 08:29:35 +00:00
|
|
|
|
|
|
|
struct SoundIoDevice *soundio_get_input_device(struct SoundIo *soundio, int index) {
|
|
|
|
assert(soundio->safe_devices_info);
|
|
|
|
assert(index >= 0);
|
|
|
|
assert(index < soundio->safe_devices_info->input_devices.length);
|
|
|
|
SoundIoDevice *device = soundio->safe_devices_info->input_devices.at(index);
|
|
|
|
soundio_device_ref(device);
|
|
|
|
return device;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct SoundIoDevice *soundio_get_output_device(struct SoundIo *soundio, int index) {
|
|
|
|
assert(soundio->safe_devices_info);
|
|
|
|
assert(index >= 0);
|
|
|
|
assert(index < soundio->safe_devices_info->output_devices.length);
|
|
|
|
SoundIoDevice *device = soundio->safe_devices_info->output_devices.at(index);
|
|
|
|
soundio_device_ref(device);
|
|
|
|
return device;
|
|
|
|
}
|
2015-07-01 09:37:51 +00:00
|
|
|
|
|
|
|
// the name is the identifier for the device. UTF-8 encoded
|
|
|
|
const char *soundio_device_name(const struct SoundIoDevice *device) {
|
|
|
|
return device->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// UTF-8 encoded
|
|
|
|
const char *soundio_device_description(const struct SoundIoDevice *device) {
|
|
|
|
return device->description;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum SoundIoDevicePurpose soundio_device_purpose(const struct SoundIoDevice *device) {
|
|
|
|
return device->purpose;
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct SoundIoChannelLayout *soundio_device_channel_layout(const struct SoundIoDevice *device) {
|
|
|
|
return &device->channel_layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
void soundio_device_unref(struct SoundIoDevice *device) {
|
|
|
|
if (!device)
|
|
|
|
return;
|
|
|
|
|
|
|
|
device->ref_count -= 1;
|
|
|
|
assert(device->ref_count >= 0);
|
|
|
|
|
|
|
|
if (device->ref_count == 0) {
|
|
|
|
free(device->name);
|
|
|
|
free(device->description);
|
2015-07-10 09:21:47 +00:00
|
|
|
deallocate(device->formats, device->format_count);
|
2015-07-01 09:37:51 +00:00
|
|
|
destroy(device);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void soundio_device_ref(struct SoundIoDevice *device) {
|
|
|
|
device->ref_count += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void soundio_wait_events(struct SoundIo *soundio) {
|
|
|
|
soundio->wait_events(soundio);
|
|
|
|
}
|
|
|
|
|
|
|
|
void soundio_wakeup(struct SoundIo *soundio) {
|
|
|
|
soundio->wakeup(soundio);
|
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
void soundio_out_stream_fill_with_silence(struct SoundIoOutStream *out_stream) {
|
2015-07-01 09:37:51 +00:00
|
|
|
char *buffer;
|
2015-07-10 09:42:29 +00:00
|
|
|
int requested_frame_count = soundio_out_stream_free_count(out_stream);
|
2015-07-01 09:37:51 +00:00
|
|
|
while (requested_frame_count > 0) {
|
|
|
|
int frame_count = requested_frame_count;
|
2015-07-10 09:42:29 +00:00
|
|
|
soundio_out_stream_begin_write(out_stream, &buffer, &frame_count);
|
|
|
|
memset(buffer, 0, frame_count * out_stream->bytes_per_frame);
|
|
|
|
soundio_out_stream_write(out_stream, buffer, frame_count);
|
2015-07-01 09:37:51 +00:00
|
|
|
requested_frame_count -= frame_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
int soundio_out_stream_free_count(struct SoundIoOutStream *out_stream) {
|
|
|
|
SoundIo *soundio = out_stream->device->soundio;
|
|
|
|
return soundio->out_stream_free_count(soundio, out_stream);
|
2015-07-01 09:37:51 +00:00
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
void soundio_out_stream_begin_write(struct SoundIoOutStream *out_stream,
|
2015-07-01 09:37:51 +00:00
|
|
|
char **data, int *frame_count)
|
|
|
|
{
|
2015-07-10 09:42:29 +00:00
|
|
|
SoundIo *soundio = out_stream->device->soundio;
|
|
|
|
soundio->out_stream_begin_write(soundio, out_stream, data, frame_count);
|
2015-07-01 09:37:51 +00:00
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
void soundio_out_stream_write(struct SoundIoOutStream *out_stream,
|
2015-07-01 09:37:51 +00:00
|
|
|
char *data, int frame_count)
|
|
|
|
{
|
2015-07-10 09:42:29 +00:00
|
|
|
SoundIo *soundio = out_stream->device->soundio;
|
|
|
|
soundio->out_stream_write(soundio, out_stream, data, frame_count);
|
2015-07-01 09:37:51 +00:00
|
|
|
}
|
2015-07-04 09:57:06 +00:00
|
|
|
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
int soundio_out_stream_create(struct SoundIoDevice *device,
|
2015-07-10 09:21:47 +00:00
|
|
|
enum SoundIoFormat format, int sample_rate,
|
2015-07-04 09:57:06 +00:00
|
|
|
double latency, void *userdata,
|
2015-07-10 09:42:29 +00:00
|
|
|
void (*write_callback)(struct SoundIoOutStream *, int frame_count),
|
|
|
|
void (*underrun_callback)(struct SoundIoOutStream *),
|
|
|
|
struct SoundIoOutStream **out_out_stream)
|
2015-07-04 09:57:06 +00:00
|
|
|
{
|
2015-07-10 09:42:29 +00:00
|
|
|
*out_out_stream = nullptr;
|
2015-07-04 09:57:06 +00:00
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
SoundIoOutStream *out_stream = create<SoundIoOutStream>();
|
|
|
|
if (!out_stream) {
|
|
|
|
soundio_out_stream_destroy(out_stream);
|
2015-07-04 09:57:06 +00:00
|
|
|
return SoundIoErrorNoMem;
|
|
|
|
}
|
|
|
|
|
|
|
|
soundio_device_ref(device);
|
2015-07-10 09:42:29 +00:00
|
|
|
out_stream->device = device;
|
|
|
|
out_stream->userdata = userdata;
|
|
|
|
out_stream->write_callback = write_callback;
|
|
|
|
out_stream->underrun_callback = underrun_callback;
|
|
|
|
out_stream->format = format;
|
|
|
|
out_stream->sample_rate = sample_rate;
|
|
|
|
out_stream->latency = latency;
|
|
|
|
out_stream->bytes_per_frame = soundio_get_bytes_per_frame(format,
|
2015-07-04 09:57:06 +00:00
|
|
|
device->channel_layout.channel_count);
|
|
|
|
|
|
|
|
SoundIo *soundio = device->soundio;
|
2015-07-10 09:42:29 +00:00
|
|
|
int err = soundio->out_stream_init(soundio, out_stream);
|
2015-07-04 09:57:06 +00:00
|
|
|
if (err) {
|
2015-07-10 09:42:29 +00:00
|
|
|
soundio_out_stream_destroy(out_stream);
|
2015-07-04 09:57:06 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
*out_out_stream = out_stream;
|
2015-07-04 09:57:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
void soundio_out_stream_destroy(SoundIoOutStream *out_stream) {
|
|
|
|
if (!out_stream)
|
2015-07-04 09:57:06 +00:00
|
|
|
return;
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
SoundIo *soundio = out_stream->device->soundio;
|
2015-07-04 09:57:06 +00:00
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
if (soundio->out_stream_destroy)
|
|
|
|
soundio->out_stream_destroy(soundio, out_stream);
|
2015-07-04 09:57:06 +00:00
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
soundio_device_unref(out_stream->device);
|
|
|
|
destroy(out_stream);
|
2015-07-04 09:57:06 +00:00
|
|
|
}
|
2015-07-04 10:37:50 +00:00
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
int soundio_out_stream_start(struct SoundIoOutStream *out_stream) {
|
|
|
|
SoundIo *soundio = out_stream->device->soundio;
|
|
|
|
return soundio->out_stream_start(soundio, out_stream);
|
2015-07-04 10:37:50 +00:00
|
|
|
}
|
2015-07-06 08:05:22 +00:00
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
int soundio_in_stream_create(struct SoundIoDevice *device,
|
2015-07-10 09:21:47 +00:00
|
|
|
enum SoundIoFormat format, int sample_rate,
|
2015-07-08 07:42:17 +00:00
|
|
|
double latency, void *userdata,
|
2015-07-10 09:42:29 +00:00
|
|
|
void (*read_callback)(struct SoundIoInStream *),
|
|
|
|
struct SoundIoInStream **out_in_stream)
|
2015-07-06 08:05:22 +00:00
|
|
|
{
|
2015-07-10 09:42:29 +00:00
|
|
|
*out_in_stream = nullptr;
|
2015-07-06 08:05:22 +00:00
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
SoundIoInStream *sid = create<SoundIoInStream>();
|
2015-07-06 08:05:22 +00:00
|
|
|
if (!sid) {
|
2015-07-10 09:42:29 +00:00
|
|
|
soundio_in_stream_destroy(sid);
|
2015-07-06 08:05:22 +00:00
|
|
|
return SoundIoErrorNoMem;
|
|
|
|
}
|
|
|
|
|
|
|
|
soundio_device_ref(device);
|
|
|
|
sid->device = device;
|
|
|
|
sid->userdata = userdata;
|
|
|
|
sid->read_callback = read_callback;
|
2015-07-10 09:21:47 +00:00
|
|
|
sid->format = format;
|
2015-07-06 08:05:22 +00:00
|
|
|
sid->latency = latency;
|
2015-07-08 07:42:17 +00:00
|
|
|
sid->sample_rate = sample_rate;
|
2015-07-10 09:21:47 +00:00
|
|
|
sid->bytes_per_frame = soundio_get_bytes_per_frame(format,
|
2015-07-06 08:05:22 +00:00
|
|
|
device->channel_layout.channel_count);
|
|
|
|
|
|
|
|
SoundIo *soundio = device->soundio;
|
2015-07-10 09:42:29 +00:00
|
|
|
int err = soundio->in_stream_init(soundio, sid);
|
2015-07-06 08:05:22 +00:00
|
|
|
if (err) {
|
2015-07-10 09:42:29 +00:00
|
|
|
soundio_in_stream_destroy(sid);
|
2015-07-06 08:05:22 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
*out_in_stream = sid;
|
2015-07-06 08:05:22 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
int soundio_in_stream_start(struct SoundIoInStream *in_stream) {
|
|
|
|
SoundIo *soundio = in_stream->device->soundio;
|
|
|
|
return soundio->in_stream_start(soundio, in_stream);
|
2015-07-06 08:05:22 +00:00
|
|
|
}
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
void soundio_in_stream_destroy(struct SoundIoInStream *in_stream) {
|
|
|
|
if (!in_stream)
|
2015-07-06 08:05:22 +00:00
|
|
|
return;
|
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
SoundIo *soundio = in_stream->device->soundio;
|
2015-07-06 08:05:22 +00:00
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
if (soundio->in_stream_destroy)
|
|
|
|
soundio->in_stream_destroy(soundio, in_stream);
|
2015-07-06 08:05:22 +00:00
|
|
|
|
2015-07-10 09:42:29 +00:00
|
|
|
soundio_device_unref(in_stream->device);
|
|
|
|
destroy(in_stream);
|
2015-07-06 08:05:22 +00:00
|
|
|
}
|
2015-07-07 09:55:32 +00:00
|
|
|
|
|
|
|
void soundio_destroy_devices_info(SoundIoDevicesInfo *devices_info) {
|
|
|
|
if (!devices_info)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int i = 0; i < devices_info->input_devices.length; i += 1)
|
|
|
|
soundio_device_unref(devices_info->input_devices.at(i));
|
|
|
|
for (int i = 0; i < devices_info->output_devices.length; i += 1)
|
|
|
|
soundio_device_unref(devices_info->output_devices.at(i));
|
|
|
|
|
|
|
|
destroy(devices_info);
|
|
|
|
}
|