convert source code to pure C

List<T> is now a really ugly macro.

Added a workaround for jack.h not putting `void` in function
prototypes for functions that take no arguments. I made upstream
pull requests to jack1 and jack2 but I don't have high hopes
about them getting merged.

I removed the lock-free atomic asserts. clang reports
non-lock-free atomics when in fact it does have lock-free
atomics. I inspected the generated code for gcc and clang
for fetch_add, load, and store, on x86_64 and armhf, and
it's all lock free.

Closes #45.
This commit is contained in:
Andrew Kelley 2015-11-01 15:18:37 -07:00
parent baba8064e1
commit ee7c0d3e11
30 changed files with 1865 additions and 1782 deletions

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 2.8.5)
project(libsoundio C CXX)
project(libsoundio C)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
if(CMAKE_VERSION VERSION_LESS 3.0.0)
@ -135,12 +135,12 @@ endif()
set(LIBSOUNDIO_SOURCES
"${CMAKE_SOURCE_DIR}/src/soundio.cpp"
"${CMAKE_SOURCE_DIR}/src/util.cpp"
"${CMAKE_SOURCE_DIR}/src/os.cpp"
"${CMAKE_SOURCE_DIR}/src/dummy.cpp"
"${CMAKE_SOURCE_DIR}/src/channel_layout.cpp"
"${CMAKE_SOURCE_DIR}/src/ring_buffer.cpp"
"${CMAKE_SOURCE_DIR}/src/soundio.c"
"${CMAKE_SOURCE_DIR}/src/util.c"
"${CMAKE_SOURCE_DIR}/src/os.c"
"${CMAKE_SOURCE_DIR}/src/dummy.c"
"${CMAKE_SOURCE_DIR}/src/channel_layout.c"
"${CMAKE_SOURCE_DIR}/src/ring_buffer.c"
)
set(CONFIGURE_OUT_FILE "${CMAKE_BINARY_DIR}/config.h")
@ -152,27 +152,27 @@ set(LIBSOUNDIO_HEADERS
if(SOUNDIO_HAVE_JACK)
set(LIBSOUNDIO_SOURCES ${LIBSOUNDIO_SOURCES}
"${CMAKE_SOURCE_DIR}/src/jack.cpp"
"${CMAKE_SOURCE_DIR}/src/jack.c"
)
endif()
if(SOUNDIO_HAVE_PULSEAUDIO)
set(LIBSOUNDIO_SOURCES ${LIBSOUNDIO_SOURCES}
"${CMAKE_SOURCE_DIR}/src/pulseaudio.cpp"
"${CMAKE_SOURCE_DIR}/src/pulseaudio.c"
)
endif()
if(SOUNDIO_HAVE_ALSA)
set(LIBSOUNDIO_SOURCES ${LIBSOUNDIO_SOURCES}
"${CMAKE_SOURCE_DIR}/src/alsa.cpp"
"${CMAKE_SOURCE_DIR}/src/alsa.c"
)
endif()
if(SOUNDIO_HAVE_COREAUDIO)
set(LIBSOUNDIO_SOURCES ${LIBSOUNDIO_SOURCES}
"${CMAKE_SOURCE_DIR}/src/coreaudio.cpp"
"${CMAKE_SOURCE_DIR}/src/coreaudio.c"
)
endif()
if(SOUNDIO_HAVE_WASAPI)
set(LIBSOUNDIO_SOURCES ${LIBSOUNDIO_SOURCES}
"${CMAKE_SOURCE_DIR}/src/wasapi.cpp"
"${CMAKE_SOURCE_DIR}/src/wasapi.c"
)
endif()
@ -195,15 +195,10 @@ set(LIBSOUNDIO_LIBS
# GTFO, -lstdc++ !!
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror -pedantic")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -pedantic")
set(LIB_CFLAGS "-std=c++11 -fno-exceptions -fno-rtti -fvisibility=hidden -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes -Wno-c99-extensions")
set(LIB_CFLAGS "-std=c11 -fvisibility=hidden -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes -D_REENTRANT -D_POSIX_C_SOURCE=200809L")
set(EXAMPLE_CFLAGS "-std=c99 -Wall")
set(TEST_CFLAGS "${LIB_CFLAGS} -fprofile-arcs -ftest-coverage")
set(TEST_LDFLAGS "-fprofile-arcs -ftest-coverage")
@ -277,7 +272,7 @@ if(BUILD_EXAMPLE_PROGRAMS)
endif()
if(BUILD_TESTS)
add_executable(unit_tests "${CMAKE_SOURCE_DIR}/test/unit_tests.cpp" ${LIBSOUNDIO_SOURCES})
add_executable(unit_tests "${CMAKE_SOURCE_DIR}/test/unit_tests.c" ${LIBSOUNDIO_SOURCES})
target_link_libraries(unit_tests LINK_PUBLIC ${LIBSOUNDIO_LIBS})
set_target_properties(unit_tests PROPERTIES
LINKER_LANGUAGE C
@ -285,7 +280,7 @@ if(BUILD_TESTS)
LINK_FLAGS ${TEST_LDFLAGS}
)
add_executable(latency "${CMAKE_SOURCE_DIR}/test/latency.cpp" ${LIBSOUNDIO_SOURCES})
add_executable(latency "${CMAKE_SOURCE_DIR}/test/latency.c" ${LIBSOUNDIO_SOURCES})
target_link_libraries(latency LINK_PUBLIC ${LIBSOUNDIO_LIBS} m)
set_target_properties(latency PROPERTIES
LINKER_LANGUAGE C

View file

@ -181,22 +181,6 @@ and `soundio_get_backend` to get the list of available backends.
[API Documentation](http://libsound.io/doc)
## Contributing
libsoundio is programmed in a tiny subset of C++11:
* No STL.
* No `new` or `delete`.
* No `class`. All fields in structs are `public`.
* No constructors or destructors.
* No exceptions or run-time type information.
* No references.
* No linking against libstdc++.
Do not be fooled - this is a *C library*, not a C++ library. We just take
advantage of a select few C++11 compiler features such as templates, and then
link against libc.
### Building
Install the dependencies:

View file

@ -5,10 +5,13 @@
* See http://opensource.org/licenses/MIT
*/
#include "alsa.hpp"
#include "soundio.hpp"
#define _GNU_SOURCE
#include "alsa.h"
#include "soundio_private.h"
#include <sys/inotify.h>
#include <fcntl.h>
#include <unistd.h>
static snd_pcm_stream_t stream_types[] = {SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE};
@ -20,8 +23,9 @@ static snd_pcm_access_t prioritized_access_types[] = {
SND_PCM_ACCESS_RW_NONINTERLEAVED,
};
SOUNDIO_MAKE_LIST_DEF(struct SoundIoAlsaPendingFile, SoundIoListAlsaPendingFile, SOUNDIO_LIST_STATIC)
static void wakeup_device_poll(SoundIoAlsa *sia) {
static void wakeup_device_poll(struct SoundIoAlsa *sia) {
ssize_t amt = write(sia->notify_pipe_fd[1], "a", 1);
if (amt == -1) {
assert(errno != EBADF);
@ -32,16 +36,16 @@ static void wakeup_device_poll(SoundIoAlsa *sia) {
}
}
static void destroy_alsa(SoundIoPrivate *si) {
SoundIoAlsa *sia = &si->backend_data.alsa;
static void destroy_alsa(struct SoundIoPrivate *si) {
struct SoundIoAlsa *sia = &si->backend_data.alsa;
if (sia->thread) {
sia->abort_flag.clear();
atomic_flag_clear(&sia->abort_flag);
wakeup_device_poll(sia);
soundio_os_thread_destroy(sia->thread);
}
sia->pending_files.deinit();
SoundIoListAlsaPendingFile_deinit(&sia->pending_files);
if (sia->cond)
soundio_os_cond_destroy(sia->cond);
@ -71,10 +75,10 @@ static char * str_partition_on_char(char *str, char c) {
}
str += 1;
}
return nullptr;
return NULL;
}
static snd_pcm_stream_t aim_to_stream(SoundIoDeviceAim aim) {
static snd_pcm_stream_t aim_to_stream(enum SoundIoDeviceAim aim) {
switch (aim) {
case SoundIoDeviceAimOutput: return SND_PCM_STREAM_PLAYBACK;
case SoundIoDeviceAimInput: return SND_PCM_STREAM_CAPTURE;
@ -83,8 +87,8 @@ static snd_pcm_stream_t aim_to_stream(SoundIoDeviceAim aim) {
return SND_PCM_STREAM_PLAYBACK;
}
static SoundIoChannelId from_alsa_chmap_pos(unsigned int pos) {
switch ((snd_pcm_chmap_position)pos) {
static enum SoundIoChannelId from_alsa_chmap_pos(unsigned int pos) {
switch ((enum snd_pcm_chmap_position)pos) {
case SND_CHMAP_UNKNOWN: return SoundIoChannelIdInvalid;
case SND_CHMAP_NA: return SoundIoChannelIdInvalid;
case SND_CHMAP_MONO: return SoundIoChannelIdFrontCenter;
@ -126,7 +130,7 @@ static SoundIoChannelId from_alsa_chmap_pos(unsigned int pos) {
return SoundIoChannelIdInvalid;
}
static int to_alsa_chmap_pos(SoundIoChannelId channel_id) {
static int to_alsa_chmap_pos(enum SoundIoChannelId channel_id) {
switch (channel_id) {
case SoundIoChannelIdFrontLeft: return SND_CHMAP_FL;
case SoundIoChannelIdFrontRight: return SND_CHMAP_FR;
@ -168,8 +172,8 @@ static int to_alsa_chmap_pos(SoundIoChannelId channel_id) {
}
}
static void get_channel_layout(SoundIoChannelLayout *dest, snd_pcm_chmap_t *chmap) {
int channel_count = min((unsigned int)SOUNDIO_MAX_CHANNELS, chmap->channels);
static void get_channel_layout(struct SoundIoChannelLayout *dest, snd_pcm_chmap_t *chmap) {
int channel_count = soundio_int_min(SOUNDIO_MAX_CHANNELS, chmap->channels);
dest->channel_count = channel_count;
for (int i = 0; i < channel_count; i += 1) {
dest->channels[i] = from_alsa_chmap_pos(chmap->pos[i]);
@ -177,7 +181,7 @@ static void get_channel_layout(SoundIoChannelLayout *dest, snd_pcm_chmap_t *chma
soundio_channel_layout_detect_builtin(dest);
}
static int handle_channel_maps(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
static int handle_channel_maps(struct SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
if (!maps)
return 0;
@ -187,7 +191,7 @@ static int handle_channel_maps(SoundIoDevice *device, snd_pcm_chmap_query_t **ma
// one iteration to count
int layout_count = 0;
for (p = maps; (v = *p) && layout_count < SOUNDIO_MAX_CHANNELS; p += 1, layout_count += 1) { }
device->layouts = allocate<SoundIoChannelLayout>(layout_count);
device->layouts = ALLOCATE(struct SoundIoChannelLayout, layout_count);
if (!device->layouts) {
snd_pcm_free_chmaps(maps);
return SoundIoErrorNoMem;
@ -207,7 +211,7 @@ static int handle_channel_maps(SoundIoDevice *device, snd_pcm_chmap_query_t **ma
return 0;
}
static snd_pcm_format_t to_alsa_fmt(SoundIoFormat fmt) {
static snd_pcm_format_t to_alsa_fmt(enum SoundIoFormat fmt) {
switch (fmt) {
case SoundIoFormatS8: return SND_PCM_FORMAT_S8;
case SoundIoFormatU8: return SND_PCM_FORMAT_U8;
@ -234,7 +238,9 @@ static snd_pcm_format_t to_alsa_fmt(SoundIoFormat fmt) {
return SND_PCM_FORMAT_UNKNOWN;
}
static void test_fmt_mask(SoundIoDevice *device, const snd_pcm_format_mask_t *fmt_mask, SoundIoFormat fmt) {
static void test_fmt_mask(struct SoundIoDevice *device, const snd_pcm_format_mask_t *fmt_mask,
enum SoundIoFormat fmt)
{
if (snd_pcm_format_mask_test(fmt_mask, to_alsa_fmt(fmt))) {
device->formats[device->format_count] = fmt;
device->format_count += 1;
@ -242,7 +248,7 @@ static void test_fmt_mask(SoundIoDevice *device, const snd_pcm_format_mask_t *fm
}
static int set_access(snd_pcm_t *handle, snd_pcm_hw_params_t *hwparams, snd_pcm_access_t *out_access) {
for (int i = 0; i < array_length(prioritized_access_types); i += 1) {
for (int i = 0; i < ARRAY_LENGTH(prioritized_access_types); i += 1) {
snd_pcm_access_t access = prioritized_access_types[i];
int err = snd_pcm_hw_params_set_access(handle, hwparams, access);
if (err >= 0) {
@ -255,10 +261,10 @@ static int set_access(snd_pcm_t *handle, snd_pcm_hw_params_t *hwparams, snd_pcm_
}
// this function does not override device->formats, so if you want it to, deallocate and set it to NULL
static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle, int resample,
static int probe_open_device(struct SoundIoDevice *device, snd_pcm_t *handle, int resample,
int *out_channels_min, int *out_channels_max)
{
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
int err;
snd_pcm_hw_params_t *hwparams;
@ -270,7 +276,7 @@ static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle, int resam
if ((err = snd_pcm_hw_params_set_rate_resample(handle, hwparams, resample)) < 0)
return SoundIoErrorOpeningDevice;
if ((err = set_access(handle, hwparams, nullptr)))
if ((err = set_access(handle, hwparams, NULL)))
return err;
unsigned int channels_min;
@ -287,10 +293,10 @@ static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle, int resam
unsigned int rate_min;
unsigned int rate_max;
if ((err = snd_pcm_hw_params_get_rate_min(hwparams, &rate_min, nullptr)) < 0)
if ((err = snd_pcm_hw_params_get_rate_min(hwparams, &rate_min, NULL)) < 0)
return SoundIoErrorOpeningDevice;
if ((err = snd_pcm_hw_params_set_rate_last(handle, hwparams, &rate_max, nullptr)) < 0)
if ((err = snd_pcm_hw_params_set_rate_last(handle, hwparams, &rate_max, NULL)) < 0)
return SoundIoErrorOpeningDevice;
device->sample_rate_count = 1;
@ -345,7 +351,7 @@ static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle, int resam
if (!device->formats) {
snd_pcm_hw_params_get_format_mask(hwparams, fmt_mask);
device->formats = allocate<SoundIoFormat>(18);
device->formats = ALLOCATE(enum SoundIoFormat, 18);
if (!device->formats)
return SoundIoErrorNoMem;
@ -373,7 +379,7 @@ static int probe_open_device(SoundIoDevice *device, snd_pcm_t *handle, int resam
return 0;
}
static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
static int probe_device(struct SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
int err;
snd_pcm_t *handle;
@ -398,20 +404,20 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
// the min and max channel counts are correct.
int layout_count = 0;
for (int i = 0; i < soundio_channel_layout_builtin_count(); i += 1) {
const SoundIoChannelLayout *layout = soundio_channel_layout_get_builtin(i);
const struct SoundIoChannelLayout *layout = soundio_channel_layout_get_builtin(i);
if (layout->channel_count >= channels_min && layout->channel_count <= channels_max) {
layout_count += 1;
}
}
device->layout_count = layout_count;
device->layouts = allocate<SoundIoChannelLayout>(device->layout_count);
device->layouts = ALLOCATE(struct SoundIoChannelLayout, device->layout_count);
if (!device->layouts) {
snd_pcm_close(handle);
return SoundIoErrorNoMem;
}
int layout_index = 0;
for (int i = 0; i < soundio_channel_layout_builtin_count(); i += 1) {
const SoundIoChannelLayout *layout = soundio_channel_layout_get_builtin(i);
const struct SoundIoChannelLayout *layout = soundio_channel_layout_get_builtin(i);
if (layout->channel_count >= channels_min && layout->channel_count <= channels_max) {
device->layouts[layout_index++] = *soundio_channel_layout_get_builtin(i);
}
@ -428,7 +434,7 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
snd_pcm_close(handle);
return err;
}
maps = nullptr;
maps = NULL;
if (!device->is_raw) {
if (device->sample_rates[0].min == device->sample_rates[0].max)
@ -452,9 +458,9 @@ static inline bool str_has_prefix(const char *big_str, const char *prefix) {
return strncmp(big_str, prefix, strlen(prefix)) == 0;
}
static int refresh_devices(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoAlsa *sia = &si->backend_data.alsa;
static int refresh_devices(struct SoundIoPrivate *si) {
struct SoundIo *soundio = &si->pub;
struct SoundIoAlsa *sia = &si->backend_data.alsa;
int err;
if ((err = snd_config_update_free_global()) < 0)
@ -462,7 +468,7 @@ static int refresh_devices(SoundIoPrivate *si) {
if ((err = snd_config_update()) < 0)
return SoundIoErrorSystemResources;
SoundIoDevicesInfo *devices_info = allocate<SoundIoDevicesInfo>(1);
struct SoundIoDevicesInfo *devices_info = ALLOCATE(struct SoundIoDevicesInfo, 1);
if (!devices_info)
return SoundIoErrorNoMem;
devices_info->default_output_index = -1;
@ -517,7 +523,7 @@ static int refresh_devices(SoundIoPrivate *si) {
is_capture = true;
}
for (int stream_type_i = 0; stream_type_i < array_length(stream_types); stream_type_i += 1) {
for (int stream_type_i = 0; stream_type_i < ARRAY_LENGTH(stream_types); stream_type_i += 1) {
snd_pcm_stream_t stream = stream_types[stream_type_i];
if (stream == SND_PCM_STREAM_PLAYBACK && !is_playback) continue;
if (stream == SND_PCM_STREAM_CAPTURE && !is_capture) continue;
@ -528,7 +534,7 @@ static int refresh_devices(SoundIoPrivate *si) {
}
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1);
if (!dev) {
free(name);
free(descr);
@ -536,13 +542,13 @@ static int refresh_devices(SoundIoPrivate *si) {
snd_device_name_free_hint(hints);
return SoundIoErrorNoMem;
}
SoundIoDevice *device = &dev->pub;
struct SoundIoDevice *device = &dev->pub;
device->ref_count = 1;
device->soundio = soundio;
device->is_raw = false;
device->id = strdup(name);
device->name = descr1 ?
soundio_alloc_sprintf(nullptr, "%s: %s", descr, descr1) : strdup(descr);
soundio_alloc_sprintf(NULL, "%s: %s", descr, descr1) : strdup(descr);
if (!device->id || !device->name) {
soundio_device_unref(device);
@ -553,7 +559,7 @@ static int refresh_devices(SoundIoPrivate *si) {
return SoundIoErrorNoMem;
}
SoundIoList<SoundIoDevice *> *device_list;
struct SoundIoListDevicePtr *device_list;
bool is_default = str_has_prefix(name, "default:") || strcmp(name, "default") == 0;
if (stream == SND_PCM_STREAM_PLAYBACK) {
device->aim = SoundIoDeviceAimOutput;
@ -568,9 +574,9 @@ static int refresh_devices(SoundIoPrivate *si) {
devices_info->default_input_index = device_list->length;
}
device->probe_error = probe_device(device, nullptr);
device->probe_error = probe_device(device, NULL);
if (device_list->append(device)) {
if (SoundIoListDevicePtr_append(device_list, device)) {
soundio_device_unref(device);
free(name);
free(descr);
@ -631,7 +637,7 @@ static int refresh_devices(SoundIoPrivate *si) {
snd_pcm_info_set_device(pcm_info, device_index);
snd_pcm_info_set_subdevice(pcm_info, 0);
for (int stream_type_i = 0; stream_type_i < array_length(stream_types); stream_type_i += 1) {
for (int stream_type_i = 0; stream_type_i < ARRAY_LENGTH(stream_types); stream_type_i += 1) {
snd_pcm_stream_t stream = stream_types[stream_type_i];
snd_pcm_info_set_stream(pcm_info, stream);
@ -647,17 +653,17 @@ static int refresh_devices(SoundIoPrivate *si) {
const char *device_name = snd_pcm_info_get_name(pcm_info);
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1);
if (!dev) {
snd_ctl_close(handle);
soundio_destroy_devices_info(devices_info);
return SoundIoErrorNoMem;
}
SoundIoDevice *device = &dev->pub;
struct SoundIoDevice *device = &dev->pub;
device->ref_count = 1;
device->soundio = soundio;
device->id = soundio_alloc_sprintf(nullptr, "hw:%d,%d", card_index, device_index);
device->name = soundio_alloc_sprintf(nullptr, "%s %s", card_name, device_name);
device->id = soundio_alloc_sprintf(NULL, "hw:%d,%d", card_index, device_index);
device->name = soundio_alloc_sprintf(NULL, "%s %s", card_name, device_name);
device->is_raw = true;
if (!device->id || !device->name) {
@ -667,7 +673,7 @@ static int refresh_devices(SoundIoPrivate *si) {
return SoundIoErrorNoMem;
}
SoundIoList<SoundIoDevice *> *device_list;
struct SoundIoListDevicePtr *device_list;
if (stream == SND_PCM_STREAM_PLAYBACK) {
device->aim = SoundIoDeviceAimOutput;
device_list = &devices_info->output_devices;
@ -680,7 +686,7 @@ static int refresh_devices(SoundIoPrivate *si) {
snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps_from_hw(card_index, device_index, -1, stream);
device->probe_error = probe_device(device, maps);
if (device_list->append(device)) {
if (SoundIoListDevicePtr_append(device_list, device)) {
soundio_device_unref(device);
soundio_destroy_devices_info(devices_info);
return SoundIoErrorNoMem;
@ -704,9 +710,9 @@ static int refresh_devices(SoundIoPrivate *si) {
return 0;
}
static void shutdown_backend(SoundIoPrivate *si, int err) {
SoundIo *soundio = &si->pub;
SoundIoAlsa *sia = &si->backend_data.alsa;
static void shutdown_backend(struct SoundIoPrivate *si, int err) {
struct SoundIo *soundio = &si->pub;
struct SoundIoAlsa *sia = &si->backend_data.alsa;
soundio_os_mutex_lock(sia->mutex);
sia->shutdown_err = err;
soundio_os_cond_signal(sia->cond, sia->mutex);
@ -730,8 +736,8 @@ static bool copy_str(char *dest, const char *src, int buf_len) {
}
static void device_thread_run(void *arg) {
SoundIoPrivate *si = (SoundIoPrivate *)arg;
SoundIoAlsa *sia = &si->backend_data.alsa;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)arg;
struct SoundIoAlsa *sia = &si->backend_data.alsa;
// Some systems cannot read integer variables if they are not
// properly aligned. On other systems, incorrect alignment may
@ -751,7 +757,7 @@ static void device_thread_run(void *arg) {
int err;
for (;;) {
int poll_num = poll(fds, 2, -1);
if (!sia->abort_flag.test_and_set())
if (!atomic_flag_test_and_set(&sia->abort_flag))
break;
if (poll_num == -1) {
if (errno == EINTR)
@ -801,13 +807,14 @@ static void device_thread_run(void *arg) {
continue;
}
if (event->mask & IN_CREATE) {
if ((err = sia->pending_files.add_one())) {
if ((err = SoundIoListAlsaPendingFile_add_one(&sia->pending_files))) {
shutdown_backend(si, SoundIoErrorNoMem);
return;
}
SoundIoAlsaPendingFile *pending_file = &sia->pending_files.last();
struct SoundIoAlsaPendingFile *pending_file =
SoundIoListAlsaPendingFile_last_ptr(&sia->pending_files);
if (!copy_str(pending_file->name, event->name, SOUNDIO_MAX_ALSA_SND_FILE_LEN)) {
sia->pending_files.pop();
SoundIoListAlsaPendingFile_pop(&sia->pending_files);
}
continue;
}
@ -817,9 +824,10 @@ static void device_thread_run(void *arg) {
if (!(event->mask & IN_CLOSE_WRITE))
continue;
for (int i = 0; i < sia->pending_files.length; i += 1) {
SoundIoAlsaPendingFile *pending_file = &sia->pending_files.at(i);
struct SoundIoAlsaPendingFile *pending_file =
SoundIoListAlsaPendingFile_ptr_at(&sia->pending_files, i);
if (strcmp(pending_file->name, event->name) == 0) {
sia->pending_files.swap_remove(i);
SoundIoListAlsaPendingFile_swap_remove(&sia->pending_files, i);
if (sia->pending_files.length == 0) {
got_rescan_event = true;
}
@ -864,13 +872,13 @@ static void device_thread_run(void *arg) {
}
}
static void my_flush_events(SoundIoPrivate *si, bool wait) {
SoundIo *soundio = &si->pub;
SoundIoAlsa *sia = &si->backend_data.alsa;
static void my_flush_events(struct SoundIoPrivate *si, bool wait) {
struct SoundIo *soundio = &si->pub;
struct SoundIoAlsa *sia = &si->backend_data.alsa;
bool change = false;
bool cb_shutdown = false;
SoundIoDevicesInfo *old_devices_info = nullptr;
struct SoundIoDevicesInfo *old_devices_info = NULL;
soundio_os_mutex_lock(sia->mutex);
@ -886,7 +894,7 @@ static void my_flush_events(SoundIoPrivate *si, bool wait) {
} else if (sia->ready_devices_info) {
old_devices_info = si->safe_devices_info;
si->safe_devices_info = sia->ready_devices_info;
sia->ready_devices_info = nullptr;
sia->ready_devices_info = NULL;
change = true;
}
@ -900,54 +908,54 @@ static void my_flush_events(SoundIoPrivate *si, bool wait) {
soundio_destroy_devices_info(old_devices_info);
}
static void flush_events_alsa(SoundIoPrivate *si) {
static void flush_events_alsa(struct SoundIoPrivate *si) {
my_flush_events(si, false);
}
static void wait_events_alsa(SoundIoPrivate *si) {
static void wait_events_alsa(struct SoundIoPrivate *si) {
my_flush_events(si, false);
my_flush_events(si, true);
}
static void wakeup_alsa(SoundIoPrivate *si) {
SoundIoAlsa *sia = &si->backend_data.alsa;
static void wakeup_alsa(struct SoundIoPrivate *si) {
struct SoundIoAlsa *sia = &si->backend_data.alsa;
soundio_os_mutex_lock(sia->mutex);
soundio_os_cond_signal(sia->cond, sia->mutex);
soundio_os_mutex_unlock(sia->mutex);
}
static void force_device_scan_alsa(SoundIoPrivate *si) {
SoundIoAlsa *sia = &si->backend_data.alsa;
static void force_device_scan_alsa(struct SoundIoPrivate *si) {
struct SoundIoAlsa *sia = &si->backend_data.alsa;
wakeup_device_poll(sia);
}
static void outstream_destroy_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
static void outstream_destroy_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
if (osa->thread) {
osa->thread_exit_flag.clear();
atomic_flag_clear(&osa->thread_exit_flag);
soundio_os_thread_destroy(osa->thread);
osa->thread = nullptr;
osa->thread = NULL;
}
if (osa->handle) {
snd_pcm_close(osa->handle);
osa->handle = nullptr;
osa->handle = NULL;
}
free(osa->poll_fds);
osa->poll_fds = nullptr;
osa->poll_fds = NULL;
free(osa->chmap);
osa->chmap = nullptr;
osa->chmap = NULL;
free(osa->sample_buffer);
osa->sample_buffer = nullptr;
osa->sample_buffer = NULL;
}
static int outstream_xrun_recovery(SoundIoOutStreamPrivate *os, int err) {
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
static int outstream_xrun_recovery(struct SoundIoOutStreamPrivate *os, int err) {
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
if (err == -EPIPE) {
err = snd_pcm_prepare(osa->handle);
if (err >= 0)
@ -955,7 +963,7 @@ static int outstream_xrun_recovery(SoundIoOutStreamPrivate *os, int err) {
} else if (err == -ESTRPIPE) {
while ((err = snd_pcm_resume(osa->handle)) == -EAGAIN) {
// wait until suspend flag is released
poll(nullptr, 0, 1);
poll(NULL, 0, 1);
}
if (err < 0)
err = snd_pcm_prepare(osa->handle);
@ -965,9 +973,9 @@ static int outstream_xrun_recovery(SoundIoOutStreamPrivate *os, int err) {
return err;
}
static int instream_xrun_recovery(SoundIoInStreamPrivate *is, int err) {
SoundIoInStream *instream = &is->pub;
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
static int instream_xrun_recovery(struct SoundIoInStreamPrivate *is, int err) {
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
if (err == -EPIPE) {
err = snd_pcm_prepare(isa->handle);
if (err >= 0)
@ -975,7 +983,7 @@ static int instream_xrun_recovery(SoundIoInStreamPrivate *is, int err) {
} else if (err == -ESTRPIPE) {
while ((err = snd_pcm_resume(isa->handle)) == -EAGAIN) {
// wait until suspend flag is released
poll(nullptr, 0, 1);
poll(NULL, 0, 1);
}
if (err < 0)
err = snd_pcm_prepare(isa->handle);
@ -985,8 +993,8 @@ static int instream_xrun_recovery(SoundIoInStreamPrivate *is, int err) {
return err;
}
static int outstream_wait_for_poll(SoundIoOutStreamPrivate *os) {
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
static int outstream_wait_for_poll(struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
int err;
unsigned short revents;
for (;;) {
@ -1006,8 +1014,8 @@ static int outstream_wait_for_poll(SoundIoOutStreamPrivate *os) {
}
}
static int instream_wait_for_poll(SoundIoInStreamPrivate *is) {
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
static int instream_wait_for_poll(struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
int err;
unsigned short revents;
for (;;) {
@ -1028,9 +1036,9 @@ static int instream_wait_for_poll(SoundIoInStreamPrivate *is) {
}
static void outstream_thread_run(void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *) arg;
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *) arg;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
int err;
@ -1055,7 +1063,7 @@ static void outstream_thread_run(void *arg) {
if ((snd_pcm_uframes_t)avail == osa->buffer_size_frames) {
outstream->write_callback(outstream, 0, avail);
if (!osa->thread_exit_flag.test_and_set())
if (!atomic_flag_test_and_set(&osa->thread_exit_flag))
return;
continue;
}
@ -1070,14 +1078,14 @@ static void outstream_thread_run(void *arg) {
case SND_PCM_STATE_PAUSED:
{
if ((err = outstream_wait_for_poll(os)) < 0) {
if (!osa->thread_exit_flag.test_and_set())
if (!atomic_flag_test_and_set(&osa->thread_exit_flag))
return;
outstream->error_callback(outstream, SoundIoErrorStreaming);
return;
}
if (!osa->thread_exit_flag.test_and_set())
if (!atomic_flag_test_and_set(&osa->thread_exit_flag))
return;
if (!osa->clear_buffer_flag.test_and_set()) {
if (!atomic_flag_test_and_set(&osa->clear_buffer_flag)) {
if ((err = snd_pcm_drop(osa->handle)) < 0) {
outstream->error_callback(outstream, SoundIoErrorStreaming);
return;
@ -1130,9 +1138,9 @@ static void outstream_thread_run(void *arg) {
}
static void instream_thread_run(void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *) arg;
SoundIoInStream *instream = &is->pub;
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *) arg;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
int err;
@ -1155,12 +1163,12 @@ static void instream_thread_run(void *arg) {
case SND_PCM_STATE_PAUSED:
{
if ((err = instream_wait_for_poll(is)) < 0) {
if (!isa->thread_exit_flag.test_and_set())
if (!atomic_flag_test_and_set(&isa->thread_exit_flag))
return;
instream->error_callback(instream, SoundIoErrorStreaming);
return;
}
if (!isa->thread_exit_flag.test_and_set())
if (!atomic_flag_test_and_set(&isa->thread_exit_flag))
return;
snd_pcm_sframes_t avail = snd_pcm_avail_update(isa->handle);
@ -1198,21 +1206,21 @@ 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;
static int outstream_open_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoDevice *device = outstream->device;
osa->clear_buffer_flag.test_and_set();
atomic_flag_test_and_set(&osa->clear_buffer_flag);
if (outstream->software_latency == 0.0)
outstream->software_latency = 1.0;
outstream->software_latency = clamp(device->software_latency_min, outstream->software_latency, device->software_latency_max);
outstream->software_latency = soundio_double_clamp(device->software_latency_min, outstream->software_latency, device->software_latency_max);
int ch_count = outstream->layout.channel_count;
osa->chmap_size = sizeof(int) + sizeof(int) * ch_count;
osa->chmap = (snd_pcm_chmap_t *)allocate<char>(osa->chmap_size);
osa->chmap = (snd_pcm_chmap_t *)ALLOCATE(char, osa->chmap_size);
if (!osa->chmap) {
outstream_destroy_alsa(si, os);
return SoundIoErrorNoMem;
@ -1272,7 +1280,7 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
if (device->is_raw) {
period_count = 4;
unsigned int microseconds = 0.25 * outstream->software_latency * 1000000.0;
if ((err = snd_pcm_hw_params_set_period_time_near(osa->handle, hwparams, &microseconds, nullptr)) < 0) {
if ((err = snd_pcm_hw_params_set_period_time_near(osa->handle, hwparams, &microseconds, NULL)) < 0) {
outstream_destroy_alsa(si, os);
return SoundIoErrorOpeningDevice;
}
@ -1282,14 +1290,14 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
snd_pcm_uframes_t period_frames =
ceil_dbl_to_uframes(period_duration * (double)outstream->sample_rate);
if ((err = snd_pcm_hw_params_set_period_size_near(osa->handle, hwparams, &period_frames, nullptr)) < 0) {
if ((err = snd_pcm_hw_params_set_period_size_near(osa->handle, hwparams, &period_frames, NULL)) < 0) {
outstream_destroy_alsa(si, os);
return SoundIoErrorOpeningDevice;
}
}
snd_pcm_uframes_t period_size;
if ((snd_pcm_hw_params_get_period_size(hwparams, &period_size, nullptr)) < 0) {
if ((snd_pcm_hw_params_get_period_size(hwparams, &period_size, NULL)) < 0) {
outstream_destroy_alsa(si, os);
return SoundIoErrorOpeningDevice;
}
@ -1343,7 +1351,7 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
if (osa->access == SND_PCM_ACCESS_RW_INTERLEAVED || osa->access == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
osa->sample_buffer_size = ch_count * osa->period_size * phys_bytes_per_sample;
osa->sample_buffer = allocate_nonzero<char>(osa->sample_buffer_size);
osa->sample_buffer = ALLOCATE_NONZERO(char, osa->sample_buffer_size);
if (!osa->sample_buffer) {
outstream_destroy_alsa(si, os);
return SoundIoErrorNoMem;
@ -1356,7 +1364,7 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
return SoundIoErrorOpeningDevice;
}
osa->poll_fds = allocate<struct pollfd>(osa->poll_fd_count);
osa->poll_fds = ALLOCATE(struct pollfd, osa->poll_fd_count);
if (!osa->poll_fds) {
outstream_destroy_alsa(si, os);
return SoundIoErrorNoMem;
@ -1370,26 +1378,26 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
return 0;
}
static int outstream_start_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
SoundIo *soundio = &si->pub;
static int outstream_start_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
struct SoundIo *soundio = &si->pub;
assert(!osa->thread);
int err;
osa->thread_exit_flag.test_and_set();
atomic_flag_test_and_set(&osa->thread_exit_flag);
if ((err = soundio_os_thread_create(outstream_thread_run, os, soundio->emit_rtprio_warning, &osa->thread)))
return err;
return 0;
}
static int outstream_begin_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os,
static int outstream_begin_write_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
struct SoundIoChannelArea **out_areas, int *frame_count)
{
*out_areas = nullptr;
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
SoundIoOutStream *outstream = &os->pub;
*out_areas = NULL;
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
struct SoundIoOutStream *outstream = &os->pub;
if (osa->access == SND_PCM_ACCESS_RW_INTERLEAVED) {
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
@ -1397,7 +1405,7 @@ static int outstream_begin_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivat
osa->areas[ch].step = outstream->bytes_per_frame;
}
osa->write_frame_count = min(*frame_count, osa->period_size);
osa->write_frame_count = soundio_int_min(*frame_count, osa->period_size);
*frame_count = osa->write_frame_count;
} else if (osa->access == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
@ -1405,7 +1413,7 @@ static int outstream_begin_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivat
osa->areas[ch].step = outstream->bytes_per_sample;
}
osa->write_frame_count = min(*frame_count, osa->period_size);
osa->write_frame_count = soundio_int_min(*frame_count, osa->period_size);
*frame_count = osa->write_frame_count;
} else {
const snd_pcm_channel_area_t *areas;
@ -1435,9 +1443,9 @@ static int outstream_begin_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivat
return 0;
}
static int outstream_end_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
SoundIoOutStream *outstream = &os->pub;
static int outstream_end_write_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
struct SoundIoOutStream *outstream = &os->pub;
snd_pcm_sframes_t commitres;
if (osa->access == SND_PCM_ACCESS_RW_INTERLEAVED) {
@ -1462,11 +1470,11 @@ static int outstream_end_write_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate
return 0;
}
static int outstream_clear_buffer_alsa(SoundIoPrivate *si,
SoundIoOutStreamPrivate *os)
static int outstream_clear_buffer_alsa(struct SoundIoPrivate *si,
struct SoundIoOutStreamPrivate *os)
{
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
osa->clear_buffer_flag.clear();
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
atomic_flag_clear(&osa->clear_buffer_flag);
return 0;
}
@ -1474,7 +1482,7 @@ static int outstream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoOutStre
if (!si)
return SoundIoErrorInvalid;
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
if (!osa->handle)
return SoundIoErrorInvalid;
@ -1494,8 +1502,8 @@ static int outstream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoOutStre
static int outstream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
double *out_latency)
{
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
int err;
snd_pcm_sframes_t delay;
@ -1507,43 +1515,43 @@ static int outstream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoO
return 0;
}
static void instream_destroy_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
static void instream_destroy_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
if (isa->thread) {
isa->thread_exit_flag.clear();
atomic_flag_clear(&isa->thread_exit_flag);
soundio_os_thread_destroy(isa->thread);
isa->thread = nullptr;
isa->thread = NULL;
}
if (isa->handle) {
snd_pcm_close(isa->handle);
isa->handle = nullptr;
isa->handle = NULL;
}
free(isa->poll_fds);
isa->poll_fds = nullptr;
isa->poll_fds = NULL;
free(isa->chmap);
isa->chmap = nullptr;
isa->chmap = NULL;
free(isa->sample_buffer);
isa->sample_buffer = nullptr;
isa->sample_buffer = NULL;
}
static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
SoundIoInStream *instream = &is->pub;
SoundIoDevice *device = instream->device;
static int instream_open_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoDevice *device = instream->device;
if (instream->software_latency == 0.0)
instream->software_latency = 1.0;
instream->software_latency = clamp(device->software_latency_min, instream->software_latency, device->software_latency_max);
instream->software_latency = soundio_double_clamp(device->software_latency_min, instream->software_latency, device->software_latency_max);
int ch_count = instream->layout.channel_count;
isa->chmap_size = sizeof(int) + sizeof(int) * ch_count;
isa->chmap = (snd_pcm_chmap_t *)allocate<char>(isa->chmap_size);
isa->chmap = (snd_pcm_chmap_t *)ALLOCATE(char, isa->chmap_size);
if (!isa->chmap) {
instream_destroy_alsa(si, is);
return SoundIoErrorNoMem;
@ -1600,7 +1608,7 @@ static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
}
snd_pcm_uframes_t period_frames = ceil_dbl_to_uframes(0.5 * instream->software_latency * (double)instream->sample_rate);
if ((err = snd_pcm_hw_params_set_period_size_near(isa->handle, hwparams, &period_frames, nullptr)) < 0) {
if ((err = snd_pcm_hw_params_set_period_size_near(isa->handle, hwparams, &period_frames, NULL)) < 0) {
instream_destroy_alsa(si, is);
return SoundIoErrorOpeningDevice;
}
@ -1645,7 +1653,7 @@ static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
if (isa->access == SND_PCM_ACCESS_RW_INTERLEAVED || isa->access == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
isa->sample_buffer_size = ch_count * isa->period_size * phys_bytes_per_sample;
isa->sample_buffer = allocate_nonzero<char>(isa->sample_buffer_size);
isa->sample_buffer = ALLOCATE_NONZERO(char, isa->sample_buffer_size);
if (!isa->sample_buffer) {
instream_destroy_alsa(si, is);
return SoundIoErrorNoMem;
@ -1658,7 +1666,7 @@ static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
return SoundIoErrorOpeningDevice;
}
isa->poll_fds = allocate<struct pollfd>(isa->poll_fd_count);
isa->poll_fds = ALLOCATE(struct pollfd, isa->poll_fd_count);
if (!isa->poll_fds) {
instream_destroy_alsa(si, is);
return SoundIoErrorNoMem;
@ -1672,13 +1680,13 @@ static int instream_open_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
return 0;
}
static int instream_start_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
SoundIo *soundio = &si->pub;
static int instream_start_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
struct SoundIo *soundio = &si->pub;
assert(!isa->thread);
isa->thread_exit_flag.test_and_set();
atomic_flag_test_and_set(&isa->thread_exit_flag);
int err;
if ((err = soundio_os_thread_create(instream_thread_run, is, soundio->emit_rtprio_warning, &isa->thread))) {
instream_destroy_alsa(si, is);
@ -1688,12 +1696,12 @@ static int instream_start_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
return 0;
}
static int instream_begin_read_alsa(SoundIoPrivate *si,
SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count)
static int instream_begin_read_alsa(struct SoundIoPrivate *si,
struct SoundIoInStreamPrivate *is, struct SoundIoChannelArea **out_areas, int *frame_count)
{
*out_areas = nullptr;
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
SoundIoInStream *instream = &is->pub;
*out_areas = NULL;
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
struct SoundIoInStream *instream = &is->pub;
if (isa->access == SND_PCM_ACCESS_RW_INTERLEAVED) {
for (int ch = 0; ch < instream->layout.channel_count; ch += 1) {
@ -1701,7 +1709,7 @@ static int instream_begin_read_alsa(SoundIoPrivate *si,
isa->areas[ch].step = instream->bytes_per_frame;
}
isa->read_frame_count = min(*frame_count, isa->period_size);
isa->read_frame_count = soundio_int_min(*frame_count, isa->period_size);
*frame_count = isa->read_frame_count;
snd_pcm_sframes_t commitres = snd_pcm_readi(isa->handle, isa->sample_buffer, isa->read_frame_count);
@ -1718,7 +1726,7 @@ static int instream_begin_read_alsa(SoundIoPrivate *si,
ptrs[ch] = isa->areas[ch].ptr;
}
isa->read_frame_count = min(*frame_count, isa->period_size);
isa->read_frame_count = soundio_int_min(*frame_count, isa->period_size);
*frame_count = isa->read_frame_count;
snd_pcm_sframes_t commitres = snd_pcm_readn(isa->handle, (void**)ptrs, isa->read_frame_count);
@ -1753,8 +1761,8 @@ static int instream_begin_read_alsa(SoundIoPrivate *si,
return 0;
}
static int instream_end_read_alsa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
static int instream_end_read_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
if (isa->access == SND_PCM_ACCESS_RW_INTERLEAVED) {
// nothing to do
@ -1773,7 +1781,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 = &is->backend_data.alsa;
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
if (isa->is_paused == pause)
return 0;
@ -1789,8 +1797,8 @@ static int instream_pause_alsa(struct SoundIoPrivate *si, struct SoundIoInStream
static int instream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
double *out_latency)
{
SoundIoInStream *instream = &is->pub;
SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
int err;
snd_pcm_sframes_t delay;
@ -1802,13 +1810,13 @@ static int instream_get_latency_alsa(struct SoundIoPrivate *si, struct SoundIoIn
return 0;
}
int soundio_alsa_init(SoundIoPrivate *si) {
SoundIoAlsa *sia = &si->backend_data.alsa;
int soundio_alsa_init(struct SoundIoPrivate *si) {
struct SoundIoAlsa *sia = &si->backend_data.alsa;
int err;
sia->notify_fd = -1;
sia->notify_wd = -1;
sia->abort_flag.test_and_set();
atomic_flag_test_and_set(&sia->abort_flag);
sia->mutex = soundio_os_mutex_create();
if (!sia->mutex) {
@ -1865,7 +1873,7 @@ int soundio_alsa_init(SoundIoPrivate *si) {
wakeup_device_poll(sia);
if ((err = soundio_os_thread_create(device_thread_run, si, nullptr, &sia->thread))) {
if ((err = soundio_os_thread_create(device_thread_run, si, NULL, &sia->thread))) {
destroy_alsa(si);
return err;
}

View file

@ -5,28 +5,31 @@
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_ALSA_HPP
#define SOUNDIO_ALSA_HPP
#ifndef SOUNDIO_ALSA_H
#define SOUNDIO_ALSA_H
#include "soundio_private.h"
#include "soundio_internal.h"
#include "os.h"
#include "atomics.hpp"
#include "list.hpp"
#include "list.h"
#include "atomics.h"
#include <alsa/asoundlib.h>
struct SoundIoPrivate;
int soundio_alsa_init(struct SoundIoPrivate *si);
struct SoundIoDeviceAlsa { };
struct SoundIoDeviceAlsa { int make_the_struct_not_empty; };
#define SOUNDIO_MAX_ALSA_SND_FILE_LEN 16
struct SoundIoAlsaPendingFile {
char name[SOUNDIO_MAX_ALSA_SND_FILE_LEN];
};
SOUNDIO_MAKE_LIST_STRUCT(struct SoundIoAlsaPendingFile, SoundIoListAlsaPendingFile, SOUNDIO_LIST_STATIC)
struct SoundIoAlsa {
SoundIoOsMutex *mutex;
SoundIoOsCond *cond;
struct SoundIoOsMutex *mutex;
struct SoundIoOsCond *cond;
struct SoundIoOsThread *thread;
atomic_flag abort_flag;
@ -34,7 +37,7 @@ struct SoundIoAlsa {
int notify_wd;
bool have_devices_flag;
int notify_pipe_fd[2];
SoundIoList<SoundIoAlsaPendingFile> pending_files;
struct SoundIoListAlsaPendingFile pending_files;
// this one is ready to be read with flush_events. protected by mutex
struct SoundIoDevicesInfo *ready_devices_info;
@ -54,13 +57,13 @@ struct SoundIoOutStreamAlsa {
char *sample_buffer;
int poll_fd_count;
struct pollfd *poll_fds;
SoundIoOsThread *thread;
struct SoundIoOsThread *thread;
atomic_flag thread_exit_flag;
int period_size;
int write_frame_count;
bool is_paused;
atomic_flag clear_buffer_flag;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
struct SoundIoInStreamAlsa {
@ -73,12 +76,12 @@ struct SoundIoInStreamAlsa {
char *sample_buffer;
int poll_fd_count;
struct pollfd *poll_fds;
SoundIoOsThread *thread;
struct SoundIoOsThread *thread;
atomic_flag thread_exit_flag;
int period_size;
int read_frame_count;
bool is_paused;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
#endif

33
src/atomics.h Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of libsoundio, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_ATOMICS_H
#define SOUNDIO_ATOMICS_H
// Simple wrappers around atomic values so that the compiler will catch it if
// I accidentally use operators such as +, -, += on them.
#include <stdatomic.h>
struct SoundIoAtomicLong {
atomic_long x;
};
struct SoundIoAtomicInt {
atomic_int x;
};
struct SoundIoAtomicBool {
atomic_bool x;
};
#define SOUNDIO_ATOMIC_LOAD(a) atomic_load(&a.x)
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) atomic_fetch_add(&a.x, delta)
#define SOUNDIO_ATOMIC_STORE(a, value) atomic_store(&a.x, value)
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) atomic_exchange(&a.x, value)
#endif

View file

@ -1,34 +0,0 @@
/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of libsoundio, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_ATOMICS_HPP
#define SOUNDIO_ATOMICS_HPP
#include <atomic>
using std::atomic_flag;
using std::atomic_int;
using std::atomic_long;
using std::atomic_bool;
using std::atomic_uintptr_t;
#if ATOMIC_INT_LOCK_FREE != 2
#error "require atomic_int to be lock free"
#endif
#if ATOMIC_LONG_LOCK_FREE != 2
#error "require atomic_long to be lock free"
#endif
#if ATOMIC_BOOL_LOCK_FREE != 2
#error "require atomic_bool to be lock free"
#endif
#if ATOMIC_POINTER_LOCK_FREE != 2
#error "require atomic pointers to be lock free"
#endif
#endif

View file

@ -5,7 +5,7 @@
* See http://opensource.org/licenses/MIT
*/
#include "soundio.hpp"
#include "soundio_private.h"
#include <stdio.h>
@ -308,12 +308,12 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
},
};
static const int channel_name_alias_count = 3;
static const char *channel_names[][channel_name_alias_count] = {
#define CHANNEL_NAME_ALIAS_COUNT 3
static const char *channel_names[][CHANNEL_NAME_ALIAS_COUNT] = {
[SoundIoChannelIdInvalid] = {
"(Invalid Channel)",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdFrontLeft] = {
"Front Left",
@ -407,258 +407,258 @@ static const char *channel_names[][channel_name_alias_count] = {
},
[SoundIoChannelIdBackLeftCenter] = {
"Back Left Center",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdBackRightCenter] = {
"Back Right Center",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdFrontLeftWide] = {
"Front Left Wide",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdFrontRightWide] = {
"Front Right Wide",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdFrontLeftHigh] = {
"Front Left High",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdFrontCenterHigh] = {
"Front Center High",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdFrontRightHigh] = {
"Front Right High",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdTopFrontLeftCenter] = {
"Top Front Left Center",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdTopFrontRightCenter] = {
"Top Front Right Center",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdTopSideLeft] = {
"Top Side Left",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdTopSideRight] = {
"Top Side Right",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdLeftLfe] = {
"Left LFE",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdRightLfe] = {
"Right LFE",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdLfe2] = {
"LFE 2",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdBottomCenter] = {
"Bottom Center",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdBottomLeftCenter] = {
"Bottom Left Center",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdBottomRightCenter] = {
"Bottom Right Center",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdMsMid] = {
"Mid/Side Mid",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdMsSide] = {
"Mid/Side Side",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAmbisonicW] = {
"Ambisonic W",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAmbisonicX] = {
"Ambisonic X",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAmbisonicY] = {
"Ambisonic Y",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAmbisonicZ] = {
"Ambisonic Z",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdXyX] = {
"X-Y X",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdXyY] = {
"X-Y Y",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdHeadphonesLeft] = {
"Headphones Left",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdHeadphonesRight] = {
"Headphones Right",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdClickTrack] = {
"Click Track",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdForeignLanguage] = {
"Foreign Language",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdHearingImpaired] = {
"Hearing Impaired",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdNarration] = {
"Narration",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdHaptic] = {
"Haptic",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdDialogCentricMix] = {
"Dialog Centric Mix",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux] = {
"Aux",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux0] = {
"Aux 0",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux1] = {
"Aux 1",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux2] = {
"Aux 2",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux3] = {
"Aux 3",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux4] = {
"Aux 4",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux5] = {
"Aux 5",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux6] = {
"Aux 6",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux7] = {
"Aux 7",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux8] = {
"Aux 8",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux9] = {
"Aux 9",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux10] = {
"Aux 10",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux11] = {
"Aux 11",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux12] = {
"Aux 12",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux13] = {
"Aux 13",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux14] = {
"Aux 14",
nullptr,
nullptr,
NULL,
NULL,
},
[SoundIoChannelIdAux15] = {
"Aux 15",
nullptr,
nullptr,
NULL,
NULL,
},
};
const char *soundio_get_channel_name(enum SoundIoChannelId id) {
if (id < 0 || id > array_length(channel_names))
if (id >= ARRAY_LENGTH(channel_names))
return "(Invalid Channel)";
else
return channel_names[id][0];
@ -680,12 +680,12 @@ bool soundio_channel_layout_equal(
}
int soundio_channel_layout_builtin_count(void) {
return array_length(builtin_channel_layouts);
return ARRAY_LENGTH(builtin_channel_layouts);
}
const struct SoundIoChannelLayout *soundio_channel_layout_get_builtin(int index) {
assert(index >= 0);
assert(index <= array_length(builtin_channel_layouts));
assert(index <= ARRAY_LENGTH(builtin_channel_layouts));
return &builtin_channel_layouts[index];
}
@ -700,14 +700,14 @@ int soundio_channel_layout_find_channel(
}
bool soundio_channel_layout_detect_builtin(struct SoundIoChannelLayout *layout) {
for (int i = 0; i < array_length(builtin_channel_layouts); i += 1) {
for (int i = 0; i < ARRAY_LENGTH(builtin_channel_layouts); i += 1) {
const struct SoundIoChannelLayout *builtin_layout = &builtin_channel_layouts[i];
if (soundio_channel_layout_equal(builtin_layout, layout)) {
layout->name = builtin_layout->name;
return true;
}
}
layout->name = nullptr;
layout->name = NULL;
return false;
}
@ -722,18 +722,18 @@ const struct SoundIoChannelLayout *soundio_channel_layout_get_default(int channe
case 7: return soundio_channel_layout_get_builtin(SoundIoChannelLayoutId6Point1);
case 8: return soundio_channel_layout_get_builtin(SoundIoChannelLayoutId7Point1);
}
return nullptr;
return NULL;
}
enum SoundIoChannelId soundio_parse_channel_id(const char *str, int str_len) {
for (int id = 0; id < array_length(channel_names); id += 1) {
for (int i = 0; i < channel_name_alias_count; i += 1) {
for (int id = 0; id < ARRAY_LENGTH(channel_names); id += 1) {
for (int i = 0; i < CHANNEL_NAME_ALIAS_COUNT; i += 1) {
const char *alias = channel_names[id][i];
if (!alias)
break;
int alias_len = strlen(alias);
if (soundio_streql(alias, alias_len, str, str_len))
return (SoundIoChannelId)id;
return (enum SoundIoChannelId)id;
}
}
return SoundIoChannelIdInvalid;

View file

@ -5,8 +5,8 @@
* See http://opensource.org/licenses/MIT
*/
#include "coreaudio.hpp"
#include "soundio.hpp"
#include "coreaudio.h"
#include "soundio_private.h"
#include <assert.h>
@ -91,19 +91,21 @@ static AudioObjectPropertyAddress device_listen_props[] = {
},
};
static SoundIoDeviceAim aims[] = {
static enum SoundIoDeviceAim aims[] = {
SoundIoDeviceAimInput,
SoundIoDeviceAimOutput,
};
SOUNDIO_MAKE_LIST_DEF(AudioDeviceID, SoundIoListAudioDeviceID, SOUNDIO_LIST_STATIC)
static OSStatus on_devices_changed(AudioObjectID in_object_id, UInt32 in_number_addresses,
const AudioObjectPropertyAddress in_addresses[], void *in_client_data)
{
SoundIoPrivate *si = (SoundIoPrivate*)in_client_data;
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
struct SoundIoPrivate *si = (struct SoundIoPrivate*)in_client_data;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
sica->device_scan_queued.store(true);
soundio_os_cond_signal(sica->scan_devices_cond, nullptr);
SOUNDIO_ATOMIC_STORE(sica->device_scan_queued, true);
soundio_os_cond_signal(sica->scan_devices_cond, NULL);
return noErr;
}
@ -111,30 +113,30 @@ static OSStatus on_devices_changed(AudioObjectID in_object_id, UInt32 in_number_
static OSStatus on_service_restarted(AudioObjectID in_object_id, UInt32 in_number_addresses,
const AudioObjectPropertyAddress in_addresses[], void *in_client_data)
{
SoundIoPrivate *si = (SoundIoPrivate*)in_client_data;
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
struct SoundIoPrivate *si = (struct SoundIoPrivate*)in_client_data;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
sica->service_restarted.store(true);
soundio_os_cond_signal(sica->scan_devices_cond, nullptr);
SOUNDIO_ATOMIC_STORE(sica->service_restarted, true);
soundio_os_cond_signal(sica->scan_devices_cond, NULL);
return noErr;
}
static void unsubscribe_device_listeners(SoundIoPrivate *si) {
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
static void unsubscribe_device_listeners(struct SoundIoPrivate *si) {
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
for (int device_index = 0; device_index < sica->registered_listeners.length; device_index += 1) {
AudioDeviceID device_id = sica->registered_listeners.at(device_index);
for (int i = 0; i < array_length(device_listen_props); i += 1) {
AudioDeviceID device_id = SoundIoListAudioDeviceID_val_at(&sica->registered_listeners, device_index);
for (int i = 0; i < ARRAY_LENGTH(device_listen_props); i += 1) {
AudioObjectRemovePropertyListener(device_id, &device_listen_props[i],
on_devices_changed, si);
}
}
sica->registered_listeners.clear();
SoundIoListAudioDeviceID_clear(&sica->registered_listeners);
}
static void destroy_ca(struct SoundIoPrivate *si) {
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
AudioObjectPropertyAddress prop_address = {
kAudioHardwarePropertyDevices,
@ -147,11 +149,11 @@ static void destroy_ca(struct SoundIoPrivate *si) {
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop_address, on_service_restarted, si);
unsubscribe_device_listeners(si);
sica->registered_listeners.deinit();
SoundIoListAudioDeviceID_deinit(&sica->registered_listeners);
if (sica->thread) {
sica->abort_flag.clear();
soundio_os_cond_signal(sica->scan_devices_cond, nullptr);
atomic_flag_clear(&sica->abort_flag);
soundio_os_cond_signal(sica->scan_devices_cond, NULL);
soundio_os_thread_destroy(sica->thread);
}
@ -178,7 +180,7 @@ static int from_cf_string(CFStringRef string_ref, char **out_str, int *out_str_l
CFIndex length = CFStringGetLength(string_ref);
CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
char *buf = allocate_nonzero<char>(max_size);
char *buf = ALLOCATE_NONZERO(char, max_size);
if (!buf)
return SoundIoErrorNoMem;
@ -192,12 +194,12 @@ static int from_cf_string(CFStringRef string_ref, char **out_str, int *out_str_l
return 0;
}
static int aim_to_scope(SoundIoDeviceAim aim) {
static int aim_to_scope(enum SoundIoDeviceAim aim) {
return (aim == SoundIoDeviceAimInput) ?
kAudioObjectPropertyScopeInput : kAudioObjectPropertyScopeOutput;
}
static SoundIoChannelId from_channel_descr(const AudioChannelDescription *descr) {
static enum SoundIoChannelId from_channel_descr(const AudioChannelDescription *descr) {
switch (descr->mChannelLabel) {
default: return SoundIoChannelIdInvalid;
case kAudioChannelLabel_Left: return SoundIoChannelIdFrontLeft;
@ -274,7 +276,7 @@ static SoundIoChannelId from_channel_descr(const AudioChannelDescription *descr)
// * SoundIoErrorIncompatibleDevice
// This does not handle all the possible layout enum values and it does not
// handle channel bitmaps.
static int from_coreaudio_layout(const AudioChannelLayout *ca_layout, SoundIoChannelLayout *layout) {
static int from_coreaudio_layout(const AudioChannelLayout *ca_layout, struct SoundIoChannelLayout *layout) {
switch (ca_layout->mChannelLayoutTag) {
case kAudioChannelLayoutTag_UseChannelDescriptions:
{
@ -377,15 +379,15 @@ static bool all_channels_invalid(const struct SoundIoChannelLayout *layout) {
}
struct RefreshDevices {
SoundIoPrivate *si;
SoundIoDevicesInfo *devices_info;
struct SoundIoPrivate *si;
struct SoundIoDevicesInfo *devices_info;
int devices_size;
AudioObjectID *devices;
CFStringRef string_ref;
char *device_name;
int device_name_len;
AudioBufferList *buffer_list;
SoundIoDevice *device;
struct SoundIoDevice *device;
AudioChannelLayout *audio_channel_layout;
char *device_uid;
int device_uid_len;
@ -393,7 +395,7 @@ struct RefreshDevices {
bool ok;
};
static void deinit_refresh_devices(RefreshDevices *rd) {
static void deinit_refresh_devices(struct RefreshDevices *rd) {
if (!rd->ok)
unsubscribe_device_listeners(rd->si);
soundio_destroy_devices_info(rd->devices_info);
@ -409,8 +411,8 @@ static void deinit_refresh_devices(RefreshDevices *rd) {
}
static int refresh_devices(struct SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
struct SoundIo *soundio = &si->pub;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
UInt32 io_size;
OSStatus os_err;
@ -418,10 +420,10 @@ static int refresh_devices(struct SoundIoPrivate *si) {
unsubscribe_device_listeners(si);
RefreshDevices rd = {0};
struct RefreshDevices rd = {0};
rd.si = si;
if (!(rd.devices_info = allocate<SoundIoDevicesInfo>(1))) {
if (!(rd.devices_info = ALLOCATE(struct SoundIoDevicesInfo, 1))) {
deinit_refresh_devices(&rd);
return SoundIoErrorNoMem;
}
@ -433,7 +435,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
};
if ((os_err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
&prop_address, 0, nullptr, &io_size)))
&prop_address, 0, NULL, &io_size)))
{
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
@ -445,13 +447,13 @@ static int refresh_devices(struct SoundIoPrivate *si) {
int device_count = io_size / (UInt32)sizeof(AudioObjectID);
if (device_count >= 1) {
rd.devices_size = io_size;
rd.devices = (AudioObjectID *)allocate<char>(rd.devices_size);
rd.devices = (AudioObjectID *)ALLOCATE(char, rd.devices_size);
if (!rd.devices) {
deinit_refresh_devices(&rd);
return SoundIoErrorNoMem;
}
if ((os_err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop_address, 0, NULL,
&io_size, rd.devices)))
{
deinit_refresh_devices(&rd);
@ -462,7 +464,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
io_size = sizeof(AudioObjectID);
prop_address.mSelector = kAudioHardwarePropertyDefaultInputDevice;
if ((os_err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop_address,
0, nullptr, &io_size, &default_input_id)))
0, NULL, &io_size, &default_input_id)))
{
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
@ -471,7 +473,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
io_size = sizeof(AudioObjectID);
prop_address.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
if ((os_err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop_address,
0, nullptr, &io_size, &default_output_id)))
0, NULL, &io_size, &default_output_id)))
{
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
@ -481,8 +483,8 @@ static int refresh_devices(struct SoundIoPrivate *si) {
for (int device_i = 0; device_i < device_count; device_i += 1) {
AudioObjectID device_id = rd.devices[device_i];
for (int i = 0; i < array_length(device_listen_props); i += 1) {
if ((err = sica->registered_listeners.add_one())) {
for (int i = 0; i < ARRAY_LENGTH(device_listen_props); i += 1) {
if ((err = SoundIoListAudioDeviceID_add_one(&sica->registered_listeners))) {
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
}
@ -492,7 +494,8 @@ static int refresh_devices(struct SoundIoPrivate *si) {
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
}
sica->registered_listeners.last() = device_id;
AudioDeviceID *last_device_id = SoundIoListAudioDeviceID_last_ptr(&sica->registered_listeners);
*last_device_id = device_id;
}
prop_address.mSelector = kAudioObjectPropertyName;
@ -501,17 +504,17 @@ static int refresh_devices(struct SoundIoPrivate *si) {
io_size = sizeof(CFStringRef);
if (rd.string_ref) {
CFRelease(rd.string_ref);
rd.string_ref = nullptr;
rd.string_ref = NULL;
}
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address,
0, nullptr, &io_size, &rd.string_ref)))
0, NULL, &io_size, &rd.string_ref)))
{
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
}
free(rd.device_name);
rd.device_name = nullptr;
rd.device_name = NULL;
if ((err = from_cf_string(rd.string_ref, &rd.device_name, &rd.device_name_len))) {
deinit_refresh_devices(&rd);
return err;
@ -523,43 +526,43 @@ static int refresh_devices(struct SoundIoPrivate *si) {
io_size = sizeof(CFStringRef);
if (rd.string_ref) {
CFRelease(rd.string_ref);
rd.string_ref = nullptr;
rd.string_ref = NULL;
}
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address,
0, nullptr, &io_size, &rd.string_ref)))
0, NULL, &io_size, &rd.string_ref)))
{
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
}
free(rd.device_uid);
rd.device_uid = nullptr;
rd.device_uid = NULL;
if ((err = from_cf_string(rd.string_ref, &rd.device_uid, &rd.device_uid_len))) {
deinit_refresh_devices(&rd);
return err;
}
for (int aim_i = 0; aim_i < array_length(aims); aim_i += 1) {
SoundIoDeviceAim aim = aims[aim_i];
for (int aim_i = 0; aim_i < ARRAY_LENGTH(aims); aim_i += 1) {
enum SoundIoDeviceAim aim = aims[aim_i];
io_size = 0;
prop_address.mSelector = kAudioDevicePropertyStreamConfiguration;
prop_address.mScope = aim_to_scope(aim);
prop_address.mElement = kAudioObjectPropertyElementMaster;
if ((os_err = AudioObjectGetPropertyDataSize(device_id, &prop_address, 0, nullptr, &io_size))) {
if ((os_err = AudioObjectGetPropertyDataSize(device_id, &prop_address, 0, NULL, &io_size))) {
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
}
free(rd.buffer_list);
rd.buffer_list = (AudioBufferList*)allocate_nonzero<char>(io_size);
rd.buffer_list = (AudioBufferList*)ALLOCATE_NONZERO(char, io_size);
if (!rd.buffer_list) {
deinit_refresh_devices(&rd);
return SoundIoErrorNoMem;
}
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, NULL,
&io_size, rd.buffer_list)))
{
deinit_refresh_devices(&rd);
@ -574,12 +577,12 @@ static int refresh_devices(struct SoundIoPrivate *si) {
if (channel_count <= 0)
continue;
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1);
if (!dev) {
deinit_refresh_devices(&rd);
return SoundIoErrorNoMem;
}
SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
struct SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
dca->device_id = device_id;
assert(!rd.device);
rd.device = &dev->pub;
@ -599,14 +602,14 @@ static int refresh_devices(struct SoundIoPrivate *si) {
prop_address.mScope = aim_to_scope(aim);
prop_address.mElement = kAudioObjectPropertyElementMaster;
if (!(os_err = AudioObjectGetPropertyDataSize(device_id, &prop_address,
0, nullptr, &io_size)))
0, NULL, &io_size)))
{
rd.audio_channel_layout = (AudioChannelLayout *)allocate<char>(io_size);
rd.audio_channel_layout = (AudioChannelLayout *)ALLOCATE(char, io_size);
if (!rd.audio_channel_layout) {
deinit_refresh_devices(&rd);
return SoundIoErrorNoMem;
}
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, NULL,
&io_size, rd.audio_channel_layout)))
{
deinit_refresh_devices(&rd);
@ -635,7 +638,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
prop_address.mElement = kAudioObjectPropertyElementMaster;
io_size = sizeof(double);
double value;
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, NULL,
&io_size, &value)))
{
deinit_refresh_devices(&rd);
@ -659,21 +662,21 @@ static int refresh_devices(struct SoundIoPrivate *si) {
prop_address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
prop_address.mScope = aim_to_scope(aim);
prop_address.mElement = kAudioObjectPropertyElementMaster;
if ((os_err = AudioObjectGetPropertyDataSize(device_id, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyDataSize(device_id, &prop_address, 0, NULL,
&io_size)))
{
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
}
int avr_array_len = io_size / sizeof(AudioValueRange);
rd.avr_array = (AudioValueRange*)allocate<char>(io_size);
rd.avr_array = (AudioValueRange*)ALLOCATE(char, io_size);
if (!rd.avr_array) {
deinit_refresh_devices(&rd);
return SoundIoErrorNoMem;
}
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, NULL,
&io_size, rd.avr_array)))
{
deinit_refresh_devices(&rd);
@ -687,7 +690,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
rd.device->sample_rates[0].max = (int)(rd.avr_array[0].mMaximum);
} else {
rd.device->sample_rate_count = avr_array_len;
rd.device->sample_rates = allocate<SoundIoSampleRateRange>(avr_array_len);
rd.device->sample_rates = ALLOCATE(struct SoundIoSampleRateRange, avr_array_len);
if (!rd.device->sample_rates) {
deinit_refresh_devices(&rd);
return SoundIoErrorNoMem;
@ -707,7 +710,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
prop_address.mElement = kAudioObjectPropertyElementMaster;
io_size = sizeof(UInt32);
UInt32 buffer_frame_size;
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, NULL,
&io_size, &buffer_frame_size)))
{
deinit_refresh_devices(&rd);
@ -721,7 +724,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
prop_address.mElement = kAudioObjectPropertyElementMaster;
io_size = sizeof(AudioValueRange);
AudioValueRange avr;
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, NULL,
&io_size, &avr)))
{
deinit_refresh_devices(&rd);
@ -734,14 +737,14 @@ static int refresh_devices(struct SoundIoPrivate *si) {
prop_address.mScope = aim_to_scope(aim);
prop_address.mElement = kAudioObjectPropertyElementMaster;
io_size = sizeof(UInt32);
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, nullptr,
if ((os_err = AudioObjectGetPropertyData(device_id, &prop_address, 0, NULL,
&io_size, &dca->latency_frames)))
{
deinit_refresh_devices(&rd);
return SoundIoErrorOpeningDevice;
}
SoundIoList<SoundIoDevice *> *device_list;
struct SoundIoListDevicePtr *device_list;
if (rd.device->aim == SoundIoDeviceAimOutput) {
device_list = &rd.devices_info->output_devices;
if (device_id == default_output_id)
@ -753,11 +756,11 @@ static int refresh_devices(struct SoundIoPrivate *si) {
rd.devices_info->default_input_index = device_list->length;
}
if ((err = device_list->append(rd.device))) {
if ((err = SoundIoListDevicePtr_append(device_list, rd.device))) {
deinit_refresh_devices(&rd);
return err;
}
rd.device = nullptr;
rd.device = NULL;
}
}
@ -766,36 +769,36 @@ static int refresh_devices(struct SoundIoPrivate *si) {
sica->ready_devices_info = rd.devices_info;
soundio_os_mutex_unlock(sica->mutex);
rd.devices_info = nullptr;
rd.devices_info = NULL;
rd.ok = true;
deinit_refresh_devices(&rd);
return 0;
}
static void shutdown_backend(SoundIoPrivate *si, int err) {
SoundIo *soundio = &si->pub;
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
static void shutdown_backend(struct SoundIoPrivate *si, int err) {
struct SoundIo *soundio = &si->pub;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
soundio_os_mutex_lock(sica->mutex);
sica->shutdown_err = err;
sica->have_devices_flag.store(true);
SOUNDIO_ATOMIC_STORE(sica->have_devices_flag, true);
soundio_os_mutex_unlock(sica->mutex);
soundio_os_cond_signal(sica->cond, nullptr);
soundio_os_cond_signal(sica->have_devices_cond, nullptr);
soundio_os_cond_signal(sica->cond, NULL);
soundio_os_cond_signal(sica->have_devices_cond, NULL);
soundio->on_events_signal(soundio);
}
static void flush_events_ca(struct SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
struct SoundIo *soundio = &si->pub;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
// block until have devices
while (!sica->have_devices_flag.load())
soundio_os_cond_wait(sica->have_devices_cond, nullptr);
while (!SOUNDIO_ATOMIC_LOAD(sica->have_devices_flag))
soundio_os_cond_wait(sica->have_devices_cond, NULL);
bool change = false;
bool cb_shutdown = false;
SoundIoDevicesInfo *old_devices_info = nullptr;
struct SoundIoDevicesInfo *old_devices_info = NULL;
soundio_os_mutex_lock(sica->mutex);
@ -805,7 +808,7 @@ static void flush_events_ca(struct SoundIoPrivate *si) {
} else if (sica->ready_devices_info) {
old_devices_info = si->safe_devices_info;
si->safe_devices_info = sica->ready_devices_info;
sica->ready_devices_info = nullptr;
sica->ready_devices_info = NULL;
change = true;
}
@ -820,65 +823,65 @@ static void flush_events_ca(struct SoundIoPrivate *si) {
}
static void wait_events_ca(struct SoundIoPrivate *si) {
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
flush_events_ca(si);
soundio_os_cond_wait(sica->cond, nullptr);
soundio_os_cond_wait(sica->cond, NULL);
}
static void wakeup_ca(struct SoundIoPrivate *si) {
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
soundio_os_cond_signal(sica->cond, nullptr);
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
soundio_os_cond_signal(sica->cond, NULL);
}
static void force_device_scan_ca(struct SoundIoPrivate *si) {
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
sica->device_scan_queued.store(true);
soundio_os_cond_signal(sica->scan_devices_cond, nullptr);
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
SOUNDIO_ATOMIC_STORE(sica->device_scan_queued, true);
soundio_os_cond_signal(sica->scan_devices_cond, NULL);
}
static void device_thread_run(void *arg) {
SoundIoPrivate *si = (SoundIoPrivate *)arg;
SoundIo *soundio = &si->pub;
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)arg;
struct SoundIo *soundio = &si->pub;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
int err;
for (;;) {
if (!sica->abort_flag.test_and_set())
if (!atomic_flag_test_and_set(&sica->abort_flag))
break;
if (sica->service_restarted.load()) {
if (SOUNDIO_ATOMIC_LOAD(sica->service_restarted)) {
shutdown_backend(si, SoundIoErrorBackendDisconnected);
return;
}
if (sica->device_scan_queued.exchange(false)) {
if (SOUNDIO_ATOMIC_EXCHANGE(sica->device_scan_queued, false)) {
err = refresh_devices(si);
if (err) {
shutdown_backend(si, err);
return;
}
if (!sica->have_devices_flag.exchange(true))
soundio_os_cond_signal(sica->have_devices_cond, nullptr);
soundio_os_cond_signal(sica->cond, nullptr);
if (!SOUNDIO_ATOMIC_EXCHANGE(sica->have_devices_flag, true))
soundio_os_cond_signal(sica->have_devices_cond, NULL);
soundio_os_cond_signal(sica->cond, NULL);
soundio->on_events_signal(soundio);
}
soundio_os_cond_wait(sica->scan_devices_cond, nullptr);
soundio_os_cond_wait(sica->scan_devices_cond, NULL);
}
}
static OSStatus on_outstream_device_overload(AudioObjectID in_object_id, UInt32 in_number_addresses,
const AudioObjectPropertyAddress in_addresses[], void *in_client_data)
{
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)in_client_data;
SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)in_client_data;
struct SoundIoOutStream *outstream = &os->pub;
outstream->underflow_callback(outstream);
return noErr;
}
static void outstream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
SoundIoOutStream *outstream = &os->pub;
SoundIoDevice *device = outstream->device;
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoDevice *device = outstream->device;
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
struct SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
AudioObjectPropertyAddress prop_address = {
kAudioDeviceProcessorOverload,
@ -890,7 +893,7 @@ static void outstream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoOutStr
if (osca->instance) {
AudioOutputUnitStop(osca->instance);
AudioComponentInstanceDispose(osca->instance);
osca->instance = nullptr;
osca->instance = NULL;
}
}
@ -898,30 +901,30 @@ static OSStatus write_callback_ca(void *userdata, AudioUnitRenderActionFlags *io
const AudioTimeStamp *in_time_stamp, UInt32 in_bus_number, UInt32 in_number_frames,
AudioBufferList *io_data)
{
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *) userdata;
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *) userdata;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
osca->io_data = io_data;
osca->buffer_index = 0;
osca->frames_left = in_number_frames;
outstream->write_callback(outstream, osca->frames_left, osca->frames_left);
osca->io_data = nullptr;
osca->io_data = NULL;
return noErr;
}
static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
SoundIoOutStream *outstream = &os->pub;
SoundIoDevice *device = outstream->device;
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoDevice *device = outstream->device;
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
struct SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
if (outstream->software_latency == 0.0)
outstream->software_latency = device->software_latency_current;
outstream->software_latency = clamp(
outstream->software_latency = soundio_double_clamp(
device->software_latency_min,
outstream->software_latency,
device->software_latency_max);
@ -931,7 +934,7 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP
desc.componentSubType = kAudioUnitSubType_HALOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
AudioComponent component = AudioComponentFindNext(nullptr, &desc);
AudioComponent component = AudioComponentFindNext(NULL, &desc);
if (!component) {
outstream_destroy_ca(si, os);
return SoundIoErrorOpeningDevice;
@ -987,7 +990,7 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP
};
UInt32 buffer_frame_size = outstream->software_latency * outstream->sample_rate;
if ((os_err = AudioObjectSetPropertyData(dca->device_id, &prop_address,
0, nullptr, sizeof(UInt32), &buffer_frame_size)))
0, NULL, sizeof(UInt32), &buffer_frame_size)))
{
outstream_destroy_ca(si, os);
return SoundIoErrorOpeningDevice;
@ -1009,7 +1012,7 @@ static int outstream_open_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamP
}
static int outstream_pause_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
OSStatus os_err;
if (pause) {
if ((os_err = AudioOutputUnitStop(osca->instance))) {
@ -1029,10 +1032,10 @@ static int outstream_start_ca(struct SoundIoPrivate *si, struct SoundIoOutStream
}
static int outstream_begin_write_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
SoundIoChannelArea **out_areas, int *frame_count)
struct SoundIoChannelArea **out_areas, int *frame_count)
{
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
if (osca->buffer_index >= osca->io_data->mNumberBuffers)
return SoundIoErrorInvalid;
@ -1054,7 +1057,7 @@ static int outstream_begin_write_ca(struct SoundIoPrivate *si, struct SoundIoOut
}
static int outstream_end_write_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
osca->buffer_index += 1;
osca->frames_left -= osca->write_frame_count;
assert(osca->frames_left >= 0);
@ -1068,7 +1071,7 @@ static int outstream_clear_buffer_ca(struct SoundIoPrivate *si, struct SoundIoOu
static int outstream_get_latency_ca(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
double *out_latency)
{
SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
struct SoundIoOutStreamCoreAudio *osca = &os->backend_data.coreaudio;
*out_latency = osca->hardware_latency;
return 0;
}
@ -1076,18 +1079,18 @@ static int outstream_get_latency_ca(struct SoundIoPrivate *si, struct SoundIoOut
static OSStatus on_instream_device_overload(AudioObjectID in_object_id, UInt32 in_number_addresses,
const AudioObjectPropertyAddress in_addresses[], void *in_client_data)
{
SoundIoInStreamPrivate *os = (SoundIoInStreamPrivate *)in_client_data;
SoundIoInStream *instream = &os->pub;
struct SoundIoInStreamPrivate *os = (struct SoundIoInStreamPrivate *)in_client_data;
struct SoundIoInStream *instream = &os->pub;
instream->overflow_callback(instream);
return noErr;
}
static void instream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
SoundIoInStream *instream = &is->pub;
SoundIoDevice *device = instream->device;
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
struct SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoDevice *device = instream->device;
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
struct SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
AudioObjectPropertyAddress prop_address = {
kAudioDeviceProcessorOverload,
@ -1099,23 +1102,23 @@ static void instream_destroy_ca(struct SoundIoPrivate *si, struct SoundIoInStrea
if (isca->instance) {
AudioOutputUnitStop(isca->instance);
AudioComponentInstanceDispose(isca->instance);
isca->instance = nullptr;
isca->instance = NULL;
}
free(isca->buffer_list);
isca->buffer_list = nullptr;
isca->buffer_list = NULL;
}
static OSStatus read_callback_ca(void *userdata, AudioUnitRenderActionFlags *io_action_flags,
const AudioTimeStamp *in_time_stamp, UInt32 in_bus_number, UInt32 in_number_frames,
AudioBufferList *io_data)
{
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *) userdata;
SoundIoInStream *instream = &is->pub;
SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *) userdata;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
for (int i = 0; i < isca->buffer_list->mNumberBuffers; i += 1) {
isca->buffer_list->mBuffers[i].mData = nullptr;
isca->buffer_list->mBuffers[i].mData = NULL;
}
OSStatus os_err;
@ -1151,18 +1154,18 @@ static OSStatus read_callback_ca(void *userdata, AudioUnitRenderActionFlags *io_
}
static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
SoundIoInStream *instream = &is->pub;
SoundIoDevice *device = instream->device;
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
struct SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoDevice *device = instream->device;
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
struct SoundIoDeviceCoreAudio *dca = &dev->backend_data.coreaudio;
UInt32 io_size;
OSStatus os_err;
if (instream->software_latency == 0.0)
instream->software_latency = device->software_latency_current;
instream->software_latency = clamp(
instream->software_latency = soundio_double_clamp(
device->software_latency_min,
instream->software_latency,
device->software_latency_max);
@ -1174,20 +1177,20 @@ static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPri
prop_address.mElement = kAudioObjectPropertyElementMaster;
io_size = 0;
if ((os_err = AudioObjectGetPropertyDataSize(dca->device_id, &prop_address,
0, nullptr, &io_size)))
0, NULL, &io_size)))
{
instream_destroy_ca(si, is);
return SoundIoErrorOpeningDevice;
}
isca->buffer_list = (AudioBufferList*)allocate_nonzero<char>(io_size);
isca->buffer_list = (AudioBufferList*)ALLOCATE_NONZERO(char, io_size);
if (!isca->buffer_list) {
instream_destroy_ca(si, is);
return SoundIoErrorNoMem;
}
if ((os_err = AudioObjectGetPropertyData(dca->device_id, &prop_address,
0, nullptr, &io_size, isca->buffer_list)))
0, NULL, &io_size, isca->buffer_list)))
{
instream_destroy_ca(si, is);
return SoundIoErrorOpeningDevice;
@ -1199,7 +1202,7 @@ static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPri
desc.componentSubType = kAudioUnitSubType_HALOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
AudioComponent component = AudioComponentFindNext(nullptr, &desc);
AudioComponent component = AudioComponentFindNext(NULL, &desc);
if (!component) {
instream_destroy_ca(si, is);
return SoundIoErrorOpeningDevice;
@ -1270,7 +1273,7 @@ static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPri
prop_address.mElement = INPUT_ELEMENT;
UInt32 buffer_frame_size = instream->software_latency * instream->sample_rate;
if ((os_err = AudioObjectSetPropertyData(dca->device_id, &prop_address,
0, nullptr, sizeof(UInt32), &buffer_frame_size)))
0, NULL, sizeof(UInt32), &buffer_frame_size)))
{
instream_destroy_ca(si, is);
return SoundIoErrorOpeningDevice;
@ -1291,7 +1294,7 @@ static int instream_open_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPri
}
static int instream_pause_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
struct SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
OSStatus os_err;
if (pause) {
if ((os_err = AudioOutputUnitStop(isca->instance))) {
@ -1311,9 +1314,9 @@ static int instream_start_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPr
}
static int instream_begin_read_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
SoundIoChannelArea **out_areas, int *frame_count)
struct SoundIoChannelArea **out_areas, int *frame_count)
{
SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
struct SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
if (*frame_count != isca->frames_left)
return SoundIoErrorInvalid;
@ -1324,7 +1327,7 @@ static int instream_begin_read_ca(struct SoundIoPrivate *si, struct SoundIoInStr
}
static int instream_end_read_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
struct SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
isca->frames_left = 0;
return 0;
}
@ -1332,20 +1335,20 @@ static int instream_end_read_ca(struct SoundIoPrivate *si, struct SoundIoInStrea
static int instream_get_latency_ca(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
double *out_latency)
{
SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
struct SoundIoInStreamCoreAudio *isca = &is->backend_data.coreaudio;
*out_latency = isca->hardware_latency;
return 0;
}
int soundio_coreaudio_init(SoundIoPrivate *si) {
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
int soundio_coreaudio_init(struct SoundIoPrivate *si) {
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
int err;
sica->have_devices_flag.store(false);
sica->device_scan_queued.store(true);
sica->service_restarted.store(false);
sica->abort_flag.test_and_set();
SOUNDIO_ATOMIC_STORE(sica->have_devices_flag, false);
SOUNDIO_ATOMIC_STORE(sica->device_scan_queued, true);
SOUNDIO_ATOMIC_STORE(sica->service_restarted, false);
atomic_flag_test_and_set(&sica->abort_flag);
sica->mutex = soundio_os_mutex_create();
if (!sica->mutex) {
@ -1391,7 +1394,7 @@ int soundio_coreaudio_init(SoundIoPrivate *si) {
return SoundIoErrorSystemResources;
}
if ((err = soundio_os_thread_create(device_thread_run, si, nullptr, &sica->thread))) {
if ((err = soundio_os_thread_create(device_thread_run, si, NULL, &sica->thread))) {
destroy_ca(si);
return err;
}

View file

@ -5,17 +5,18 @@
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_COREAUDIO_HPP
#define SOUNDIO_COREAUDIO_HPP
#ifndef SOUNDIO_COREAUDIO_H
#define SOUNDIO_COREAUDIO_H
#include "soundio_private.h"
#include "soundio_internal.h"
#include "os.h"
#include "atomics.hpp"
#include "list.hpp"
#include "list.h"
#include "atomics.h"
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
struct SoundIoPrivate;
int soundio_coreaudio_init(struct SoundIoPrivate *si);
struct SoundIoDeviceCoreAudio {
@ -23,21 +24,23 @@ struct SoundIoDeviceCoreAudio {
UInt32 latency_frames;
};
SOUNDIO_MAKE_LIST_STRUCT(AudioDeviceID, SoundIoListAudioDeviceID, SOUNDIO_LIST_STATIC)
struct SoundIoCoreAudio {
SoundIoOsMutex *mutex;
SoundIoOsCond *cond;
struct SoundIoOsMutex *mutex;
struct SoundIoOsCond *cond;
struct SoundIoOsThread *thread;
atomic_flag abort_flag;
// this one is ready to be read with flush_events. protected by mutex
struct SoundIoDevicesInfo *ready_devices_info;
atomic_bool have_devices_flag;
SoundIoOsCond *have_devices_cond;
SoundIoOsCond *scan_devices_cond;
SoundIoList<AudioDeviceID> registered_listeners;
struct SoundIoAtomicBool have_devices_flag;
struct SoundIoOsCond *have_devices_cond;
struct SoundIoOsCond *scan_devices_cond;
struct SoundIoListAudioDeviceID registered_listeners;
atomic_bool device_scan_queued;
atomic_bool service_restarted;
struct SoundIoAtomicBool device_scan_queued;
struct SoundIoAtomicBool service_restarted;
int shutdown_err;
bool emitted_shutdown_cb;
};
@ -49,7 +52,7 @@ struct SoundIoOutStreamCoreAudio {
int frames_left;
int write_frame_count;
double hardware_latency;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
struct SoundIoInStreamCoreAudio {
@ -57,7 +60,7 @@ struct SoundIoInStreamCoreAudio {
AudioBufferList *buffer_list;
int frames_left;
double hardware_latency;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
#endif

View file

@ -5,16 +5,16 @@
* See http://opensource.org/licenses/MIT
*/
#include "dummy.hpp"
#include "soundio.hpp"
#include "dummy.h"
#include "soundio_private.h"
#include <stdio.h>
#include <string.h>
static void playback_thread_run(void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)arg;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
int free_bytes = soundio_ring_buffer_capacity(&osd->ring_buffer) - fill_bytes;
@ -25,14 +25,14 @@ static void playback_thread_run(void *arg) {
double start_time = soundio_os_get_time();
long frames_consumed = 0;
while (osd->abort_flag.test_and_set()) {
while (atomic_flag_test_and_set(&osd->abort_flag)) {
double now = soundio_os_get_time();
double time_passed = now - start_time;
double next_period = start_time +
ceil_dbl(time_passed / osd->period_duration) * osd->period_duration;
double relative_time = next_period - now;
soundio_os_cond_timed_wait(osd->cond, nullptr, relative_time);
if (!osd->clear_buffer_flag.test_and_set()) {
soundio_os_cond_timed_wait(osd->cond, NULL, relative_time);
if (!atomic_flag_test_and_set(&osd->clear_buffer_flag)) {
soundio_ring_buffer_clear(&osd->ring_buffer);
int free_bytes = soundio_ring_buffer_capacity(&osd->ring_buffer);
int free_frames = free_bytes / outstream->bytes_per_frame;
@ -44,7 +44,7 @@ static void playback_thread_run(void *arg) {
continue;
}
if (osd->pause_requested.load()) {
if (SOUNDIO_ATOMIC_LOAD(osd->pause_requested)) {
start_time = now;
frames_consumed = 0;
continue;
@ -58,7 +58,7 @@ static void playback_thread_run(void *arg) {
double total_time = soundio_os_get_time() - start_time;
long total_frames = total_time * outstream->sample_rate;
int frames_to_kill = total_frames - frames_consumed;
int read_count = min(frames_to_kill, fill_frames);
int read_count = soundio_int_min(frames_to_kill, fill_frames);
int byte_count = read_count * outstream->bytes_per_frame;
soundio_ring_buffer_advance_read_ptr(&osd->ring_buffer, byte_count);
frames_consumed += read_count;
@ -78,21 +78,21 @@ static void playback_thread_run(void *arg) {
}
static void capture_thread_run(void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg;
SoundIoInStream *instream = &is->pub;
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)arg;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
long frames_consumed = 0;
double start_time = soundio_os_get_time();
while (isd->abort_flag.test_and_set()) {
while (atomic_flag_test_and_set(&isd->abort_flag)) {
double now = soundio_os_get_time();
double time_passed = now - start_time;
double next_period = start_time +
ceil_dbl(time_passed / isd->period_duration) * isd->period_duration;
double relative_time = next_period - now;
soundio_os_cond_timed_wait(isd->cond, nullptr, relative_time);
soundio_os_cond_timed_wait(isd->cond, NULL, relative_time);
if (isd->pause_requested.load()) {
if (SOUNDIO_ATOMIC_LOAD(isd->pause_requested)) {
start_time = now;
frames_consumed = 0;
continue;
@ -106,7 +106,7 @@ static void capture_thread_run(void *arg) {
double total_time = soundio_os_get_time() - start_time;
long total_frames = total_time * instream->sample_rate;
int frames_to_kill = total_frames - frames_consumed;
int write_count = min(frames_to_kill, free_frames);
int write_count = soundio_int_min(frames_to_kill, free_frames);
int byte_count = write_count * instream->bytes_per_frame;
soundio_ring_buffer_advance_write_ptr(&isd->ring_buffer, byte_count);
frames_consumed += write_count;
@ -123,8 +123,8 @@ static void capture_thread_run(void *arg) {
}
}
static void destroy_dummy(SoundIoPrivate *si) {
SoundIoDummy *sid = &si->backend_data.dummy;
static void destroy_dummy(struct SoundIoPrivate *si) {
struct SoundIoDummy *sid = &si->backend_data.dummy;
if (sid->cond)
soundio_os_cond_destroy(sid->cond);
@ -133,55 +133,57 @@ static void destroy_dummy(SoundIoPrivate *si) {
soundio_os_mutex_destroy(sid->mutex);
}
static void flush_events_dummy(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoDummy *sid = &si->backend_data.dummy;
static void flush_events_dummy(struct SoundIoPrivate *si) {
struct SoundIo *soundio = &si->pub;
struct SoundIoDummy *sid = &si->backend_data.dummy;
if (sid->devices_emitted)
return;
sid->devices_emitted = true;
soundio->on_devices_change(soundio);
}
static void wait_events_dummy(SoundIoPrivate *si) {
SoundIoDummy *sid = &si->backend_data.dummy;
static void wait_events_dummy(struct SoundIoPrivate *si) {
struct SoundIoDummy *sid = &si->backend_data.dummy;
flush_events_dummy(si);
soundio_os_cond_wait(sid->cond, nullptr);
soundio_os_cond_wait(sid->cond, NULL);
}
static void wakeup_dummy(SoundIoPrivate *si) {
SoundIoDummy *sid = &si->backend_data.dummy;
soundio_os_cond_signal(sid->cond, nullptr);
static void wakeup_dummy(struct SoundIoPrivate *si) {
struct SoundIoDummy *sid = &si->backend_data.dummy;
soundio_os_cond_signal(sid->cond, NULL);
}
static void force_device_scan_dummy(SoundIoPrivate *si) {
static void force_device_scan_dummy(struct SoundIoPrivate *si) {
// nothing to do; dummy devices never change
}
static void outstream_destroy_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
static void outstream_destroy_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
if (osd->thread) {
osd->abort_flag.clear();
soundio_os_cond_signal(osd->cond, nullptr);
atomic_flag_clear(&osd->abort_flag);
soundio_os_cond_signal(osd->cond, NULL);
soundio_os_thread_destroy(osd->thread);
osd->thread = nullptr;
osd->thread = NULL;
}
soundio_os_cond_destroy(osd->cond);
osd->cond = nullptr;
osd->cond = NULL;
soundio_ring_buffer_deinit(&osd->ring_buffer);
}
static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
SoundIoOutStream *outstream = &os->pub;
SoundIoDevice *device = outstream->device;
static int outstream_open_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoDevice *device = outstream->device;
osd->clear_buffer_flag.test_and_set();
osd->pause_requested.store(false);
atomic_flag_test_and_set(&osd->clear_buffer_flag);
SOUNDIO_ATOMIC_STORE(osd->pause_requested, false);
if (outstream->software_latency == 0.0)
outstream->software_latency = clamp(device->software_latency_min, 1.0, device->software_latency_max);
if (outstream->software_latency == 0.0) {
outstream->software_latency = soundio_double_clamp(
device->software_latency_min, 1.0, device->software_latency_max);
}
osd->period_duration = outstream->software_latency / 2.0;
@ -205,16 +207,16 @@ static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
}
static int outstream_pause_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
osd->pause_requested.store(pause);
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
SOUNDIO_ATOMIC_STORE(osd->pause_requested, pause);
return 0;
}
static int outstream_start_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
SoundIo *soundio = &si->pub;
static int outstream_start_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
struct SoundIo *soundio = &si->pub;
assert(!osd->thread);
osd->abort_flag.test_and_set();
atomic_flag_test_and_set(&osd->abort_flag);
int err;
if ((err = soundio_os_thread_create(playback_thread_run, os,
soundio->emit_rtprio_warning, &osd->thread)))
@ -224,11 +226,11 @@ static int outstream_start_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os
return 0;
}
static int outstream_begin_write_dummy(SoundIoPrivate *si,
SoundIoOutStreamPrivate *os, SoundIoChannelArea **out_areas, int *frame_count)
static int outstream_begin_write_dummy(struct SoundIoPrivate *si,
struct SoundIoOutStreamPrivate *os, struct SoundIoChannelArea **out_areas, int *frame_count)
{
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
if (*frame_count > osd->frames_left)
return SoundIoErrorInvalid;
@ -244,55 +246,57 @@ static int outstream_begin_write_dummy(SoundIoPrivate *si,
return 0;
}
static int outstream_end_write_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
SoundIoOutStream *outstream = &os->pub;
static int outstream_end_write_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
struct SoundIoOutStream *outstream = &os->pub;
int byte_count = osd->write_frame_count * outstream->bytes_per_frame;
soundio_ring_buffer_advance_write_ptr(&osd->ring_buffer, byte_count);
osd->frames_left -= osd->write_frame_count;
return 0;
}
static int outstream_clear_buffer_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
osd->clear_buffer_flag.clear();
soundio_os_cond_signal(osd->cond, nullptr);
static int outstream_clear_buffer_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
atomic_flag_clear(&osd->clear_buffer_flag);
soundio_os_cond_signal(osd->cond, NULL);
return 0;
}
static int outstream_get_latency_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, double *out_latency) {
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
static int outstream_get_latency_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, double *out_latency) {
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
*out_latency = (fill_bytes / outstream->bytes_per_frame) / (double)outstream->sample_rate;
return 0;
}
static void instream_destroy_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
static void instream_destroy_dummy(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
if (isd->thread) {
isd->abort_flag.clear();
soundio_os_cond_signal(isd->cond, nullptr);
atomic_flag_clear(&isd->abort_flag);
soundio_os_cond_signal(isd->cond, NULL);
soundio_os_thread_destroy(isd->thread);
isd->thread = nullptr;
isd->thread = NULL;
}
soundio_os_cond_destroy(isd->cond);
isd->cond = nullptr;
isd->cond = NULL;
soundio_ring_buffer_deinit(&isd->ring_buffer);
}
static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
SoundIoInStream *instream = &is->pub;
SoundIoDevice *device = instream->device;
static int instream_open_dummy(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoDevice *device = instream->device;
isd->pause_requested.store(false);
SOUNDIO_ATOMIC_STORE(isd->pause_requested, false);
if (instream->software_latency == 0.0)
instream->software_latency = clamp(device->software_latency_min, 1.0, device->software_latency_max);
if (instream->software_latency == 0.0) {
instream->software_latency = soundio_double_clamp(
device->software_latency_min, 1.0, device->software_latency_max);
}
isd->period_duration = instream->software_latency;
@ -317,17 +321,17 @@ static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
return 0;
}
static int instream_pause_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is, bool pause) {
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
isd->pause_requested.store(pause);
static int instream_pause_dummy(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
SOUNDIO_ATOMIC_STORE(isd->pause_requested, pause);
return 0;
}
static int instream_start_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
SoundIo *soundio = &si->pub;
static int instream_start_dummy(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
struct SoundIo *soundio = &si->pub;
assert(!isd->thread);
isd->abort_flag.test_and_set();
atomic_flag_test_and_set(&isd->abort_flag);
int err;
if ((err = soundio_os_thread_create(capture_thread_run, is,
soundio->emit_rtprio_warning, &isd->thread)))
@ -337,11 +341,11 @@ static int instream_start_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is)
return 0;
}
static int instream_begin_read_dummy(SoundIoPrivate *si,
SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count)
static int instream_begin_read_dummy(struct SoundIoPrivate *si,
struct SoundIoInStreamPrivate *is, struct SoundIoChannelArea **out_areas, int *frame_count)
{
SoundIoInStream *instream = &is->pub;
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
assert(*frame_count <= isd->frames_left);
@ -357,27 +361,27 @@ static int instream_begin_read_dummy(SoundIoPrivate *si,
return 0;
}
static int instream_end_read_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamDummy *isd = &is->backend_data.dummy;
SoundIoInStream *instream = &is->pub;
static int instream_end_read_dummy(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
struct SoundIoInStream *instream = &is->pub;
int byte_count = isd->read_frame_count * instream->bytes_per_frame;
soundio_ring_buffer_advance_read_ptr(&isd->ring_buffer, byte_count);
isd->frames_left -= isd->read_frame_count;
return 0;
}
static int instream_get_latency_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is, double *out_latency) {
SoundIoInStream *instream = &is->pub;
SoundIoInStreamDummy *osd = &is->backend_data.dummy;
static int instream_get_latency_dummy(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, double *out_latency) {
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamDummy *osd = &is->backend_data.dummy;
int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
*out_latency = (fill_bytes / instream->bytes_per_frame) / (double)instream->sample_rate;
return 0;
}
static int set_all_device_formats(SoundIoDevice *device) {
static int set_all_device_formats(struct SoundIoDevice *device) {
device->format_count = 18;
device->formats = allocate<SoundIoFormat>(device->format_count);
device->formats = ALLOCATE(enum SoundIoFormat, device->format_count);
if (!device->formats)
return SoundIoErrorNoMem;
@ -403,17 +407,17 @@ static int set_all_device_formats(SoundIoDevice *device) {
return 0;
}
static void set_all_device_sample_rates(SoundIoDevice *device) {
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
static void set_all_device_sample_rates(struct SoundIoDevice *device) {
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
device->sample_rate_count = 1;
device->sample_rates = &dev->prealloc_sample_rate_range;
device->sample_rates[0].min = SOUNDIO_MIN_SAMPLE_RATE;
device->sample_rates[0].max = SOUNDIO_MAX_SAMPLE_RATE;
}
static int set_all_device_channel_layouts(SoundIoDevice *device) {
static int set_all_device_channel_layouts(struct SoundIoDevice *device) {
device->layout_count = soundio_channel_layout_builtin_count();
device->layouts = allocate<SoundIoChannelLayout>(device->layout_count);
device->layouts = ALLOCATE(struct SoundIoChannelLayout, device->layout_count);
if (!device->layouts)
return SoundIoErrorNoMem;
for (int i = 0; i < device->layout_count; i += 1)
@ -421,9 +425,9 @@ static int set_all_device_channel_layouts(SoundIoDevice *device) {
return 0;
}
int soundio_dummy_init(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoDummy *sid = &si->backend_data.dummy;
int soundio_dummy_init(struct SoundIoPrivate *si) {
struct SoundIo *soundio = &si->pub;
struct SoundIoDummy *sid = &si->backend_data.dummy;
sid->mutex = soundio_os_mutex_create();
if (!sid->mutex) {
@ -438,7 +442,7 @@ int soundio_dummy_init(SoundIoPrivate *si) {
}
assert(!si->safe_devices_info);
si->safe_devices_info = allocate<SoundIoDevicesInfo>(1);
si->safe_devices_info = ALLOCATE(struct SoundIoDevicesInfo, 1);
if (!si->safe_devices_info) {
destroy_dummy(si);
return SoundIoErrorNoMem;
@ -449,12 +453,12 @@ int soundio_dummy_init(SoundIoPrivate *si) {
// create output device
{
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1);
if (!dev) {
destroy_dummy(si);
return SoundIoErrorNoMem;
}
SoundIoDevice *device = &dev->pub;
struct SoundIoDevice *device = &dev->pub;
device->ref_count = 1;
device->soundio = soundio;
@ -486,7 +490,7 @@ int soundio_dummy_init(SoundIoPrivate *si) {
device->sample_rate_current = 48000;
device->aim = SoundIoDeviceAimOutput;
if (si->safe_devices_info->output_devices.append(device)) {
if (SoundIoListDevicePtr_append(&si->safe_devices_info->output_devices, device)) {
soundio_device_unref(device);
destroy_dummy(si);
return SoundIoErrorNoMem;
@ -495,12 +499,12 @@ int soundio_dummy_init(SoundIoPrivate *si) {
// create input device
{
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1);
if (!dev) {
destroy_dummy(si);
return SoundIoErrorNoMem;
}
SoundIoDevice *device = &dev->pub;
struct SoundIoDevice *device = &dev->pub;
device->ref_count = 1;
device->soundio = soundio;
@ -531,7 +535,7 @@ int soundio_dummy_init(SoundIoPrivate *si) {
device->sample_rate_current = 48000;
device->aim = SoundIoDeviceAimInput;
if (si->safe_devices_info->input_devices.append(device)) {
if (SoundIoListDevicePtr_append(&si->safe_devices_info->input_devices, device)) {
soundio_device_unref(device);
destroy_dummy(si);
return SoundIoErrorNoMem;

View file

@ -5,23 +5,24 @@
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_DUMMY_HPP
#define SOUNDIO_DUMMY_HPP
#ifndef SOUNDIO_DUMMY_H
#define SOUNDIO_DUMMY_H
#include "soundio_private.h"
#include "soundio_internal.h"
#include "os.h"
#include "atomics.hpp"
#include "ring_buffer.hpp"
#include "ring_buffer.h"
#include "atomics.h"
struct SoundIoPrivate;
int soundio_dummy_init(struct SoundIoPrivate *si);
struct SoundIoDummy {
SoundIoOsMutex *mutex;
SoundIoOsCond *cond;
struct SoundIoOsMutex *mutex;
struct SoundIoOsCond *cond;
bool devices_emitted;
};
struct SoundIoDeviceDummy { };
struct SoundIoDeviceDummy { int make_the_struct_not_empty; };
struct SoundIoOutStreamDummy {
struct SoundIoOsThread *thread;
@ -34,8 +35,8 @@ struct SoundIoOutStreamDummy {
struct SoundIoRingBuffer ring_buffer;
double playback_start_time;
atomic_flag clear_buffer_flag;
atomic_bool pause_requested;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoAtomicBool pause_requested;
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
struct SoundIoInStreamDummy {
@ -47,8 +48,8 @@ struct SoundIoInStreamDummy {
int read_frame_count;
int buffer_frame_count;
struct SoundIoRingBuffer ring_buffer;
atomic_bool pause_requested;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoAtomicBool pause_requested;
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
#endif

View file

@ -5,9 +5,9 @@
* See http://opensource.org/licenses/MIT
*/
#include "jack.hpp"
#include "soundio.hpp"
#include "list.hpp"
#include "jack.h"
#include "soundio_private.h"
#include "list.h"
#include <stdio.h>
@ -18,7 +18,7 @@ struct SoundIoJackPort {
int full_name_len;
const char *name;
int name_len;
SoundIoChannelId channel_id;
enum SoundIoChannelId channel_id;
jack_latency_range_t latency_range;
};
@ -26,11 +26,14 @@ struct SoundIoJackClient {
const char *name;
int name_len;
bool is_physical;
SoundIoDeviceAim aim;
enum SoundIoDeviceAim aim;
int port_count;
SoundIoJackPort ports[SOUNDIO_MAX_CHANNELS];
struct SoundIoJackPort ports[SOUNDIO_MAX_CHANNELS];
};
SOUNDIO_MAKE_LIST_STRUCT(struct SoundIoJackClient, SoundIoListJackClient, SOUNDIO_LIST_STATIC)
SOUNDIO_MAKE_LIST_DEF(struct SoundIoJackClient, SoundIoListJackClient, SOUNDIO_LIST_STATIC)
static void split_str(const char *input_str, int input_str_len, char c,
const char **out_1, int *out_len_1, const char **out_2, int *out_len_2)
{
@ -46,11 +49,11 @@ static void split_str(const char *input_str, int input_str_len, char c,
}
}
static SoundIoJackClient *find_or_create_client(SoundIoList<SoundIoJackClient> *clients,
SoundIoDeviceAim aim, bool is_physical, const char *client_name, int client_name_len)
static struct SoundIoJackClient *find_or_create_client(struct SoundIoListJackClient *clients,
enum SoundIoDeviceAim aim, bool is_physical, const char *client_name, int client_name_len)
{
for (int i = 0; i < clients->length; i += 1) {
SoundIoJackClient *client = &clients->at(i);
struct SoundIoJackClient *client = SoundIoListJackClient_ptr_at(clients, i);
if (client->is_physical == is_physical &&
client->aim == aim &&
soundio_streql(client->name, client->name_len, client_name, client_name_len))
@ -59,9 +62,9 @@ static SoundIoJackClient *find_or_create_client(SoundIoList<SoundIoJackClient> *
}
}
int err;
if ((err = clients->add_one()))
return nullptr;
SoundIoJackClient *client = &clients->last();
if ((err = SoundIoListJackClient_add_one(clients)))
return NULL;
struct SoundIoJackClient *client = SoundIoListJackClient_last_ptr(clients);
client->is_physical = is_physical;
client->aim = aim;
client->name = client_name;
@ -70,36 +73,36 @@ static SoundIoJackClient *find_or_create_client(SoundIoList<SoundIoJackClient> *
return client;
}
static void destruct_device(SoundIoDevicePrivate *dp) {
SoundIoDeviceJack *dj = &dp->backend_data.jack;
static void destruct_device(struct SoundIoDevicePrivate *dp) {
struct SoundIoDeviceJack *dj = &dp->backend_data.jack;
for (int i = 0; i < dj->port_count; i += 1) {
SoundIoDeviceJackPort *djp = &dj->ports[i];
struct SoundIoDeviceJackPort *djp = &dj->ports[i];
free(djp->full_name);
}
free(dj->ports);
}
static int refresh_devices_bare(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoJack *sij = &si->backend_data.jack;
static int refresh_devices_bare(struct SoundIoPrivate *si) {
struct SoundIo *soundio = &si->pub;
struct SoundIoJack *sij = &si->backend_data.jack;
if (sij->is_shutdown)
return SoundIoErrorBackendDisconnected;
SoundIoDevicesInfo *devices_info = allocate<SoundIoDevicesInfo>(1);
struct SoundIoDevicesInfo *devices_info = ALLOCATE(struct SoundIoDevicesInfo, 1);
if (!devices_info)
return SoundIoErrorNoMem;
devices_info->default_output_index = -1;
devices_info->default_input_index = -1;
const char **port_names = jack_get_ports(sij->client, nullptr, nullptr, 0);
const char **port_names = jack_get_ports(sij->client, NULL, NULL, 0);
if (!port_names) {
soundio_destroy_devices_info(devices_info);
return SoundIoErrorNoMem;
}
SoundIoList<SoundIoJackClient> clients = {0};
struct SoundIoListJackClient clients = {0};
const char **port_name_ptr = port_names;
for (; *port_name_ptr; port_name_ptr += 1) {
const char *client_and_port_name = *port_name_ptr;
@ -120,12 +123,12 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
continue;
}
SoundIoDeviceAim aim = (flags & JackPortIsInput) ?
enum SoundIoDeviceAim aim = (flags & JackPortIsInput) ?
SoundIoDeviceAimOutput : SoundIoDeviceAimInput;
bool is_physical = flags & JackPortIsPhysical;
const char *client_name = nullptr;
const char *port_name = nullptr;
const char *client_name = NULL;
const char *port_name = NULL;
int client_name_len;
int port_name_len;
split_str(client_and_port_name, client_and_port_name_len, ':',
@ -134,7 +137,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
// device does not have colon, skip it
continue;
}
SoundIoJackClient *client = find_or_create_client(&clients, aim, is_physical,
struct SoundIoJackClient *client = find_or_create_client(&clients, aim, is_physical,
client_name, client_name_len);
if (!client) {
jack_free(port_names);
@ -145,7 +148,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
// we hit the channel limit, skip the leftovers
continue;
}
SoundIoJackPort *port = &client->ports[client->port_count++];
struct SoundIoJackPort *port = &client->ports[client->port_count++];
port->full_name = client_and_port_name;
port->full_name_len = client_and_port_name_len;
port->name = port_name;
@ -158,21 +161,21 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
}
for (int i = 0; i < clients.length; i += 1) {
SoundIoJackClient *client = &clients.at(i);
struct SoundIoJackClient *client = SoundIoListJackClient_ptr_at(&clients, i);
if (client->port_count <= 0)
continue;
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1);
if (!dev) {
jack_free(port_names);
soundio_destroy_devices_info(devices_info);
return SoundIoErrorNoMem;
}
SoundIoDevice *device = &dev->pub;
SoundIoDeviceJack *dj = &dev->backend_data.jack;
struct SoundIoDevice *device = &dev->pub;
struct SoundIoDeviceJack *dj = &dev->backend_data.jack;
int description_len = client->name_len + 3 + 2 * client->port_count;
for (int port_index = 0; port_index < client->port_count; port_index += 1) {
SoundIoJackPort *port = &client->ports[port_index];
struct SoundIoJackPort *port = &client->ports[port_index];
description_len += port->name_len;
}
@ -184,7 +187,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
device->is_raw = false;
device->aim = client->aim;
device->id = soundio_str_dupe(client->name, client->name_len);
device->name = allocate<char>(description_len);
device->name = ALLOCATE(char, description_len);
device->current_format = SoundIoFormatFloat32NE;
device->sample_rate_count = 1;
device->sample_rates = &dev->prealloc_sample_rate_range;
@ -197,7 +200,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
device->software_latency_max = sij->period_size / (double) sij->sample_rate;
dj->port_count = client->port_count;
dj->ports = allocate<SoundIoDeviceJackPort>(dj->port_count);
dj->ports = ALLOCATE(struct SoundIoDeviceJackPort, dj->port_count);
if (!device->id || !device->name || !dj->ports) {
jack_free(port_names);
@ -207,8 +210,8 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
}
for (int port_index = 0; port_index < client->port_count; port_index += 1) {
SoundIoJackPort *port = &client->ports[port_index];
SoundIoDeviceJackPort *djp = &dj->ports[port_index];
struct SoundIoJackPort *port = &client->ports[port_index];
struct SoundIoDeviceJackPort *djp = &dj->ports[port_index];
djp->full_name = soundio_str_dupe(port->full_name, port->full_name_len);
djp->full_name_len = port->full_name_len;
djp->channel_id = port->channel_id;
@ -226,7 +229,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
memcpy(&device->name[client->name_len], ": ", 2);
int index = client->name_len + 2;
for (int port_index = 0; port_index < client->port_count; port_index += 1) {
SoundIoJackPort *port = &client->ports[port_index];
struct SoundIoJackPort *port = &client->ports[port_index];
memcpy(&device->name[index], port->name, port->name_len);
index += port->name_len;
if (port_index + 1 < client->port_count) {
@ -238,7 +241,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
device->current_layout.channel_count = client->port_count;
bool any_invalid = false;
for (int port_index = 0; port_index < client->port_count; port_index += 1) {
SoundIoJackPort *port = &client->ports[port_index];
struct SoundIoJackPort *port = &client->ports[port_index];
device->current_layout.channels[port_index] = port->channel_id;
any_invalid = any_invalid || (port->channel_id == SoundIoChannelIdInvalid);
}
@ -256,7 +259,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
device->formats = &dev->prealloc_format;
device->formats[0] = device->current_format;
SoundIoList<SoundIoDevice *> *device_list;
struct SoundIoListDevicePtr *device_list;
if (device->aim == SoundIoDeviceAimOutput) {
device_list = &devices_info->output_devices;
if (devices_info->default_output_index < 0 && client->is_physical)
@ -268,7 +271,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
devices_info->default_input_index = device_list->length;
}
if (device_list->append(device)) {
if (SoundIoListDevicePtr_append(device_list, device)) {
soundio_device_unref(device);
soundio_destroy_devices_info(devices_info);
return SoundIoErrorNoMem;
@ -283,7 +286,7 @@ static int refresh_devices_bare(SoundIoPrivate *si) {
return 0;
}
static int refresh_devices(SoundIoPrivate *si) {
static int refresh_devices(struct SoundIoPrivate *si) {
int err = SoundIoErrorInterrupted;
while (err == SoundIoErrorInterrupted)
err = refresh_devices_bare(si);
@ -291,8 +294,8 @@ static int refresh_devices(SoundIoPrivate *si) {
}
static void my_flush_events(struct SoundIoPrivate *si, bool wait) {
SoundIo *soundio = &si->pub;
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIo *soundio = &si->pub;
struct SoundIoJack *sij = &si->backend_data.jack;
int err;
bool cb_shutdown = false;
@ -312,9 +315,9 @@ static void my_flush_events(struct SoundIoPrivate *si, bool wait) {
if (cb_shutdown) {
soundio->on_backend_disconnect(soundio, SoundIoErrorBackendDisconnected);
} else {
if (!sij->refresh_devices_flag.test_and_set()) {
if (!atomic_flag_test_and_set(&sij->refresh_devices_flag)) {
if ((err = refresh_devices(si))) {
sij->refresh_devices_flag.clear();
atomic_flag_clear(&sij->refresh_devices_flag);
} else {
soundio->on_devices_change(soundio);
}
@ -332,16 +335,16 @@ static void wait_events_jack(struct SoundIoPrivate *si) {
}
static void wakeup_jack(struct SoundIoPrivate *si) {
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoJack *sij = &si->backend_data.jack;
soundio_os_mutex_lock(sij->mutex);
soundio_os_cond_signal(sij->cond, sij->mutex);
soundio_os_mutex_unlock(sij->mutex);
}
static void force_device_scan_jack(struct SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoJack *sij = &si->backend_data.jack;
sij->refresh_devices_flag.clear();
struct SoundIo *soundio = &si->pub;
struct SoundIoJack *sij = &si->backend_data.jack;
atomic_flag_clear(&sij->refresh_devices_flag);
soundio_os_mutex_lock(sij->mutex);
soundio_os_cond_signal(sij->cond, sij->mutex);
soundio->on_events_signal(soundio);
@ -349,12 +352,12 @@ static void force_device_scan_jack(struct SoundIoPrivate *si) {
}
static int outstream_process_callback(jack_nframes_t nframes, void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStreamJack *osj = &os->backend_data.jack;
SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)arg;
struct SoundIoOutStreamJack *osj = &os->backend_data.jack;
struct SoundIoOutStream *outstream = &os->pub;
osj->frames_left = nframes;
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
struct SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
osj->areas[ch].ptr = (char*)jack_port_get_buffer(osjp->source_port, nframes);
osj->areas[ch].step = outstream->bytes_per_sample;
}
@ -363,36 +366,36 @@ static int outstream_process_callback(jack_nframes_t nframes, void *arg) {
}
static void outstream_destroy_jack(struct SoundIoPrivate *is, struct SoundIoOutStreamPrivate *os) {
SoundIoOutStreamJack *osj = &os->backend_data.jack;
struct SoundIoOutStreamJack *osj = &os->backend_data.jack;
jack_client_close(osj->client);
osj->client = nullptr;
osj->client = NULL;
}
static SoundIoDeviceJackPort *find_port_matching_channel(SoundIoDevice *device, SoundIoChannelId id) {
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
SoundIoDeviceJack *dj = &dev->backend_data.jack;
static struct SoundIoDeviceJackPort *find_port_matching_channel(struct SoundIoDevice *device, enum SoundIoChannelId id) {
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
struct SoundIoDeviceJack *dj = &dev->backend_data.jack;
for (int ch = 0; ch < device->current_layout.channel_count; ch += 1) {
SoundIoChannelId chan_id = device->current_layout.channels[ch];
enum SoundIoChannelId chan_id = device->current_layout.channels[ch];
if (chan_id == id)
return &dj->ports[ch];
}
return nullptr;
return NULL;
}
static int outstream_xrun_callback(void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)arg;
struct SoundIoOutStream *outstream = &os->pub;
outstream->underflow_callback(outstream);
return 0;
}
static int outstream_buffer_size_callback(jack_nframes_t nframes, void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStreamJack *osj = &os->backend_data.jack;
SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)arg;
struct SoundIoOutStreamJack *osj = &os->backend_data.jack;
struct SoundIoOutStream *outstream = &os->pub;
if ((jack_nframes_t)osj->period_size == nframes) {
return 0;
} else {
@ -402,8 +405,8 @@ static int outstream_buffer_size_callback(jack_nframes_t nframes, void *arg) {
}
static int outstream_sample_rate_callback(jack_nframes_t nframes, void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)arg;
struct SoundIoOutStream *outstream = &os->pub;
if (nframes == (jack_nframes_t)outstream->sample_rate) {
return 0;
} else {
@ -413,18 +416,22 @@ static int outstream_sample_rate_callback(jack_nframes_t nframes, void *arg) {
}
static void outstream_shutdown_callback(void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)arg;
struct SoundIoOutStream *outstream = &os->pub;
outstream->error_callback(outstream, SoundIoErrorStreaming);
}
static inline jack_nframes_t nframes_max(jack_nframes_t a, jack_nframes_t b) {
return (a >= b) ? a : b;
}
static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
SoundIoJack *sij = &si->backend_data.jack;
SoundIoOutStreamJack *osj = &os->backend_data.jack;
SoundIoOutStream *outstream = &os->pub;
SoundIoDevice *device = outstream->device;
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
SoundIoDeviceJack *dj = &dev->backend_data.jack;
struct SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoOutStreamJack *osj = &os->backend_data.jack;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoDevice *device = outstream->device;
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
struct SoundIoDeviceJack *dj = &dev->backend_data.jack;
if (sij->is_shutdown)
return SoundIoErrorBackendDisconnected;
@ -472,7 +479,7 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
// register ports and map channels
int connected_count = 0;
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
SoundIoChannelId my_channel_id = outstream->layout.channels[ch];
enum SoundIoChannelId my_channel_id = outstream->layout.channels[ch];
const char *channel_name = soundio_get_channel_name(my_channel_id);
unsigned long flags = JackPortIsOutput;
if (!outstream->non_terminal_hint)
@ -482,15 +489,15 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
outstream_destroy_jack(si, os);
return SoundIoErrorOpeningDevice;
}
SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
struct SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
osjp->source_port = jport;
// figure out which dest port this connects to
SoundIoDeviceJackPort *djp = find_port_matching_channel(device, my_channel_id);
struct SoundIoDeviceJackPort *djp = find_port_matching_channel(device, my_channel_id);
if (djp) {
osjp->dest_port_name = djp->full_name;
osjp->dest_port_name_len = djp->full_name_len;
connected_count += 1;
max_port_latency = max(max_port_latency, djp->latency_range.max);
max_port_latency = nframes_max(max_port_latency, djp->latency_range.max);
}
}
// If nothing got connected, channel layouts aren't working. Just send the
@ -499,13 +506,13 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
max_port_latency = 0;
outstream->layout_error = SoundIoErrorIncompatibleDevice;
int ch_count = min(outstream->layout.channel_count, dj->port_count);
int ch_count = soundio_int_min(outstream->layout.channel_count, dj->port_count);
for (int ch = 0; ch < ch_count; ch += 1) {
SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
SoundIoDeviceJackPort *djp = &dj->ports[ch];
struct SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
struct SoundIoDeviceJackPort *djp = &dj->ports[ch];
osjp->dest_port_name = djp->full_name;
osjp->dest_port_name_len = djp->full_name_len;
max_port_latency = max(max_port_latency, djp->latency_range.max);
max_port_latency = nframes_max(max_port_latency, djp->latency_range.max);
}
}
@ -515,7 +522,7 @@ static int outstream_open_jack(struct SoundIoPrivate *si, struct SoundIoOutStrea
}
static int outstream_pause_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoJack *sij = &si->backend_data.jack;
if (sij->is_shutdown)
return SoundIoErrorBackendDisconnected;
@ -524,9 +531,9 @@ static int outstream_pause_jack(struct SoundIoPrivate *si, struct SoundIoOutStre
}
static int outstream_start_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
SoundIoOutStreamJack *osj = &os->backend_data.jack;
SoundIoOutStream *outstream = &os->pub;
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoOutStreamJack *osj = &os->backend_data.jack;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoJack *sij = &si->backend_data.jack;
int err;
if (sij->is_shutdown)
@ -536,7 +543,7 @@ static int outstream_start_jack(struct SoundIoPrivate *si, struct SoundIoOutStre
return SoundIoErrorStreaming;
for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) {
SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
struct SoundIoOutStreamJackPort *osjp = &osj->ports[ch];
const char *dest_port_name = osjp->dest_port_name;
// allow unconnected ports
if (!dest_port_name)
@ -550,9 +557,9 @@ static int outstream_start_jack(struct SoundIoPrivate *si, struct SoundIoOutStre
}
static int outstream_begin_write_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
SoundIoChannelArea **out_areas, int *frame_count)
struct SoundIoChannelArea **out_areas, int *frame_count)
{
SoundIoOutStreamJack *osj = &os->backend_data.jack;
struct SoundIoOutStreamJack *osj = &os->backend_data.jack;
if (*frame_count != osj->frames_left)
return SoundIoErrorInvalid;
@ -563,7 +570,7 @@ static int outstream_begin_write_jack(struct SoundIoPrivate *si, struct SoundIoO
}
static int outstream_end_write_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
SoundIoOutStreamJack *osj = &os->backend_data.jack;
struct SoundIoOutStreamJack *osj = &os->backend_data.jack;
osj->frames_left = 0;
return 0;
}
@ -575,30 +582,30 @@ static int outstream_clear_buffer_jack(struct SoundIoPrivate *si, struct SoundIo
static int outstream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os,
double *out_latency)
{
SoundIoOutStreamJack *osj = &os->backend_data.jack;
struct SoundIoOutStreamJack *osj = &os->backend_data.jack;
*out_latency = osj->hardware_latency;
return 0;
}
static void instream_destroy_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
SoundIoInStreamJack *isj = &is->backend_data.jack;
struct SoundIoInStreamJack *isj = &is->backend_data.jack;
jack_client_close(isj->client);
isj->client = nullptr;
isj->client = NULL;
}
static int instream_xrun_callback(void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg;
SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)arg;
struct SoundIoInStream *instream = &is->pub;
instream->overflow_callback(instream);
return 0;
}
static int instream_buffer_size_callback(jack_nframes_t nframes, void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg;
SoundIoInStreamJack *isj = &is->backend_data.jack;
SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)arg;
struct SoundIoInStreamJack *isj = &is->backend_data.jack;
struct SoundIoInStream *instream = &is->pub;
if ((jack_nframes_t)isj->period_size == nframes) {
return 0;
@ -609,8 +616,8 @@ static int instream_buffer_size_callback(jack_nframes_t nframes, void *arg) {
}
static int instream_sample_rate_callback(jack_nframes_t nframes, void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg;
SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)arg;
struct SoundIoInStream *instream = &is->pub;
if (nframes == (jack_nframes_t)instream->sample_rate) {
return 0;
} else {
@ -620,18 +627,18 @@ static int instream_sample_rate_callback(jack_nframes_t nframes, void *arg) {
}
static void instream_shutdown_callback(void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg;
SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)arg;
struct SoundIoInStream *instream = &is->pub;
instream->error_callback(instream, SoundIoErrorStreaming);
}
static int instream_process_callback(jack_nframes_t nframes, void *arg) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)arg;
SoundIoInStream *instream = &is->pub;
SoundIoInStreamJack *isj = &is->backend_data.jack;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)arg;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamJack *isj = &is->backend_data.jack;
isj->frames_left = nframes;
for (int ch = 0; ch < instream->layout.channel_count; ch += 1) {
SoundIoInStreamJackPort *isjp = &isj->ports[ch];
struct SoundIoInStreamJackPort *isjp = &isj->ports[ch];
isj->areas[ch].ptr = (char*)jack_port_get_buffer(isjp->dest_port, nframes);
isj->areas[ch].step = instream->bytes_per_sample;
}
@ -640,12 +647,12 @@ static int instream_process_callback(jack_nframes_t nframes, void *arg) {
}
static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
SoundIoInStream *instream = &is->pub;
SoundIoInStreamJack *isj = &is->backend_data.jack;
SoundIoJack *sij = &si->backend_data.jack;
SoundIoDevice *device = instream->device;
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
SoundIoDeviceJack *dj = &dev->backend_data.jack;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamJack *isj = &is->backend_data.jack;
struct SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoDevice *device = instream->device;
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
struct SoundIoDeviceJack *dj = &dev->backend_data.jack;
if (sij->is_shutdown)
return SoundIoErrorBackendDisconnected;
@ -692,7 +699,7 @@ static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamP
// register ports and map channels
int connected_count = 0;
for (int ch = 0; ch < instream->layout.channel_count; ch += 1) {
SoundIoChannelId my_channel_id = instream->layout.channels[ch];
enum SoundIoChannelId my_channel_id = instream->layout.channels[ch];
const char *channel_name = soundio_get_channel_name(my_channel_id);
unsigned long flags = JackPortIsInput;
if (!instream->non_terminal_hint)
@ -702,15 +709,15 @@ static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamP
instream_destroy_jack(si, is);
return SoundIoErrorOpeningDevice;
}
SoundIoInStreamJackPort *isjp = &isj->ports[ch];
struct SoundIoInStreamJackPort *isjp = &isj->ports[ch];
isjp->dest_port = jport;
// figure out which source port this connects to
SoundIoDeviceJackPort *djp = find_port_matching_channel(device, my_channel_id);
struct SoundIoDeviceJackPort *djp = find_port_matching_channel(device, my_channel_id);
if (djp) {
isjp->source_port_name = djp->full_name;
isjp->source_port_name_len = djp->full_name_len;
connected_count += 1;
max_port_latency = max(max_port_latency, djp->latency_range.max);
max_port_latency = nframes_max(max_port_latency, djp->latency_range.max);
}
}
// If nothing got connected, channel layouts aren't working. Just send the
@ -719,13 +726,13 @@ static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamP
max_port_latency = 0;
instream->layout_error = SoundIoErrorIncompatibleDevice;
int ch_count = min(instream->layout.channel_count, dj->port_count);
int ch_count = soundio_int_min(instream->layout.channel_count, dj->port_count);
for (int ch = 0; ch < ch_count; ch += 1) {
SoundIoInStreamJackPort *isjp = &isj->ports[ch];
SoundIoDeviceJackPort *djp = &dj->ports[ch];
struct SoundIoInStreamJackPort *isjp = &isj->ports[ch];
struct SoundIoDeviceJackPort *djp = &dj->ports[ch];
isjp->source_port_name = djp->full_name;
isjp->source_port_name_len = djp->full_name_len;
max_port_latency = max(max_port_latency, djp->latency_range.max);
max_port_latency = nframes_max(max_port_latency, djp->latency_range.max);
}
}
@ -735,7 +742,7 @@ static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamP
}
static int instream_pause_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoJack *sij = &si->backend_data.jack;
if (sij->is_shutdown)
return SoundIoErrorBackendDisconnected;
@ -744,9 +751,9 @@ static int instream_pause_jack(struct SoundIoPrivate *si, struct SoundIoInStream
}
static int instream_start_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
SoundIoInStreamJack *isj = &is->backend_data.jack;
SoundIoInStream *instream = &is->pub;
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoInStreamJack *isj = &is->backend_data.jack;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoJack *sij = &si->backend_data.jack;
int err;
if (sij->is_shutdown)
@ -756,7 +763,7 @@ static int instream_start_jack(struct SoundIoPrivate *si, struct SoundIoInStream
return SoundIoErrorStreaming;
for (int ch = 0; ch < instream->layout.channel_count; ch += 1) {
SoundIoInStreamJackPort *isjp = &isj->ports[ch];
struct SoundIoInStreamJackPort *isjp = &isj->ports[ch];
const char *source_port_name = isjp->source_port_name;
// allow unconnected ports
if (!source_port_name)
@ -770,9 +777,9 @@ static int instream_start_jack(struct SoundIoPrivate *si, struct SoundIoInStream
}
static int instream_begin_read_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
SoundIoChannelArea **out_areas, int *frame_count)
struct SoundIoChannelArea **out_areas, int *frame_count)
{
SoundIoInStreamJack *isj = &is->backend_data.jack;
struct SoundIoInStreamJack *isj = &is->backend_data.jack;
if (*frame_count != isj->frames_left)
return SoundIoErrorInvalid;
@ -783,7 +790,7 @@ static int instream_begin_read_jack(struct SoundIoPrivate *si, struct SoundIoInS
}
static int instream_end_read_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
SoundIoInStreamJack *isj = &is->backend_data.jack;
struct SoundIoInStreamJack *isj = &is->backend_data.jack;
isj->frames_left = 0;
return 0;
}
@ -791,15 +798,15 @@ static int instream_end_read_jack(struct SoundIoPrivate *si, struct SoundIoInStr
static int instream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is,
double *out_latency)
{
SoundIoInStreamJack *isj = &is->backend_data.jack;
struct SoundIoInStreamJack *isj = &is->backend_data.jack;
*out_latency = isj->hardware_latency;
return 0;
}
static void notify_devices_change(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoJack *sij = &si->backend_data.jack;
sij->refresh_devices_flag.clear();
static void notify_devices_change(struct SoundIoPrivate *si) {
struct SoundIo *soundio = &si->pub;
struct SoundIoJack *sij = &si->backend_data.jack;
atomic_flag_clear(&sij->refresh_devices_flag);
soundio_os_mutex_lock(sij->mutex);
soundio_os_cond_signal(sij->cond, sij->mutex);
soundio->on_events_signal(soundio);
@ -807,37 +814,37 @@ static void notify_devices_change(SoundIoPrivate *si) {
}
static int buffer_size_callback(jack_nframes_t nframes, void *arg) {
SoundIoPrivate *si = (SoundIoPrivate *)arg;
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)arg;
struct SoundIoJack *sij = &si->backend_data.jack;
sij->period_size = nframes;
notify_devices_change(si);
return 0;
}
static int sample_rate_callback(jack_nframes_t nframes, void *arg) {
SoundIoPrivate *si = (SoundIoPrivate *)arg;
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)arg;
struct SoundIoJack *sij = &si->backend_data.jack;
sij->sample_rate = nframes;
notify_devices_change(si);
return 0;
}
static void port_registration_callback(jack_port_id_t port_id, int reg, void *arg) {
SoundIoPrivate *si = (SoundIoPrivate *)arg;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)arg;
notify_devices_change(si);
}
static void port_rename_calllback(jack_port_id_t port_id,
const char *old_name, const char *new_name, void *arg)
{
SoundIoPrivate *si = (SoundIoPrivate *)arg;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)arg;
notify_devices_change(si);
}
static void shutdown_callback(void *arg) {
SoundIoPrivate *si = (SoundIoPrivate *)arg;
SoundIo *soundio = &si->pub;
SoundIoJack *sij = &si->backend_data.jack;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)arg;
struct SoundIo *soundio = &si->pub;
struct SoundIoJack *sij = &si->backend_data.jack;
soundio_os_mutex_lock(sij->mutex);
sij->is_shutdown = true;
soundio_os_cond_signal(sij->cond, sij->mutex);
@ -845,8 +852,8 @@ static void shutdown_callback(void *arg) {
soundio_os_mutex_unlock(sij->mutex);
}
static void destroy_jack(SoundIoPrivate *si) {
SoundIoJack *sij = &si->backend_data.jack;
static void destroy_jack(struct SoundIoPrivate *si) {
struct SoundIoJack *sij = &si->backend_data.jack;
if (sij->client)
jack_client_close(sij->client);
@ -859,15 +866,15 @@ static void destroy_jack(SoundIoPrivate *si) {
}
int soundio_jack_init(struct SoundIoPrivate *si) {
SoundIoJack *sij = &si->backend_data.jack;
SoundIo *soundio = &si->pub;
struct SoundIoJack *sij = &si->backend_data.jack;
struct SoundIo *soundio = &si->pub;
if (!global_msg_callback_flag.test_and_set()) {
if (!atomic_flag_test_and_set(&global_msg_callback_flag)) {
if (soundio->jack_error_callback)
jack_set_error_function(soundio->jack_error_callback);
if (soundio->jack_info_callback)
jack_set_info_function(soundio->jack_info_callback);
global_msg_callback_flag.clear();
atomic_flag_clear(&global_msg_callback_flag);
}
sij->mutex = soundio_os_mutex_create();
@ -916,7 +923,7 @@ int soundio_jack_init(struct SoundIoPrivate *si) {
}
jack_on_shutdown(sij->client, shutdown_callback, si);
sij->refresh_devices_flag.clear();
atomic_flag_clear(&sij->refresh_devices_flag);
sij->period_size = jack_get_buffer_size(sij->client);
sij->sample_rate = jack_get_sample_rate(sij->client);

View file

@ -5,33 +5,39 @@
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_JACK_HPP
#define SOUNDIO_JACK_HPP
#ifndef SOUNDIO_JACK_H
#define SOUNDIO_JACK_H
#include "soundio_private.h"
#include "soundio_internal.h"
#include "os.h"
#include "atomics.hpp"
#include "atomics.h"
// jack.h does not properly put `void` in function prototypes with no
// arguments, so we're forced to temporarily disable -Werror=strict-prototypes
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#include <jack/jack.h>
#pragma GCC diagnostic pop
struct SoundIoPrivate;
int soundio_jack_init(struct SoundIoPrivate *si);
struct SoundIoDeviceJackPort {
char *full_name;
int full_name_len;
SoundIoChannelId channel_id;
enum SoundIoChannelId channel_id;
jack_latency_range_t latency_range;
};
struct SoundIoDeviceJack {
int port_count;
SoundIoDeviceJackPort *ports;
struct SoundIoDeviceJackPort *ports;
};
struct SoundIoJack {
jack_client_t *client;
SoundIoOsMutex *mutex;
SoundIoOsCond *cond;
struct SoundIoOsMutex *mutex;
struct SoundIoOsCond *cond;
atomic_flag refresh_devices_flag;
int sample_rate;
int period_size;
@ -50,8 +56,8 @@ struct SoundIoOutStreamJack {
int period_size;
int frames_left;
double hardware_latency;
SoundIoOutStreamJackPort ports[SOUNDIO_MAX_CHANNELS];
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoOutStreamJackPort ports[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
struct SoundIoInStreamJackPort {
@ -65,8 +71,8 @@ struct SoundIoInStreamJack {
int period_size;
int frames_left;
double hardware_latency;
SoundIoInStreamJackPort ports[SOUNDIO_MAX_CHANNELS];
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoInStreamJackPort ports[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
char *buf_ptrs[SOUNDIO_MAX_CHANNELS];
};

145
src/list.h Normal file
View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of libsoundio, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_LIST_H
#define SOUNDIO_LIST_H
#include "util.h"
#include "soundio_internal.h"
#include <assert.h>
#define SOUNDIO_LIST_STATIC static
#define SOUNDIO_LIST_NOT_STATIC
#define SOUNDIO_MAKE_LIST_STRUCT(Type, Name, static_kw) \
struct Name { \
Type *items; \
int length; \
int capacity; \
};
#define SOUNDIO_MAKE_LIST_PROTO(Type, Name, static_kw) \
static_kw void Name##_deinit(struct Name *s); \
static_kw int __attribute__((warn_unused_result)) Name##_append(struct Name *s, Type item); \
static_kw Type Name##_val_at(struct Name *s, int index); \
static_kw Type * Name##_ptr_at(struct Name *s, int index); \
static_kw Type Name##_pop(struct Name *s); \
static_kw int __attribute__((warn_unused_result)) Name##_add_one(struct Name *s); \
static_kw Type Name##_last_val(struct Name *s); \
static_kw Type *Name##_last_ptr(struct Name *s); \
static_kw int __attribute__((warn_unused_result)) Name##_resize(struct Name *s, int new_length); \
static_kw void Name##_clear(struct Name *s); \
static_kw int __attribute__((warn_unused_result)) \
Name##_ensure_capacity(struct Name *s, int new_capacity); \
static_kw Type Name##_swap_remove(struct Name *s, int index);
#define SOUNDIO_MAKE_LIST_DEF(Type, Name, static_kw) \
__attribute__ ((unused)) \
static_kw void Name##_deinit(struct Name *s) { \
free(s->items); \
} \
\
__attribute__ ((unused)) \
__attribute__ ((warn_unused_result)) \
static_kw int Name##_ensure_capacity(struct Name *s, int new_capacity) { \
int better_capacity = soundio_int_max(s->capacity, 16); \
while (better_capacity < new_capacity) \
better_capacity = better_capacity * 2; \
if (better_capacity != s->capacity) { \
Type *new_items = REALLOCATE_NONZERO(Type, s->items, better_capacity); \
if (!new_items) \
return SoundIoErrorNoMem; \
s->items = new_items; \
s->capacity = better_capacity; \
} \
return 0; \
} \
\
__attribute__ ((unused)) \
__attribute__ ((warn_unused_result)) \
static_kw int Name##_append(struct Name *s, Type item) { \
int err = Name##_ensure_capacity(s, s->length + 1); \
if (err) \
return err; \
s->items[s->length] = item; \
s->length += 1; \
return 0; \
} \
\
__attribute__ ((unused)) \
static_kw Type Name##_val_at(struct Name *s, int index) { \
assert(index >= 0); \
assert(index < s->length); \
return s->items[index]; \
} \
\
/* remember that the pointer to this item is invalid after you \
* modify the length of the list \
*/ \
__attribute__ ((unused)) \
static_kw Type * Name##_ptr_at(struct Name *s, int index) { \
assert(index >= 0); \
assert(index < s->length); \
return &s->items[index]; \
} \
\
__attribute__ ((unused)) \
static_kw Type Name##_pop(struct Name *s) { \
assert(s->length >= 1); \
s->length -= 1; \
return s->items[s->length]; \
} \
\
__attribute__ ((unused)) \
__attribute__ ((warn_unused_result)) \
static_kw int Name##_resize(struct Name *s, int new_length) { \
assert(new_length >= 0); \
int err = Name##_ensure_capacity(s, new_length); \
if (err) \
return err; \
s->length = new_length; \
return 0; \
} \
\
__attribute__ ((unused)) \
__attribute__ ((warn_unused_result)) \
static_kw int Name##_add_one(struct Name *s) { \
return Name##_resize(s, s->length + 1); \
} \
\
__attribute__ ((unused)) \
static_kw Type Name##_last_val(struct Name *s) { \
assert(s->length >= 1); \
return s->items[s->length - 1]; \
} \
\
__attribute__ ((unused)) \
static_kw Type *Name##_last_ptr(struct Name *s) { \
assert(s->length >= 1); \
return &s->items[s->length - 1]; \
} \
\
__attribute__ ((unused)) \
static_kw void Name##_clear(struct Name *s) { \
s->length = 0; \
} \
\
__attribute__ ((unused)) \
static_kw Type Name##_swap_remove(struct Name *s, int index) { \
assert(index >= 0); \
assert(index < s->length); \
Type last = Name##_pop(s); \
if (index == s->length) \
return last; \
Type item = s->items[index]; \
s->items[index] = last; \
return item; \
}
#endif

View file

@ -1,102 +0,0 @@
/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of libsoundio, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_LIST_HPP
#define SOUNDIO_LIST_HPP
#include "util.hpp"
#include "soundio_private.h"
#include <assert.h>
template<typename T>
struct SoundIoList {
void deinit() {
free(items);
}
int __attribute__((warn_unused_result)) append(T item) {
int err = ensure_capacity(length + 1);
if (err)
return err;
items[length++] = item;
return 0;
}
// remember that the pointer to this item is invalid after you
// modify the length of the list
const T & at(int index) const {
assert(index >= 0);
assert(index < length);
return items[index];
}
T & at(int index) {
assert(index >= 0);
assert(index < length);
return items[index];
}
T pop() {
assert(length >= 1);
return items[--length];
}
int __attribute__((warn_unused_result)) add_one() {
return resize(length + 1);
}
const T & last() const {
assert(length >= 1);
return items[length - 1];
}
T & last() {
assert(length >= 1);
return items[length - 1];
}
int __attribute__((warn_unused_result)) resize(int new_length) {
assert(new_length >= 0);
int err = ensure_capacity(new_length);
if (err)
return err;
length = new_length;
return 0;
}
void clear() {
length = 0;
}
int __attribute__((warn_unused_result)) ensure_capacity(int new_capacity) {
int better_capacity = max(capacity, 16);
while (better_capacity < new_capacity)
better_capacity = better_capacity * 2;
if (better_capacity != capacity) {
T *new_items = reallocate_nonzero(items, better_capacity);
if (!new_items)
return SoundIoErrorNoMem;
items = new_items;
capacity = better_capacity;
}
return 0;
}
T swap_remove(int index) {
assert(index >= 0);
assert(index < length);
T last = pop();
if (index == length)
return last;
T item = items[index];
items[index] = last;
return item;
}
T * items;
int length;
int capacity;
};
#endif

View file

@ -5,9 +5,16 @@
* See http://opensource.org/licenses/MIT
*/
#if defined(__APPLE__)
#define _DARWIN_C_SOURCE
#undef _POSIX_C_SOURCE
#else
#define _GNU_SOURCE
#endif
#include "os.h"
#include "soundio_private.h"
#include "util.hpp"
#include "soundio_internal.h"
#include "util.h"
#include <stdlib.h>
#include <time.h>
@ -53,7 +60,7 @@
#include <pthread.h>
#include <unistd.h>
#include <sys/mman.h>
#ifndef MAP_ANONYMOUS
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif
@ -159,7 +166,7 @@ double soundio_os_get_time(void) {
#if defined(SOUNDIO_OS_WINDOWS)
static DWORD WINAPI run_win32_thread(LPVOID userdata) {
struct SoundIoOsThread *thread = (struct SoundIoOsThread *)userdata;
HRESULT err = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
HRESULT err = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
assert(err == S_OK);
thread->run(thread->arg);
CoUninitialize();
@ -184,7 +191,7 @@ int soundio_os_thread_create(
{
*out_thread = NULL;
struct SoundIoOsThread *thread = allocate<SoundIoOsThread>(1);
struct SoundIoOsThread *thread = ALLOCATE(struct SoundIoOsThread, 1);
if (!thread) {
soundio_os_thread_destroy(thread);
return SoundIoErrorNoMem;
@ -276,7 +283,7 @@ void soundio_os_thread_destroy(struct SoundIoOsThread *thread) {
}
struct SoundIoOsMutex *soundio_os_mutex_create(void) {
struct SoundIoOsMutex *mutex = allocate<SoundIoOsMutex>(1);
struct SoundIoOsMutex *mutex = ALLOCATE(struct SoundIoOsMutex, 1);
if (!mutex) {
soundio_os_mutex_destroy(mutex);
return NULL;
@ -328,7 +335,7 @@ void soundio_os_mutex_unlock(struct SoundIoOsMutex *mutex) {
}
struct SoundIoOsCond * soundio_os_cond_create(void) {
struct SoundIoOsCond *cond = allocate<SoundIoOsCond>(1);
struct SoundIoOsCond *cond = ALLOCATE(struct SoundIoOsCond, 1);
if (!cond) {
soundio_os_cond_destroy(cond);
@ -558,7 +565,7 @@ static int internal_init(void) {
GetSystemInfo(&win32_system_info);
page_size = win32_system_info.dwAllocationGranularity;
#else
page_size = getpagesize();
page_size = sysconf(_SC_PAGESIZE);
#if defined(__MACH__)
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
#endif
@ -581,7 +588,7 @@ int soundio_os_init(void) {
if ((err = internal_init()))
return err;
if (!InitOnceComplete(&win32_init_once, INIT_ONCE_ASYNC, nullptr))
if (!InitOnceComplete(&win32_init_once, INIT_ONCE_ASYNC, NULL))
return SoundIoErrorSystemResources;
#else
assert_no_err(pthread_mutex_lock(&init_mutex));
@ -734,5 +741,5 @@ void soundio_os_deinit_mirrored_memory(struct SoundIoOsMirroredMemory *mem) {
int err = munmap(mem->address, 2 * mem->capacity);
assert(!err);
#endif
mem->address = nullptr;
mem->address = NULL;
}

View file

@ -5,8 +5,8 @@
* See http://opensource.org/licenses/MIT
*/
#include "pulseaudio.hpp"
#include "soundio.hpp"
#include "pulseaudio.h"
#include "soundio_private.h"
#include <string.h>
#include <stdio.h>
@ -15,19 +15,19 @@
static void subscribe_callback(pa_context *context,
pa_subscription_event_type_t event_bits, uint32_t index, void *userdata)
{
SoundIoPrivate *si = (SoundIoPrivate *)userdata;
SoundIo *soundio = &si->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)userdata;
struct SoundIo *soundio = &si->pub;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
sipa->device_scan_queued = true;
pa_threaded_mainloop_signal(sipa->main_loop, 0);
soundio->on_events_signal(soundio);
}
static int subscribe_to_events(SoundIoPrivate *si) {
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static int subscribe_to_events(struct SoundIoPrivate *si) {
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_subscription_mask_t events = (pa_subscription_mask_t)(
PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE|PA_SUBSCRIPTION_MASK_SERVER);
pa_operation *subscribe_op = pa_context_subscribe(sipa->pulse_context, events, nullptr, si);
pa_operation *subscribe_op = pa_context_subscribe(sipa->pulse_context, events, NULL, si);
if (!subscribe_op)
return SoundIoErrorNoMem;
pa_operation_unref(subscribe_op);
@ -35,9 +35,9 @@ static int subscribe_to_events(SoundIoPrivate *si) {
}
static void context_state_callback(pa_context *context, void *userdata) {
SoundIoPrivate *si = (SoundIoPrivate *)userdata;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
SoundIo *soundio = &si->pub;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)userdata;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIo *soundio = &si->pub;
switch (pa_context_get_state(context)) {
case PA_CONTEXT_UNCONNECTED: // The context hasn't been connected yet.
@ -68,8 +68,8 @@ static void context_state_callback(pa_context *context, void *userdata) {
}
}
static void destroy_pa(SoundIoPrivate *si) {
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static void destroy_pa(struct SoundIoPrivate *si) {
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
if (sipa->main_loop)
pa_threaded_mainloop_stop(sipa->main_loop);
@ -90,7 +90,7 @@ static void destroy_pa(SoundIoPrivate *si) {
free(sipa->default_source_name);
}
static SoundIoFormat from_pulseaudio_format(pa_sample_spec sample_spec) {
static enum SoundIoFormat from_pulseaudio_format(pa_sample_spec sample_spec) {
switch (sample_spec.format) {
case PA_SAMPLE_U8: return SoundIoFormatU8;
case PA_SAMPLE_S16LE: return SoundIoFormatS16LE;
@ -113,7 +113,7 @@ static SoundIoFormat from_pulseaudio_format(pa_sample_spec sample_spec) {
return SoundIoFormatInvalid;
}
static SoundIoChannelId from_pulseaudio_channel_pos(pa_channel_position_t pos) {
static enum SoundIoChannelId from_pulseaudio_channel_pos(pa_channel_position_t pos) {
switch (pos) {
case PA_CHANNEL_POSITION_MONO: return SoundIoChannelIdFrontCenter;
case PA_CHANNEL_POSITION_FRONT_LEFT: return SoundIoChannelIdFrontLeft;
@ -156,15 +156,15 @@ static SoundIoChannelId from_pulseaudio_channel_pos(pa_channel_position_t pos) {
}
}
static void set_from_pulseaudio_channel_map(pa_channel_map channel_map, SoundIoChannelLayout *channel_layout) {
static void set_from_pulseaudio_channel_map(pa_channel_map channel_map, struct SoundIoChannelLayout *channel_layout) {
channel_layout->channel_count = channel_map.channels;
for (int i = 0; i < channel_map.channels; i += 1) {
channel_layout->channels[i] = from_pulseaudio_channel_pos(channel_map.map[i]);
}
channel_layout->name = nullptr;
channel_layout->name = NULL;
int builtin_layout_count = soundio_channel_layout_builtin_count();
for (int i = 0; i < builtin_layout_count; i += 1) {
const SoundIoChannelLayout *builtin_layout = soundio_channel_layout_get_builtin(i);
const struct SoundIoChannelLayout *builtin_layout = soundio_channel_layout_get_builtin(i);
if (soundio_channel_layout_equal(builtin_layout, channel_layout)) {
channel_layout->name = builtin_layout->name;
break;
@ -172,9 +172,9 @@ static void set_from_pulseaudio_channel_map(pa_channel_map channel_map, SoundIoC
}
}
static int set_all_device_channel_layouts(SoundIoDevice *device) {
static int set_all_device_channel_layouts(struct SoundIoDevice *device) {
device->layout_count = soundio_channel_layout_builtin_count();
device->layouts = allocate<SoundIoChannelLayout>(device->layout_count);
device->layouts = ALLOCATE(struct SoundIoChannelLayout, device->layout_count);
if (!device->layouts)
return SoundIoErrorNoMem;
for (int i = 0; i < device->layout_count; i += 1)
@ -182,9 +182,9 @@ static int set_all_device_channel_layouts(SoundIoDevice *device) {
return 0;
}
static int set_all_device_formats(SoundIoDevice *device) {
static int set_all_device_formats(struct SoundIoDevice *device) {
device->format_count = 9;
device->formats = allocate<SoundIoFormat>(device->format_count);
device->formats = ALLOCATE(enum SoundIoFormat, device->format_count);
if (!device->formats)
return SoundIoErrorNoMem;
device->formats[0] = SoundIoFormatU8;
@ -199,10 +199,10 @@ static int set_all_device_formats(SoundIoDevice *device) {
return 0;
}
static int perform_operation(SoundIoPrivate *si, pa_operation *op) {
static int perform_operation(struct SoundIoPrivate *si, pa_operation *op) {
if (!op)
return SoundIoErrorNoMem;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
for (;;) {
switch (pa_operation_get_state(op)) {
case PA_OPERATION_RUNNING:
@ -219,9 +219,9 @@ static int perform_operation(SoundIoPrivate *si, pa_operation *op) {
}
static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *info, int eol, void *userdata) {
SoundIoPrivate *si = (SoundIoPrivate *)userdata;
SoundIo *soundio = &si->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)userdata;
struct SoundIo *soundio = &si->pub;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
int err;
if (eol) {
pa_threaded_mainloop_signal(sipa->main_loop, 0);
@ -230,12 +230,12 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
if (sipa->device_query_err)
return;
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1);
if (!dev) {
sipa->device_query_err = SoundIoErrorNoMem;
return;
}
SoundIoDevice *device = &dev->pub;
struct SoundIoDevice *device = &dev->pub;
device->ref_count = 1;
device->soundio = soundio;
@ -252,8 +252,8 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
// some reasonable min and max values.
device->sample_rate_count = 1;
device->sample_rates = &dev->prealloc_sample_rate_range;
device->sample_rates[0].min = min(SOUNDIO_MIN_SAMPLE_RATE, device->sample_rate_current);
device->sample_rates[0].max = max(SOUNDIO_MAX_SAMPLE_RATE, device->sample_rate_current);
device->sample_rates[0].min = soundio_int_min(SOUNDIO_MIN_SAMPLE_RATE, device->sample_rate_current);
device->sample_rates[0].max = soundio_int_max(SOUNDIO_MAX_SAMPLE_RATE, device->sample_rate_current);
device->current_format = from_pulseaudio_format(info->sample_spec);
// PulseAudio performs sample format conversion, so any PulseAudio
@ -274,7 +274,7 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
device->aim = SoundIoDeviceAimOutput;
if (sipa->current_devices_info->output_devices.append(device)) {
if (SoundIoListDevicePtr_append(&sipa->current_devices_info->output_devices, device)) {
soundio_device_unref(device);
sipa->device_query_err = SoundIoErrorNoMem;
return;
@ -282,9 +282,9 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
}
static void source_info_callback(pa_context *pulse_context, const pa_source_info *info, int eol, void *userdata) {
SoundIoPrivate *si = (SoundIoPrivate *)userdata;
SoundIo *soundio = &si->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)userdata;
struct SoundIo *soundio = &si->pub;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
int err;
if (eol) {
@ -294,12 +294,12 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
if (sipa->device_query_err)
return;
SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1);
if (!dev) {
sipa->device_query_err = SoundIoErrorNoMem;
return;
}
SoundIoDevice *device = &dev->pub;
struct SoundIoDevice *device = &dev->pub;
device->ref_count = 1;
device->soundio = soundio;
@ -316,8 +316,8 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
// some reasonable min and max values.
device->sample_rate_count = 1;
device->sample_rates = &dev->prealloc_sample_rate_range;
device->sample_rates[0].min = min(8000, device->sample_rate_current);
device->sample_rates[0].max = max(5644800, device->sample_rate_current);
device->sample_rates[0].min = soundio_int_min(SOUNDIO_MIN_SAMPLE_RATE, device->sample_rate_current);
device->sample_rates[0].max = soundio_int_max(SOUNDIO_MAX_SAMPLE_RATE, device->sample_rate_current);
device->current_format = from_pulseaudio_format(info->sample_spec);
// PulseAudio performs sample format conversion, so any PulseAudio
@ -338,7 +338,7 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
device->aim = SoundIoDeviceAimInput;
if (sipa->current_devices_info->input_devices.append(device)) {
if (SoundIoListDevicePtr_append(&sipa->current_devices_info->input_devices, device)) {
soundio_device_unref(device);
sipa->device_query_err = SoundIoErrorNoMem;
return;
@ -346,9 +346,9 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
}
static void server_info_callback(pa_context *pulse_context, const pa_server_info *info, void *userdata) {
SoundIoPrivate *si = (SoundIoPrivate *)userdata;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)userdata;
assert(si);
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
assert(!sipa->default_sink_name);
assert(!sipa->default_source_name);
@ -363,26 +363,26 @@ static void server_info_callback(pa_context *pulse_context, const pa_server_info
}
// always called even when refresh_devices succeeds
static void cleanup_refresh_devices(SoundIoPrivate *si) {
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static void cleanup_refresh_devices(struct SoundIoPrivate *si) {
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
soundio_destroy_devices_info(sipa->current_devices_info);
sipa->current_devices_info = nullptr;
sipa->current_devices_info = NULL;
free(sipa->default_sink_name);
sipa->default_sink_name = nullptr;
sipa->default_sink_name = NULL;
free(sipa->default_source_name);
sipa->default_source_name = nullptr;
sipa->default_source_name = NULL;
}
// call this while holding the main loop lock
static int refresh_devices(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static int refresh_devices(struct SoundIoPrivate *si) {
struct SoundIo *soundio = &si->pub;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
assert(!sipa->current_devices_info);
sipa->current_devices_info = allocate<SoundIoDevicesInfo>(1);
sipa->current_devices_info = ALLOCATE(struct SoundIoDevicesInfo, 1);
if (!sipa->current_devices_info)
return SoundIoErrorNoMem;
@ -414,7 +414,9 @@ static int refresh_devices(SoundIoPrivate *si) {
if (sipa->current_devices_info->input_devices.length > 0) {
sipa->current_devices_info->default_input_index = 0;
for (int i = 0; i < sipa->current_devices_info->input_devices.length; i += 1) {
SoundIoDevice *device = sipa->current_devices_info->input_devices.at(i);
struct SoundIoDevice *device = SoundIoListDevicePtr_val_at(
&sipa->current_devices_info->input_devices, i);
assert(device->aim == SoundIoDeviceAimInput);
if (strcmp(device->id, sipa->default_source_name) == 0) {
sipa->current_devices_info->default_input_index = i;
@ -425,7 +427,9 @@ static int refresh_devices(SoundIoPrivate *si) {
if (sipa->current_devices_info->output_devices.length > 0) {
sipa->current_devices_info->default_output_index = 0;
for (int i = 0; i < sipa->current_devices_info->output_devices.length; i += 1) {
SoundIoDevice *device = sipa->current_devices_info->output_devices.at(i);
struct SoundIoDevice *device = SoundIoListDevicePtr_val_at(
&sipa->current_devices_info->output_devices, i);
assert(device->aim == SoundIoDeviceAimOutput);
if (strcmp(device->id, sipa->default_sink_name) == 0) {
sipa->current_devices_info->default_output_index = i;
@ -435,20 +439,20 @@ static int refresh_devices(SoundIoPrivate *si) {
soundio_destroy_devices_info(sipa->ready_devices_info);
sipa->ready_devices_info = sipa->current_devices_info;
sipa->current_devices_info = nullptr;
sipa->current_devices_info = NULL;
pa_threaded_mainloop_signal(sipa->main_loop, 0);
soundio->on_events_signal(soundio);
return 0;
}
static void my_flush_events(SoundIoPrivate *si, bool wait) {
SoundIo *soundio = &si->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static void my_flush_events(struct SoundIoPrivate *si, bool wait) {
struct SoundIo *soundio = &si->pub;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
bool change = false;
bool cb_shutdown = false;
SoundIoDevicesInfo *old_devices_info = nullptr;
struct SoundIoDevicesInfo *old_devices_info = NULL;
pa_threaded_mainloop_lock(sipa->main_loop);
@ -467,7 +471,7 @@ static void my_flush_events(SoundIoPrivate *si, bool wait) {
} else if (sipa->ready_devices_info) {
old_devices_info = si->safe_devices_info;
si->safe_devices_info = sipa->ready_devices_info;
sipa->ready_devices_info = nullptr;
sipa->ready_devices_info = NULL;
change = true;
}
@ -481,25 +485,25 @@ static void my_flush_events(SoundIoPrivate *si, bool wait) {
soundio_destroy_devices_info(old_devices_info);
}
static void flush_events_pa(SoundIoPrivate *si) {
static void flush_events_pa(struct SoundIoPrivate *si) {
my_flush_events(si, false);
}
static void wait_events_pa(SoundIoPrivate *si) {
static void wait_events_pa(struct SoundIoPrivate *si) {
my_flush_events(si, false);
my_flush_events(si, true);
}
static void wakeup_pa(SoundIoPrivate *si) {
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static void wakeup_pa(struct SoundIoPrivate *si) {
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop);
pa_threaded_mainloop_signal(sipa->main_loop, 0);
pa_threaded_mainloop_unlock(sipa->main_loop);
}
static void force_device_scan_pa(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static void force_device_scan_pa(struct SoundIoPrivate *si) {
struct SoundIo *soundio = &si->pub;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop);
sipa->device_scan_queued = true;
pa_threaded_mainloop_signal(sipa->main_loop, 0);
@ -507,7 +511,7 @@ static void force_device_scan_pa(SoundIoPrivate *si) {
pa_threaded_mainloop_unlock(sipa->main_loop);
}
static pa_sample_format_t to_pulseaudio_format(SoundIoFormat format) {
static pa_sample_format_t to_pulseaudio_format(enum SoundIoFormat format) {
switch (format) {
case SoundIoFormatU8: return PA_SAMPLE_U8;
case SoundIoFormatS16LE: return PA_SAMPLE_S16LE;
@ -534,7 +538,7 @@ static pa_sample_format_t to_pulseaudio_format(SoundIoFormat format) {
return PA_SAMPLE_INVALID;
}
static pa_channel_position_t to_pulseaudio_channel_pos(SoundIoChannelId channel_id) {
static pa_channel_position_t to_pulseaudio_channel_pos(enum SoundIoChannelId channel_id) {
switch (channel_id) {
case SoundIoChannelIdFrontLeft: return PA_CHANNEL_POSITION_FRONT_LEFT;
case SoundIoChannelIdFrontRight: return PA_CHANNEL_POSITION_FRONT_RIGHT;
@ -577,7 +581,7 @@ static pa_channel_position_t to_pulseaudio_channel_pos(SoundIoChannelId channel_
}
}
static pa_channel_map to_pulseaudio_channel_map(const SoundIoChannelLayout *channel_layout) {
static pa_channel_map to_pulseaudio_channel_map(const struct SoundIoChannelLayout *channel_layout) {
pa_channel_map channel_map;
channel_map.channels = channel_layout->channel_count;
@ -590,19 +594,19 @@ static pa_channel_map to_pulseaudio_channel_map(const SoundIoChannelLayout *chan
}
static void playback_stream_state_callback(pa_stream *stream, void *userdata) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate*) userdata;
SoundIoOutStream *outstream = &os->pub;
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate*) userdata;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIo *soundio = outstream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
switch (pa_stream_get_state(stream)) {
case PA_STREAM_UNCONNECTED:
case PA_STREAM_CREATING:
case PA_STREAM_TERMINATED:
break;
case PA_STREAM_READY:
ospa->stream_ready = true;
SOUNDIO_ATOMIC_STORE(ospa->stream_ready, true);
pa_threaded_mainloop_signal(sipa->main_loop, 0);
break;
case PA_STREAM_FAILED:
@ -612,48 +616,48 @@ static void playback_stream_state_callback(pa_stream *stream, void *userdata) {
}
static void playback_stream_underflow_callback(pa_stream *stream, void *userdata) {
SoundIoOutStream *outstream = (SoundIoOutStream*)userdata;
struct SoundIoOutStream *outstream = (struct SoundIoOutStream*)userdata;
outstream->underflow_callback(outstream);
}
static void playback_stream_write_callback(pa_stream *stream, size_t nbytes, void *userdata) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate*)(userdata);
SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate*)(userdata);
struct SoundIoOutStream *outstream = &os->pub;
int frame_count = nbytes / outstream->bytes_per_frame;
outstream->write_callback(outstream, 0, frame_count);
}
static void outstream_destroy_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
static void outstream_destroy_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_stream *stream = ospa->stream;
if (stream) {
pa_threaded_mainloop_lock(sipa->main_loop);
pa_stream_set_write_callback(stream, nullptr, nullptr);
pa_stream_set_state_callback(stream, nullptr, nullptr);
pa_stream_set_underflow_callback(stream, nullptr, nullptr);
pa_stream_set_overflow_callback(stream, nullptr, nullptr);
pa_stream_set_write_callback(stream, NULL, NULL);
pa_stream_set_state_callback(stream, NULL, NULL);
pa_stream_set_underflow_callback(stream, NULL, NULL);
pa_stream_set_overflow_callback(stream, NULL, NULL);
pa_stream_disconnect(stream);
pa_stream_unref(stream);
pa_threaded_mainloop_unlock(sipa->main_loop);
ospa->stream = nullptr;
ospa->stream = NULL;
}
}
static void timing_update_callback(pa_stream *stream, int success, void *userdata) {
SoundIoPrivate *si = (SoundIoPrivate *)userdata;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)userdata;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_signal(sipa->main_loop, 0);
}
static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
SoundIoOutStream *outstream = &os->pub;
static int outstream_open_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
struct SoundIoOutStream *outstream = &os->pub;
if ((unsigned)outstream->layout.channel_count > PA_CHANNELS_MAX)
return SoundIoErrorIncompatibleBackend;
@ -661,9 +665,9 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
if (!outstream->name)
outstream->name = "SoundIoOutStream";
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
ospa->stream_ready.store(false);
ospa->clear_buffer_flag.test_and_set();
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
SOUNDIO_ATOMIC_STORE(ospa->stream_ready, false);
atomic_flag_test_and_set(&ospa->clear_buffer_flag);
assert(sipa->pulse_context);
@ -704,13 +708,13 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
int err = pa_stream_connect_playback(ospa->stream,
outstream->device->id, &ospa->buffer_attr,
flags, nullptr, nullptr);
flags, NULL, NULL);
if (err) {
pa_threaded_mainloop_unlock(sipa->main_loop);
return SoundIoErrorOpeningDevice;
}
while (!ospa->stream_ready.load())
while (!SOUNDIO_ATOMIC_LOAD(ospa->stream_ready))
pa_threaded_mainloop_wait(sipa->main_loop);
pa_operation *update_timing_info_op = pa_stream_update_timing_info(ospa->stream, timing_update_callback, si);
@ -727,10 +731,10 @@ static int outstream_open_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
return 0;
}
static int outstream_start_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStream *outstream = &os->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
static int outstream_start_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop);
@ -738,7 +742,7 @@ static int outstream_start_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
int frame_count = ospa->write_byte_count / outstream->bytes_per_frame;
outstream->write_callback(outstream, 0, frame_count);
pa_operation *op = pa_stream_cork(ospa->stream, false, nullptr, nullptr);
pa_operation *op = pa_stream_cork(ospa->stream, false, NULL, NULL);
if (!op) {
pa_threaded_mainloop_unlock(sipa->main_loop);
return SoundIoErrorStreaming;
@ -753,11 +757,11 @@ static int outstream_start_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
return 0;
}
static int outstream_begin_write_pa(SoundIoPrivate *si,
SoundIoOutStreamPrivate *os, SoundIoChannelArea **out_areas, int *frame_count)
static int outstream_begin_write_pa(struct SoundIoPrivate *si,
struct SoundIoOutStreamPrivate *os, struct SoundIoChannelArea **out_areas, int *frame_count)
{
SoundIoOutStream *outstream = &os->pub;
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
struct SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
pa_stream *stream = ospa->stream;
ospa->write_byte_count = *frame_count * outstream->bytes_per_frame;
@ -775,28 +779,28 @@ static int outstream_begin_write_pa(SoundIoPrivate *si,
return 0;
}
static int outstream_end_write_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
static int outstream_end_write_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os) {
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
pa_stream *stream = ospa->stream;
pa_seek_mode_t seek_mode = ospa->clear_buffer_flag.test_and_set() ? PA_SEEK_RELATIVE : PA_SEEK_RELATIVE_ON_READ;
if (pa_stream_write(stream, ospa->write_ptr, ospa->write_byte_count, nullptr, 0, seek_mode))
pa_seek_mode_t seek_mode = atomic_flag_test_and_set(&ospa->clear_buffer_flag) ? PA_SEEK_RELATIVE : PA_SEEK_RELATIVE_ON_READ;
if (pa_stream_write(stream, ospa->write_ptr, ospa->write_byte_count, NULL, 0, seek_mode))
return SoundIoErrorStreaming;
return 0;
}
static int outstream_clear_buffer_pa(SoundIoPrivate *si,
SoundIoOutStreamPrivate *os)
static int outstream_clear_buffer_pa(struct SoundIoPrivate *si,
struct SoundIoOutStreamPrivate *os)
{
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
ospa->clear_buffer_flag.clear();
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
atomic_flag_clear(&ospa->clear_buffer_flag);
return 0;
}
static int outstream_pause_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, bool pause) {
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static int outstream_pause_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
if (!pa_threaded_mainloop_in_thread(sipa->main_loop)) {
pa_threaded_mainloop_lock(sipa->main_loop);
@ -818,8 +822,8 @@ static int outstream_pause_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, b
return 0;
}
static int outstream_get_latency_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, double *out_latency) {
SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
static int outstream_get_latency_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, double *out_latency) {
struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
int err;
pa_usec_t r_usec;
@ -832,19 +836,19 @@ static int outstream_get_latency_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate
}
static void recording_stream_state_callback(pa_stream *stream, void *userdata) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate*)userdata;
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
SoundIoInStream *instream = &is->pub;
SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate*)userdata;
struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
struct SoundIoInStream *instream = &is->pub;
struct SoundIo *soundio = instream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
switch (pa_stream_get_state(stream)) {
case PA_STREAM_UNCONNECTED:
case PA_STREAM_CREATING:
case PA_STREAM_TERMINATED:
break;
case PA_STREAM_READY:
ispa->stream_ready = true;
SOUNDIO_ATOMIC_STORE(ispa->stream_ready, true);
pa_threaded_mainloop_signal(sipa->main_loop, 0);
break;
case PA_STREAM_FAILED:
@ -854,43 +858,43 @@ static void recording_stream_state_callback(pa_stream *stream, void *userdata) {
}
static void recording_stream_read_callback(pa_stream *stream, size_t nbytes, void *userdata) {
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate*)userdata;
SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate*)userdata;
struct SoundIoInStream *instream = &is->pub;
assert(nbytes % instream->bytes_per_frame == 0);
assert(nbytes > 0);
int available_frame_count = nbytes / instream->bytes_per_frame;
instream->read_callback(instream, 0, available_frame_count);
}
static void instream_destroy_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static void instream_destroy_pa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_stream *stream = ispa->stream;
if (stream) {
pa_threaded_mainloop_lock(sipa->main_loop);
pa_stream_set_state_callback(stream, nullptr, nullptr);
pa_stream_set_read_callback(stream, nullptr, nullptr);
pa_stream_set_state_callback(stream, NULL, NULL);
pa_stream_set_read_callback(stream, NULL, NULL);
pa_stream_disconnect(stream);
pa_stream_unref(stream);
pa_threaded_mainloop_unlock(sipa->main_loop);
ispa->stream = nullptr;
ispa->stream = NULL;
}
}
static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
SoundIoInStream *instream = &is->pub;
static int instream_open_pa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
struct SoundIoInStream *instream = &is->pub;
if ((unsigned)instream->layout.channel_count > PA_CHANNELS_MAX)
return SoundIoErrorIncompatibleBackend;
if (!instream->name)
instream->name = "SoundIoInStream";
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
ispa->stream_ready = false;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
SOUNDIO_ATOMIC_STORE(ispa->stream_ready, false);
pa_threaded_mainloop_lock(sipa->main_loop);
@ -931,10 +935,10 @@ static int instream_open_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
return 0;
}
static int instream_start_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStream *instream = &is->pub;
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static int instream_start_pa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop);
pa_stream_flags_t flags = (pa_stream_flags_t)(PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING);
@ -947,7 +951,7 @@ static int instream_start_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
return SoundIoErrorOpeningDevice;
}
while (!ispa->stream_ready)
while (!SOUNDIO_ATOMIC_LOAD(ispa->stream_ready))
pa_threaded_mainloop_wait(sipa->main_loop);
pa_operation *update_timing_info_op = pa_stream_update_timing_info(ispa->stream, timing_update_callback, si);
@ -961,14 +965,14 @@ static int instream_start_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
return 0;
}
static int instream_begin_read_pa(SoundIoPrivate *si,
SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count)
static int instream_begin_read_pa(struct SoundIoPrivate *si,
struct SoundIoInStreamPrivate *is, struct SoundIoChannelArea **out_areas, int *frame_count)
{
SoundIoInStream *instream = &is->pub;
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
pa_stream *stream = ispa->stream;
assert(ispa->stream_ready);
assert(SOUNDIO_ATOMIC_LOAD(ispa->stream_ready));
if (!ispa->peek_buf) {
if (pa_stream_peek(stream, (const void **)&ispa->peek_buf, &ispa->peek_buf_size))
@ -980,12 +984,12 @@ static int instream_begin_read_pa(SoundIoPrivate *si,
// hole
if (!ispa->peek_buf) {
*frame_count = ispa->peek_buf_frames_left;
*out_areas = nullptr;
*out_areas = NULL;
return 0;
}
}
ispa->read_frame_count = min(*frame_count, ispa->peek_buf_frames_left);
ispa->read_frame_count = soundio_int_min(*frame_count, ispa->peek_buf_frames_left);
*frame_count = ispa->read_frame_count;
for (int ch = 0; ch < instream->layout.channel_count; ch += 1) {
ispa->areas[ch].ptr = ispa->peek_buf + ispa->peek_buf_index + instream->bytes_per_sample * ch;
@ -997,9 +1001,9 @@ static int instream_begin_read_pa(SoundIoPrivate *si,
return 0;
}
static int instream_end_read_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
SoundIoInStream *instream = &is->pub;
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
static int instream_end_read_pa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
struct SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
pa_stream *stream = ispa->stream;
// hole
@ -1016,15 +1020,15 @@ static int instream_end_read_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is)
if (ispa->peek_buf_index >= ispa->peek_buf_size) {
if (pa_stream_drop(stream))
return SoundIoErrorStreaming;
ispa->peek_buf = nullptr;
ispa->peek_buf = NULL;
}
return 0;
}
static int instream_pause_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, bool pause) {
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
static int instream_pause_pa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, bool pause) {
struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
if (!pa_threaded_mainloop_in_thread(sipa->main_loop)) {
pa_threaded_mainloop_lock(sipa->main_loop);
@ -1044,8 +1048,8 @@ static int instream_pause_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, boo
return 0;
}
static int instream_get_latency_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, double *out_latency) {
SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
static int instream_get_latency_pa(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is, double *out_latency) {
struct SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
int err;
pa_usec_t r_usec;
@ -1057,9 +1061,9 @@ static int instream_get_latency_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *i
return 0;
}
int soundio_pulseaudio_init(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
int soundio_pulseaudio_init(struct SoundIoPrivate *si) {
struct SoundIo *soundio = &si->pub;
struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
sipa->device_scan_queued = true;

View file

@ -5,17 +5,18 @@
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_PULSEAUDIO_HPP
#define SOUNDIO_PULSEAUDIO_HPP
#ifndef SOUNDIO_PULSEAUDIO_H
#define SOUNDIO_PULSEAUDIO_H
#include "soundio_private.h"
#include "atomics.hpp"
#include "soundio_internal.h"
#include "atomics.h"
#include <pulse/pulseaudio.h>
struct SoundIoPrivate;
int soundio_pulseaudio_init(struct SoundIoPrivate *si);
struct SoundIoDevicePulseAudio { };
struct SoundIoDevicePulseAudio { int make_the_struct_not_empty; };
struct SoundIoPulseAudio {
int device_query_err;
@ -41,24 +42,24 @@ struct SoundIoPulseAudio {
struct SoundIoOutStreamPulseAudio {
pa_stream *stream;
atomic_bool stream_ready;
struct SoundIoAtomicBool stream_ready;
pa_buffer_attr buffer_attr;
char *write_ptr;
size_t write_byte_count;
atomic_flag clear_buffer_flag;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
struct SoundIoInStreamPulseAudio {
pa_stream *stream;
atomic_bool stream_ready;
struct SoundIoAtomicBool stream_ready;
pa_buffer_attr buffer_attr;
char *peek_buf;
size_t peek_buf_index;
size_t peek_buf_size;
int peek_buf_frames_left;
int read_frame_count;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
#endif

View file

@ -5,25 +5,25 @@
* See http://opensource.org/licenses/MIT
*/
#include "ring_buffer.hpp"
#include "soundio.hpp"
#include "util.hpp"
#include "ring_buffer.h"
#include "soundio_private.h"
#include "util.h"
#include <stdlib.h>
struct SoundIoRingBuffer *soundio_ring_buffer_create(struct SoundIo *soundio, int requested_capacity) {
SoundIoRingBuffer *rb = allocate<SoundIoRingBuffer>(1);
struct SoundIoRingBuffer *rb = ALLOCATE(struct SoundIoRingBuffer, 1);
assert(requested_capacity > 0);
if (!rb) {
soundio_ring_buffer_destroy(rb);
return nullptr;
return NULL;
}
if (soundio_ring_buffer_init(rb, requested_capacity)) {
soundio_ring_buffer_destroy(rb);
return nullptr;
return NULL;
}
return rb;
@ -43,25 +43,31 @@ int soundio_ring_buffer_capacity(struct SoundIoRingBuffer *rb) {
}
char *soundio_ring_buffer_write_ptr(struct SoundIoRingBuffer *rb) {
return rb->mem.address + (rb->write_offset % rb->capacity);
long write_offset = SOUNDIO_ATOMIC_LOAD(rb->write_offset);
return rb->mem.address + (write_offset % rb->capacity);
}
void soundio_ring_buffer_advance_write_ptr(struct SoundIoRingBuffer *rb, int count) {
rb->write_offset += count;
SOUNDIO_ATOMIC_FETCH_ADD(rb->write_offset, count);
assert(soundio_ring_buffer_fill_count(rb) >= 0);
}
char *soundio_ring_buffer_read_ptr(struct SoundIoRingBuffer *rb) {
return rb->mem.address + (rb->read_offset % rb->capacity);
long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
return rb->mem.address + (read_offset % rb->capacity);
}
void soundio_ring_buffer_advance_read_ptr(struct SoundIoRingBuffer *rb, int count) {
rb->read_offset += count;
SOUNDIO_ATOMIC_FETCH_ADD(rb->read_offset, count);
assert(soundio_ring_buffer_fill_count(rb) >= 0);
}
int soundio_ring_buffer_fill_count(struct SoundIoRingBuffer *rb) {
int count = rb->write_offset - rb->read_offset;
// Whichever offset we load first might have a smaller value. So we load
// the read_offset first.
long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
long write_offset = SOUNDIO_ATOMIC_LOAD(rb->write_offset);
int count = write_offset - read_offset;
assert(count >= 0);
assert(count <= rb->capacity);
return count;
@ -72,15 +78,16 @@ int soundio_ring_buffer_free_count(struct SoundIoRingBuffer *rb) {
}
void soundio_ring_buffer_clear(struct SoundIoRingBuffer *rb) {
return rb->write_offset.store(rb->read_offset.load());
long read_offset = SOUNDIO_ATOMIC_LOAD(rb->read_offset);
SOUNDIO_ATOMIC_STORE(rb->write_offset, read_offset);
}
int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity) {
int err;
if ((err = soundio_os_init_mirrored_memory(&rb->mem, requested_capacity)))
return err;
rb->write_offset = 0;
rb->read_offset = 0;
SOUNDIO_ATOMIC_STORE(rb->write_offset, 0);
SOUNDIO_ATOMIC_STORE(rb->read_offset, 0);
rb->capacity = rb->mem.capacity;
return 0;

View file

@ -5,16 +5,16 @@
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_RING_BUFFER_HPP
#define SOUNDIO_RING_BUFFER_HPP
#ifndef SOUNDIO_RING_BUFFER_H
#define SOUNDIO_RING_BUFFER_H
#include "atomics.hpp"
#include "os.h"
#include "atomics.h"
struct SoundIoRingBuffer {
SoundIoOsMirroredMemory mem;
atomic_long write_offset;
atomic_long read_offset;
struct SoundIoOsMirroredMemory mem;
struct SoundIoAtomicLong write_offset;
struct SoundIoAtomicLong read_offset;
int capacity;
};

View file

@ -5,8 +5,8 @@
* See http://opensource.org/licenses/MIT
*/
#include "soundio.hpp"
#include "util.hpp"
#include "soundio_private.h"
#include "util.h"
#include "os.h"
#include "config.h"
@ -14,7 +14,7 @@
#include <assert.h>
#include <stdio.h>
static const SoundIoBackend available_backends[] = {
static const enum SoundIoBackend available_backends[] = {
#ifdef SOUNDIO_HAVE_JACK
SoundIoBackendJack,
#endif
@ -33,36 +33,40 @@ static const SoundIoBackend available_backends[] = {
SoundIoBackendDummy,
};
static int (*backend_init_fns[])(SoundIoPrivate *) = {
[SoundIoBackendNone] = nullptr,
static int (*backend_init_fns[])(struct SoundIoPrivate *) = {
[SoundIoBackendNone] = NULL,
#ifdef SOUNDIO_HAVE_JACK
[SoundIoBackendJack] = soundio_jack_init,
#else
[SoundIoBackendJack] = nullptr,
[SoundIoBackendJack] = NULL,
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
[SoundIoBackendPulseAudio] = soundio_pulseaudio_init,
#else
[SoundIoBackendPulseAudio] = nullptr,
[SoundIoBackendPulseAudio] = NULL,
#endif
#ifdef SOUNDIO_HAVE_ALSA
[SoundIoBackendAlsa] = soundio_alsa_init,
#else
[SoundIoBackendAlsa] = nullptr,
[SoundIoBackendAlsa] = NULL,
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
[SoundIoBackendCoreAudio] = soundio_coreaudio_init,
#else
[SoundIoBackendCoreAudio] = nullptr,
[SoundIoBackendCoreAudio] = NULL,
#endif
#ifdef SOUNDIO_HAVE_WASAPI
[SoundIoBackendWasapi] = soundio_wasapi_init,
#else
[SoundIoBackendWasapi] = nullptr,
[SoundIoBackendWasapi] = NULL,
#endif
[SoundIoBackendDummy] = soundio_dummy_init,
};
SOUNDIO_MAKE_LIST_DEF(struct SoundIoDevice*, SoundIoListDevicePtr, SOUNDIO_LIST_NOT_STATIC)
SOUNDIO_MAKE_LIST_DEF(struct SoundIoSampleRateRange, SoundIoListSampleRateRange, SOUNDIO_LIST_NOT_STATIC)
const char *soundio_strerror(int error) {
switch ((enum SoundIoError)error) {
case SoundIoErrorNone: return "(no error)";
@ -153,23 +157,23 @@ const char *soundio_backend_name(enum SoundIoBackend backend) {
}
void soundio_destroy(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
soundio_disconnect(soundio);
free(si);
}
static void do_nothing_cb(struct SoundIo *) { }
static void do_nothing_cb(struct SoundIo *soundio) { }
static void default_msg_callback(const char *msg) { }
static void default_backend_disconnect_cb(struct SoundIo *, int err) {
static void default_backend_disconnect_cb(struct SoundIo *soundio, int err) {
soundio_panic("libsoundio: backend disconnected: %s", soundio_strerror(err));
}
static atomic_flag rtprio_seen = ATOMIC_FLAG_INIT;
static void default_emit_rtprio_warning(void) {
if (!rtprio_seen.test_and_set()) {
if (!atomic_flag_test_and_set(&rtprio_seen)) {
fprintf(stderr, "warning: unable to set high priority thread: Operation not permitted\n");
fprintf(stderr, "See "
"https://github.com/andrewrk/genesis/wiki/warning:-unable-to-set-high-priority-thread:-Operation-not-permitted\n");
@ -179,11 +183,11 @@ static void default_emit_rtprio_warning(void) {
struct SoundIo *soundio_create(void) {
int err;
if ((err = soundio_os_init()))
return nullptr;
struct SoundIoPrivate *si = allocate<SoundIoPrivate>(1);
return NULL;
struct SoundIoPrivate *si = ALLOCATE(struct SoundIoPrivate, 1);
if (!si)
return nullptr;
SoundIo *soundio = &si->pub;
return NULL;
struct SoundIo *soundio = &si->pub;
soundio->on_devices_change = do_nothing_cb;
soundio->on_backend_disconnect = default_backend_disconnect_cb;
soundio->on_events_signal = do_nothing_cb;
@ -197,8 +201,8 @@ struct SoundIo *soundio_create(void) {
int soundio_connect(struct SoundIo *soundio) {
int err = 0;
for (int i = 0; i < array_length(available_backends); i += 1) {
SoundIoBackend backend = available_backends[i];
for (int i = 0; i < ARRAY_LENGTH(available_backends); i += 1) {
enum SoundIoBackend backend = available_backends[i];
err = soundio_connect_backend(soundio, backend);
if (!err)
return 0;
@ -209,8 +213,8 @@ int soundio_connect(struct SoundIo *soundio) {
return err;
}
int soundio_connect_backend(SoundIo *soundio, SoundIoBackend backend) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
int soundio_connect_backend(struct SoundIo *soundio, enum SoundIoBackend backend) {
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
if (soundio->current_backend)
return SoundIoErrorInvalid;
@ -218,7 +222,7 @@ int soundio_connect_backend(SoundIo *soundio, SoundIoBackend backend) {
if (backend <= 0 || backend > SoundIoBackendDummy)
return SoundIoErrorInvalid;
int (*fn)(SoundIoPrivate *) = backend_init_fns[backend];
int (*fn)(struct SoundIoPrivate *) = backend_init_fns[backend];
if (!fn)
return SoundIoErrorBackendUnavailable;
@ -234,52 +238,52 @@ int soundio_connect_backend(SoundIo *soundio, SoundIoBackend backend) {
}
void soundio_disconnect(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
if (!si)
return;
if (si->destroy)
si->destroy(si);
memset(&si->backend_data, 0, sizeof(SoundIoBackendData));
memset(&si->backend_data, 0, sizeof(union SoundIoBackendData));
soundio->current_backend = SoundIoBackendNone;
soundio_destroy_devices_info(si->safe_devices_info);
si->safe_devices_info = nullptr;
si->safe_devices_info = NULL;
si->destroy = nullptr;
si->flush_events = nullptr;
si->wait_events = nullptr;
si->wakeup = nullptr;
si->force_device_scan = nullptr;
si->destroy = NULL;
si->flush_events = NULL;
si->wait_events = NULL;
si->wakeup = NULL;
si->force_device_scan = NULL;
si->outstream_open = nullptr;
si->outstream_destroy = nullptr;
si->outstream_start = nullptr;
si->outstream_begin_write = nullptr;
si->outstream_end_write = nullptr;
si->outstream_clear_buffer = nullptr;
si->outstream_pause = nullptr;
si->outstream_get_latency = nullptr;
si->outstream_open = NULL;
si->outstream_destroy = NULL;
si->outstream_start = NULL;
si->outstream_begin_write = NULL;
si->outstream_end_write = NULL;
si->outstream_clear_buffer = NULL;
si->outstream_pause = NULL;
si->outstream_get_latency = NULL;
si->instream_open = nullptr;
si->instream_destroy = nullptr;
si->instream_start = nullptr;
si->instream_begin_read = nullptr;
si->instream_end_read = nullptr;
si->instream_pause = nullptr;
si->instream_get_latency = nullptr;
si->instream_open = NULL;
si->instream_destroy = NULL;
si->instream_start = NULL;
si->instream_begin_read = NULL;
si->instream_end_read = NULL;
si->instream_pause = NULL;
si->instream_get_latency = NULL;
}
void soundio_flush_events(struct SoundIo *soundio) {
assert(soundio->current_backend != SoundIoBackendNone);
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
si->flush_events(si);
}
int soundio_input_device_count(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
assert(si->safe_devices_info);
if (!si->safe_devices_info)
@ -293,7 +297,7 @@ int soundio_input_device_count(struct SoundIo *soundio) {
}
int soundio_output_device_count(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
assert(si->safe_devices_info);
if (!si->safe_devices_info)
@ -307,7 +311,7 @@ int soundio_output_device_count(struct SoundIo *soundio) {
}
int soundio_default_input_device_index(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
assert(si->safe_devices_info);
if (!si->safe_devices_info)
@ -321,7 +325,7 @@ int soundio_default_input_device_index(struct SoundIo *soundio) {
}
int soundio_default_output_device_index(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
assert(si->safe_devices_info);
if (!si->safe_devices_info)
@ -335,43 +339,43 @@ int soundio_default_output_device_index(struct SoundIo *soundio) {
}
struct SoundIoDevice *soundio_get_input_device(struct SoundIo *soundio, int index) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
assert(soundio->current_backend != SoundIoBackendNone);
if (soundio->current_backend == SoundIoBackendNone)
return nullptr;
return NULL;
assert(si->safe_devices_info);
if (!si->safe_devices_info)
return nullptr;
return NULL;
assert(index >= 0);
assert(index < si->safe_devices_info->input_devices.length);
if (index < 0 || index >= si->safe_devices_info->input_devices.length)
return nullptr;
return NULL;
SoundIoDevice *device = si->safe_devices_info->input_devices.at(index);
struct SoundIoDevice *device = SoundIoListDevicePtr_val_at(&si->safe_devices_info->input_devices, index);
soundio_device_ref(device);
return device;
}
struct SoundIoDevice *soundio_get_output_device(struct SoundIo *soundio, int index) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
assert(soundio->current_backend != SoundIoBackendNone);
if (soundio->current_backend == SoundIoBackendNone)
return nullptr;
return NULL;
assert(si->safe_devices_info);
if (!si->safe_devices_info)
return nullptr;
return NULL;
assert(index >= 0);
assert(index < si->safe_devices_info->output_devices.length);
if (index < 0 || index >= si->safe_devices_info->output_devices.length)
return nullptr;
return NULL;
SoundIoDevice *device = si->safe_devices_info->output_devices.at(index);
struct SoundIoDevice *device = SoundIoListDevicePtr_val_at(&si->safe_devices_info->output_devices, index);
soundio_device_ref(device);
return device;
}
@ -384,7 +388,7 @@ void soundio_device_unref(struct SoundIoDevice *device) {
assert(device->ref_count >= 0);
if (device->ref_count == 0) {
SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
struct SoundIoDevicePrivate *dev = (struct SoundIoDevicePrivate *)device;
if (dev->destruct)
dev->destruct(dev);
@ -396,7 +400,7 @@ void soundio_device_unref(struct SoundIoDevice *device) {
{
free(device->sample_rates);
}
dev->sample_rates.deinit();
SoundIoListSampleRateRange_deinit(&dev->sample_rates);
if (device->formats != &dev->prealloc_format)
free(device->formats);
@ -414,35 +418,35 @@ void soundio_device_ref(struct SoundIoDevice *device) {
}
void soundio_wait_events(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
si->wait_events(si);
}
void soundio_wakeup(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
si->wakeup(si);
}
void soundio_force_device_scan(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
si->force_device_scan(si);
}
int soundio_outstream_begin_write(struct SoundIoOutStream *outstream,
SoundIoChannelArea **areas, int *frame_count)
struct SoundIoChannelArea **areas, int *frame_count)
{
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
struct SoundIo *soundio = outstream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
if (*frame_count <= 0)
return SoundIoErrorInvalid;
return si->outstream_begin_write(si, os, areas, frame_count);
}
int soundio_outstream_end_write(struct SoundIoOutStream *outstream) {
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
struct SoundIo *soundio = outstream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
return si->outstream_end_write(si, os);
}
@ -453,13 +457,13 @@ static void default_outstream_error_callback(struct SoundIoOutStream *os, int er
static void default_underflow_callback(struct SoundIoOutStream *outstream) { }
struct SoundIoOutStream *soundio_outstream_create(struct SoundIoDevice *device) {
SoundIoOutStreamPrivate *os = allocate<SoundIoOutStreamPrivate>(1);
SoundIoOutStream *outstream = &os->pub;
struct SoundIoOutStreamPrivate *os = ALLOCATE(struct SoundIoOutStreamPrivate, 1);
struct SoundIoOutStream *outstream = &os->pub;
if (!os)
return nullptr;
return NULL;
if (!device)
return nullptr;
return NULL;
outstream->device = device;
soundio_device_ref(device);
@ -471,7 +475,7 @@ struct SoundIoOutStream *soundio_outstream_create(struct SoundIoDevice *device)
}
int soundio_outstream_open(struct SoundIoOutStream *outstream) {
SoundIoDevice *device = outstream->device;
struct SoundIoDevice *device = outstream->device;
if (device->aim != SoundIoDeviceAimOutput)
return SoundIoErrorInvalid;
@ -491,29 +495,29 @@ int soundio_outstream_open(struct SoundIoOutStream *outstream) {
return SoundIoErrorInvalid;
if (!outstream->layout.channel_count) {
const SoundIoChannelLayout *stereo = soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdStereo);
const struct SoundIoChannelLayout *stereo = soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdStereo);
outstream->layout = soundio_device_supports_layout(device, stereo) ? *stereo : device->layouts[0];
}
if (!outstream->sample_rate)
outstream->sample_rate = soundio_device_nearest_sample_rate(device, 48000);
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
outstream->bytes_per_frame = soundio_get_bytes_per_frame(outstream->format, outstream->layout.channel_count);
outstream->bytes_per_sample = soundio_get_bytes_per_sample(outstream->format);
SoundIo *soundio = device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIo *soundio = device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
return si->outstream_open(si, os);
}
void soundio_outstream_destroy(SoundIoOutStream *outstream) {
void soundio_outstream_destroy(struct SoundIoOutStream *outstream) {
if (!outstream)
return;
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
struct SoundIo *soundio = outstream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
if (si->outstream_destroy)
si->outstream_destroy(si, os);
@ -523,30 +527,30 @@ void soundio_outstream_destroy(SoundIoOutStream *outstream) {
}
int soundio_outstream_start(struct SoundIoOutStream *outstream) {
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
struct SoundIo *soundio = outstream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
return si->outstream_start(si, os);
}
int soundio_outstream_pause(struct SoundIoOutStream *outstream, bool pause) {
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
struct SoundIo *soundio = outstream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
return si->outstream_pause(si, os, pause);
}
int soundio_outstream_clear_buffer(struct SoundIoOutStream *outstream) {
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
struct SoundIo *soundio = outstream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
return si->outstream_clear_buffer(si, os);
}
int soundio_outstream_get_latency(struct SoundIoOutStream *outstream, double *out_latency) {
SoundIo *soundio = outstream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream;
struct SoundIo *soundio = outstream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoOutStreamPrivate *os = (struct SoundIoOutStreamPrivate *)outstream;
return si->outstream_get_latency(si, os, out_latency);
}
@ -557,13 +561,13 @@ static void default_instream_error_callback(struct SoundIoInStream *is, int err)
static void default_overflow_callback(struct SoundIoInStream *instream) { }
struct SoundIoInStream *soundio_instream_create(struct SoundIoDevice *device) {
SoundIoInStreamPrivate *is = allocate<SoundIoInStreamPrivate>(1);
SoundIoInStream *instream = &is->pub;
struct SoundIoInStreamPrivate *is = ALLOCATE(struct SoundIoInStreamPrivate, 1);
struct SoundIoInStream *instream = &is->pub;
if (!is)
return nullptr;
return NULL;
if (!device)
return nullptr;
return NULL;
instream->device = device;
soundio_device_ref(device);
@ -575,7 +579,7 @@ struct SoundIoInStream *soundio_instream_create(struct SoundIoDevice *device) {
}
int soundio_instream_open(struct SoundIoInStream *instream) {
SoundIoDevice *device = instream->device;
struct SoundIoDevice *device = instream->device;
if (device->aim != SoundIoDeviceAimInput)
return SoundIoErrorInvalid;
@ -594,7 +598,7 @@ int soundio_instream_open(struct SoundIoInStream *instream) {
}
if (!instream->layout.channel_count) {
const SoundIoChannelLayout *stereo = soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdStereo);
const struct SoundIoChannelLayout *stereo = soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdStereo);
instream->layout = soundio_device_supports_layout(device, stereo) ? *stereo : device->layouts[0];
}
@ -604,16 +608,16 @@ int soundio_instream_open(struct SoundIoInStream *instream) {
instream->bytes_per_frame = soundio_get_bytes_per_frame(instream->format, instream->layout.channel_count);
instream->bytes_per_sample = soundio_get_bytes_per_sample(instream->format);
SoundIo *soundio = device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream;
struct SoundIo *soundio = device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)instream;
return si->instream_open(si, is);
}
int soundio_instream_start(struct SoundIoInStream *instream) {
SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream;
struct SoundIo *soundio = instream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)instream;
return si->instream_start(si, is);
}
@ -621,9 +625,9 @@ void soundio_instream_destroy(struct SoundIoInStream *instream) {
if (!instream)
return;
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream;
SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)instream;
struct SoundIo *soundio = instream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
if (si->instream_destroy)
si->instream_destroy(si, is);
@ -633,69 +637,69 @@ void soundio_instream_destroy(struct SoundIoInStream *instream) {
}
int soundio_instream_pause(struct SoundIoInStream *instream, bool pause) {
SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream;
struct SoundIo *soundio = instream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)instream;
return si->instream_pause(si, is, pause);
}
int soundio_instream_begin_read(struct SoundIoInStream *instream,
struct SoundIoChannelArea **areas, int *frame_count)
{
SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream;
struct SoundIo *soundio = instream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)instream;
return si->instream_begin_read(si, is, areas, frame_count);
}
int soundio_instream_end_read(struct SoundIoInStream *instream) {
SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream;
struct SoundIo *soundio = instream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)instream;
return si->instream_end_read(si, is);
}
int soundio_instream_get_latency(struct SoundIoInStream *instream, double *out_latency) {
SoundIo *soundio = instream->device->soundio;
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream;
struct SoundIo *soundio = instream->device->soundio;
struct SoundIoPrivate *si = (struct SoundIoPrivate *)soundio;
struct SoundIoInStreamPrivate *is = (struct SoundIoInStreamPrivate *)instream;
return si->instream_get_latency(si, is, out_latency);
}
void soundio_destroy_devices_info(SoundIoDevicesInfo *devices_info) {
void soundio_destroy_devices_info(struct 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));
soundio_device_unref(SoundIoListDevicePtr_val_at(&devices_info->input_devices, i));
for (int i = 0; i < devices_info->output_devices.length; i += 1)
soundio_device_unref(devices_info->output_devices.at(i));
soundio_device_unref(SoundIoListDevicePtr_val_at(&devices_info->output_devices, i));
devices_info->input_devices.deinit();
devices_info->output_devices.deinit();
SoundIoListDevicePtr_deinit(&devices_info->input_devices);
SoundIoListDevicePtr_deinit(&devices_info->output_devices);
free(devices_info);
}
bool soundio_have_backend(SoundIoBackend backend) {
bool soundio_have_backend(enum SoundIoBackend backend) {
assert(backend > 0);
assert(backend <= SoundIoBackendDummy);
return backend_init_fns[backend];
}
int soundio_backend_count(struct SoundIo *soundio) {
return array_length(available_backends);
return ARRAY_LENGTH(available_backends);
}
SoundIoBackend soundio_get_backend(struct SoundIo *soundio, int index) {
enum SoundIoBackend soundio_get_backend(struct SoundIo *soundio, int index) {
return available_backends[index];
}
static bool layout_contains(const SoundIoChannelLayout *available_layouts, int available_layouts_count,
const SoundIoChannelLayout *target_layout)
static bool layout_contains(const struct SoundIoChannelLayout *available_layouts, int available_layouts_count,
const struct SoundIoChannelLayout *target_layout)
{
for (int i = 0; i < available_layouts_count; i += 1) {
const SoundIoChannelLayout *available_layout = &available_layouts[i];
const struct SoundIoChannelLayout *available_layout = &available_layouts[i];
if (soundio_channel_layout_equal(target_layout, available_layout))
return true;
}
@ -707,16 +711,16 @@ const struct SoundIoChannelLayout *soundio_best_matching_channel_layout(
const struct SoundIoChannelLayout *available_layouts, int available_layouts_count)
{
for (int i = 0; i < preferred_layouts_count; i += 1) {
const SoundIoChannelLayout *preferred_layout = &preferred_layouts[i];
const struct SoundIoChannelLayout *preferred_layout = &preferred_layouts[i];
if (layout_contains(available_layouts, available_layouts_count, preferred_layout))
return preferred_layout;
}
return nullptr;
return NULL;
}
static int compare_layouts(const void *a, const void *b) {
const SoundIoChannelLayout *layout_a = *((SoundIoChannelLayout **)a);
const SoundIoChannelLayout *layout_b = *((SoundIoChannelLayout **)b);
const struct SoundIoChannelLayout *layout_a = *((struct SoundIoChannelLayout **)a);
const struct SoundIoChannelLayout *layout_b = *((struct SoundIoChannelLayout **)b);
if (layout_a->channel_count > layout_b->channel_count)
return -1;
else if (layout_a->channel_count < layout_b->channel_count)
@ -729,7 +733,7 @@ void soundio_sort_channel_layouts(struct SoundIoChannelLayout *layouts, int layo
if (!layouts)
return;
qsort(layouts, layouts_count, sizeof(SoundIoChannelLayout), compare_layouts);
qsort(layouts, layouts_count, sizeof(struct SoundIoChannelLayout), compare_layouts);
}
void soundio_device_sort_channel_layouts(struct SoundIoDevice *device) {
@ -756,7 +760,7 @@ bool soundio_device_supports_layout(struct SoundIoDevice *device,
bool soundio_device_supports_sample_rate(struct SoundIoDevice *device, int sample_rate) {
for (int i = 0; i < device->sample_rate_count; i += 1) {
SoundIoSampleRateRange *range = &device->sample_rates[i];
struct SoundIoSampleRateRange *range = &device->sample_rates[i];
if (sample_rate >= range->min && sample_rate <= range->max)
return true;
}
@ -772,8 +776,8 @@ int soundio_device_nearest_sample_rate(struct SoundIoDevice *device, int sample_
int best_rate = -1;
int best_delta = -1;
for (int i = 0; i < device->sample_rate_count; i += 1) {
SoundIoSampleRateRange *range = &device->sample_rates[i];
int candidate_rate = clamp(range->min, sample_rate, range->max);
struct SoundIoSampleRateRange *range = &device->sample_rates[i];
int candidate_rate = soundio_int_clamp(range->min, sample_rate, range->max);
if (candidate_rate == sample_rate)
return candidate_rate;

View file

@ -1,179 +0,0 @@
/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of libsoundio, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_SOUNDIO_HPP
#define SOUNDIO_SOUNDIO_HPP
#include "soundio_private.h"
#include "list.hpp"
#ifdef SOUNDIO_HAVE_JACK
#include "jack.hpp"
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
#include "pulseaudio.hpp"
#endif
#ifdef SOUNDIO_HAVE_ALSA
#include "alsa.hpp"
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
#include "coreaudio.hpp"
#endif
#ifdef SOUNDIO_HAVE_WASAPI
#include "wasapi.hpp"
#endif
#include "dummy.hpp"
union SoundIoBackendData {
#ifdef SOUNDIO_HAVE_JACK
SoundIoJack jack;
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
SoundIoPulseAudio pulseaudio;
#endif
#ifdef SOUNDIO_HAVE_ALSA
SoundIoAlsa alsa;
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
SoundIoCoreAudio coreaudio;
#endif
#ifdef SOUNDIO_HAVE_WASAPI
SoundIoWasapi wasapi;
#endif
SoundIoDummy dummy;
};
union SoundIoDeviceBackendData {
#ifdef SOUNDIO_HAVE_JACK
SoundIoDeviceJack jack;
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
SoundIoDevicePulseAudio pulseaudio;
#endif
#ifdef SOUNDIO_HAVE_ALSA
SoundIoDeviceAlsa alsa;
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
SoundIoDeviceCoreAudio coreaudio;
#endif
#ifdef SOUNDIO_HAVE_WASAPI
SoundIoDeviceWasapi wasapi;
#endif
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
#ifdef SOUNDIO_HAVE_COREAUDIO
SoundIoOutStreamCoreAudio coreaudio;
#endif
#ifdef SOUNDIO_HAVE_WASAPI
SoundIoOutStreamWasapi wasapi;
#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
#ifdef SOUNDIO_HAVE_COREAUDIO
SoundIoInStreamCoreAudio coreaudio;
#endif
#ifdef SOUNDIO_HAVE_WASAPI
SoundIoInStreamWasapi wasapi;
#endif
SoundIoInStreamDummy dummy;
};
struct SoundIoDevicesInfo {
SoundIoList<SoundIoDevice *> input_devices;
SoundIoList<SoundIoDevice *> output_devices;
// can be -1 when default device is unknown
int default_output_index;
int default_input_index;
};
struct SoundIoOutStreamPrivate {
SoundIoOutStream pub;
SoundIoOutStreamBackendData backend_data;
};
struct SoundIoInStreamPrivate {
SoundIoInStream pub;
SoundIoInStreamBackendData backend_data;
};
struct SoundIoPrivate {
struct SoundIo pub;
// Safe to read from a single thread without a mutex.
struct SoundIoDevicesInfo *safe_devices_info;
void (*destroy)(struct SoundIoPrivate *);
void (*flush_events)(struct SoundIoPrivate *);
void (*wait_events)(struct SoundIoPrivate *);
void (*wakeup)(struct SoundIoPrivate *);
void (*force_device_scan)(struct SoundIoPrivate *);
int (*outstream_open)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
void (*outstream_destroy)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_start)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_begin_write)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *,
SoundIoChannelArea **out_areas, int *out_frame_count);
int (*outstream_end_write)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_clear_buffer)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_pause)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, bool pause);
int (*outstream_get_latency)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, double *out_latency);
int (*instream_open)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
void (*instream_destroy)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
int (*instream_start)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
int (*instream_begin_read)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *,
SoundIoChannelArea **out_areas, int *out_frame_count);
int (*instream_end_read)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
int (*instream_pause)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *, bool pause);
int (*instream_get_latency)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *, double *out_latency);
SoundIoBackendData backend_data;
};
struct SoundIoDevicePrivate {
SoundIoDevice pub;
SoundIoDeviceBackendData backend_data;
void (*destruct)(SoundIoDevicePrivate *);
SoundIoSampleRateRange prealloc_sample_rate_range;
SoundIoList<SoundIoSampleRateRange> sample_rates;
SoundIoFormat prealloc_format;
};
void soundio_destroy_devices_info(struct SoundIoDevicesInfo *devices_info);
static const int SOUNDIO_MIN_SAMPLE_RATE = 8000;
static const int SOUNDIO_MAX_SAMPLE_RATE = 5644800;
#endif

16
src/soundio_internal.h Normal file
View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of libsoundio, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_SOUNDIO_INTERNAL_H
#define SOUNDIO_SOUNDIO_INTERNAL_H
// This exists for __declspec(dllexport) and __declspec(dllimport) to be
// defined correctly without the library user having to do anything.
#define SOUNDIO_BUILDING_LIBRARY
#include "soundio/soundio.h"
#endif

View file

@ -8,9 +8,177 @@
#ifndef SOUNDIO_SOUNDIO_PRIVATE_H
#define SOUNDIO_SOUNDIO_PRIVATE_H
// This exists for __declspec(dllexport) and __declspec(dllimport) to be
// defined correctly without the library user having to do anything.
#define SOUNDIO_BUILDING_LIBRARY
#include "soundio/soundio.h"
#include "soundio_internal.h"
#ifdef SOUNDIO_HAVE_JACK
#include "jack.h"
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
#include "pulseaudio.h"
#endif
#ifdef SOUNDIO_HAVE_ALSA
#include "alsa.h"
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
#include "coreaudio.h"
#endif
#ifdef SOUNDIO_HAVE_WASAPI
#include "wasapi.h"
#endif
#include "dummy.h"
union SoundIoBackendData {
#ifdef SOUNDIO_HAVE_JACK
struct SoundIoJack jack;
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
struct SoundIoPulseAudio pulseaudio;
#endif
#ifdef SOUNDIO_HAVE_ALSA
struct SoundIoAlsa alsa;
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
struct SoundIoCoreAudio coreaudio;
#endif
#ifdef SOUNDIO_HAVE_WASAPI
struct SoundIoWasapi wasapi;
#endif
struct SoundIoDummy dummy;
};
union SoundIoDeviceBackendData {
#ifdef SOUNDIO_HAVE_JACK
struct SoundIoDeviceJack jack;
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
struct SoundIoDevicePulseAudio pulseaudio;
#endif
#ifdef SOUNDIO_HAVE_ALSA
struct SoundIoDeviceAlsa alsa;
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
struct SoundIoDeviceCoreAudio coreaudio;
#endif
#ifdef SOUNDIO_HAVE_WASAPI
struct SoundIoDeviceWasapi wasapi;
#endif
struct SoundIoDeviceDummy dummy;
};
union SoundIoOutStreamBackendData {
#ifdef SOUNDIO_HAVE_JACK
struct SoundIoOutStreamJack jack;
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
struct SoundIoOutStreamPulseAudio pulseaudio;
#endif
#ifdef SOUNDIO_HAVE_ALSA
struct SoundIoOutStreamAlsa alsa;
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
struct SoundIoOutStreamCoreAudio coreaudio;
#endif
#ifdef SOUNDIO_HAVE_WASAPI
struct SoundIoOutStreamWasapi wasapi;
#endif
struct SoundIoOutStreamDummy dummy;
};
union SoundIoInStreamBackendData {
#ifdef SOUNDIO_HAVE_JACK
struct SoundIoInStreamJack jack;
#endif
#ifdef SOUNDIO_HAVE_PULSEAUDIO
struct SoundIoInStreamPulseAudio pulseaudio;
#endif
#ifdef SOUNDIO_HAVE_ALSA
struct SoundIoInStreamAlsa alsa;
#endif
#ifdef SOUNDIO_HAVE_COREAUDIO
struct SoundIoInStreamCoreAudio coreaudio;
#endif
#ifdef SOUNDIO_HAVE_WASAPI
struct SoundIoInStreamWasapi wasapi;
#endif
struct SoundIoInStreamDummy dummy;
};
SOUNDIO_MAKE_LIST_STRUCT(struct SoundIoDevice*, SoundIoListDevicePtr, SOUNDIO_LIST_NOT_STATIC)
SOUNDIO_MAKE_LIST_PROTO(struct SoundIoDevice*, SoundIoListDevicePtr, SOUNDIO_LIST_NOT_STATIC)
struct SoundIoDevicesInfo {
struct SoundIoListDevicePtr input_devices;
struct SoundIoListDevicePtr output_devices;
// can be -1 when default device is unknown
int default_output_index;
int default_input_index;
};
struct SoundIoOutStreamPrivate {
struct SoundIoOutStream pub;
union SoundIoOutStreamBackendData backend_data;
};
struct SoundIoInStreamPrivate {
struct SoundIoInStream pub;
union SoundIoInStreamBackendData backend_data;
};
struct SoundIoPrivate {
struct SoundIo pub;
// Safe to read from a single thread without a mutex.
struct SoundIoDevicesInfo *safe_devices_info;
void (*destroy)(struct SoundIoPrivate *);
void (*flush_events)(struct SoundIoPrivate *);
void (*wait_events)(struct SoundIoPrivate *);
void (*wakeup)(struct SoundIoPrivate *);
void (*force_device_scan)(struct SoundIoPrivate *);
int (*outstream_open)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
void (*outstream_destroy)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_start)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_begin_write)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *,
struct SoundIoChannelArea **out_areas, int *out_frame_count);
int (*outstream_end_write)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_clear_buffer)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
int (*outstream_pause)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, bool pause);
int (*outstream_get_latency)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *, double *out_latency);
int (*instream_open)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
void (*instream_destroy)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
int (*instream_start)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
int (*instream_begin_read)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *,
struct SoundIoChannelArea **out_areas, int *out_frame_count);
int (*instream_end_read)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *);
int (*instream_pause)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *, bool pause);
int (*instream_get_latency)(struct SoundIoPrivate *, struct SoundIoInStreamPrivate *, double *out_latency);
union SoundIoBackendData backend_data;
};
SOUNDIO_MAKE_LIST_STRUCT(struct SoundIoSampleRateRange, SoundIoListSampleRateRange, SOUNDIO_LIST_NOT_STATIC)
SOUNDIO_MAKE_LIST_PROTO(struct SoundIoSampleRateRange, SoundIoListSampleRateRange, SOUNDIO_LIST_NOT_STATIC)
struct SoundIoDevicePrivate {
struct SoundIoDevice pub;
union SoundIoDeviceBackendData backend_data;
void (*destruct)(struct SoundIoDevicePrivate *);
struct SoundIoSampleRateRange prealloc_sample_rate_range;
struct SoundIoListSampleRateRange sample_rates;
enum SoundIoFormat prealloc_format;
};
void soundio_destroy_devices_info(struct SoundIoDevicesInfo *devices_info);
static const int SOUNDIO_MIN_SAMPLE_RATE = 8000;
static const int SOUNDIO_MAX_SAMPLE_RATE = 5644800;
#endif

View file

@ -9,7 +9,7 @@
#include <stdio.h>
#include <stdarg.h>
#include "util.hpp"
#include "util.h"
void soundio_panic(const char *format, ...) {
va_list ap;
@ -25,13 +25,13 @@ char *soundio_alloc_sprintf(int *len, const char *format, ...) {
va_start(ap, format);
va_copy(ap2, ap);
int len1 = vsnprintf(nullptr, 0, format, ap);
int len1 = vsnprintf(NULL, 0, format, ap);
assert(len1 >= 0);
size_t required_size = len1 + 1;
char *mem = allocate<char>(required_size);
char *mem = ALLOCATE(char, required_size);
if (!mem)
return nullptr;
return NULL;
int len2 = vsnprintf(mem, required_size, format, ap2);
assert(len2 == len1);

View file

@ -5,26 +5,44 @@
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_UTIL_HPP
#define SOUNDIO_UTIL_HPP
#ifndef SOUNDIO_UTIL_H
#define SOUNDIO_UTIL_H
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
template<typename T>
__attribute__((malloc)) static inline T *allocate_nonzero(size_t count) {
return reinterpret_cast<T*>(malloc(count * sizeof(T)));
#define ALLOCATE_NONZERO(Type, count) malloc((count) * sizeof(Type))
#define ALLOCATE(Type, count) calloc(count, sizeof(Type))
#define REALLOCATE_NONZERO(Type, old, new_count) realloc(old, (new_count) * sizeof(Type))
#define ARRAY_LENGTH(array) (sizeof(array)/sizeof((array)[0]))
static inline int soundio_int_min(int a, int b) {
return (a <= b) ? a : b;
}
template<typename T>
__attribute__((malloc)) static inline T *allocate(size_t count) {
return reinterpret_cast<T*>(calloc(count, sizeof(T)));
static inline int soundio_int_max(int a, int b) {
return (a >= b) ? a : b;
}
template<typename T>
static inline T *reallocate_nonzero(T * old, size_t new_count) {
return reinterpret_cast<T*>(realloc(old, new_count * sizeof(T)));
static inline int soundio_int_clamp(int min_value, int value, int max_value) {
return soundio_int_max(soundio_int_min(value, max_value), min_value);
}
static inline double soundio_double_min(double a, double b) {
return (a <= b) ? a : b;
}
static inline double soundio_double_max(double a, double b) {
return (a >= b) ? a : b;
}
static inline double soundio_double_clamp(double min_value, double value, double max_value) {
return soundio_double_max(soundio_double_min(value, max_value), min_value);
}
void soundio_panic(const char *format, ...)
@ -36,9 +54,9 @@ char *soundio_alloc_sprintf(int *len, const char *format, ...)
__attribute__ ((format (printf, 2, 3)));
static inline char *soundio_str_dupe(const char *str, int str_len) {
char *out = allocate_nonzero<char>(str_len + 1);
char *out = ALLOCATE_NONZERO(char, str_len + 1);
if (!out)
return nullptr;
return NULL;
memcpy(out, str, str_len);
out[str_len] = 0;
return out;
@ -61,24 +79,4 @@ static inline double ceil_dbl(double x) {
return ceiling;
}
template <typename T, long n>
static constexpr long array_length(const T (&)[n]) {
return n;
}
template <typename T>
static inline T max(T a, T b) {
return (a >= b) ? a : b;
}
template <typename T>
static inline T min(T a, T b) {
return (a <= b) ? a : b;
}
template<typename T>
static inline T clamp(T min_value, T value, T max_value) {
return max(min(value, max_value), min_value);
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -5,13 +5,13 @@
* See http://opensource.org/licenses/MIT
*/
#ifndef SOUNDIO_WASAPI_HPP
#define SOUNDIO_WASAPI_HPP
#ifndef SOUNDIO_WASAPI_H
#define SOUNDIO_WASAPI_H
#include "soundio_private.h"
#include "soundio_internal.h"
#include "os.h"
#include "atomics.hpp"
#include "list.hpp"
#include "list.h"
#include "atomics.h"
#define INITGUID
#define CINTERFACE
@ -25,6 +25,7 @@
#include <audiosessiontypes.h>
#include <audiopolicy.h>
struct SoundIoPrivate;
int soundio_wasapi_init(struct SoundIoPrivate *si);
struct SoundIoDeviceWasapi {
@ -33,10 +34,10 @@ struct SoundIoDeviceWasapi {
};
struct SoundIoWasapi {
SoundIoOsMutex *mutex;
SoundIoOsCond *cond;
SoundIoOsCond *scan_devices_cond;
SoundIoOsMutex *scan_devices_mutex;
struct SoundIoOsMutex *mutex;
struct SoundIoOsCond *cond;
struct SoundIoOsCond *scan_devices_cond;
struct SoundIoOsMutex *scan_devices_mutex;
struct SoundIoOsThread *thread;
bool abort_flag;
// this one is ready to be read with flush_events. protected by mutex
@ -58,17 +59,17 @@ struct SoundIoOutStreamWasapi {
IAudioSessionControl *audio_session_control;
LPWSTR stream_name;
bool need_resample;
SoundIoOsThread *thread;
SoundIoOsMutex *mutex;
SoundIoOsCond *cond;
SoundIoOsCond *start_cond;
struct SoundIoOsThread *thread;
struct SoundIoOsMutex *mutex;
struct SoundIoOsCond *cond;
struct SoundIoOsCond *start_cond;
atomic_flag thread_exit_flag;
bool is_raw;
int writable_frame_count;
UINT32 buffer_frame_count;
int write_frame_count;
HANDLE h_event;
atomic_bool desired_pause_state;
struct SoundIoAtomicBool desired_pause_state;
atomic_flag pause_resume_flag;
atomic_flag clear_buffer_flag;
bool is_paused;
@ -76,7 +77,7 @@ struct SoundIoOutStreamWasapi {
int open_err;
bool started;
UINT32 min_padding_frames;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
struct SoundIoInStreamWasapi {
@ -84,10 +85,10 @@ struct SoundIoInStreamWasapi {
IAudioCaptureClient *audio_capture_client;
IAudioSessionControl *audio_session_control;
LPWSTR stream_name;
SoundIoOsThread *thread;
SoundIoOsMutex *mutex;
SoundIoOsCond *cond;
SoundIoOsCond *start_cond;
struct SoundIoOsThread *thread;
struct SoundIoOsMutex *mutex;
struct SoundIoOsCond *cond;
struct SoundIoOsCond *start_cond;
atomic_flag thread_exit_flag;
bool is_raw;
int readable_frame_count;
@ -100,7 +101,7 @@ struct SoundIoInStreamWasapi {
bool started;
char *read_buf;
int read_buf_frames_left;
SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
};
#endif

View file

@ -5,15 +5,15 @@
* See http://opensource.org/licenses/MIT
*/
#include "soundio.hpp"
#include "soundio_private.h"
#include "os.h"
#include "util.hpp"
#include "atomics.hpp"
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
static int usage(char *exe) {
fprintf(stderr, "Usage: %s [--backend dummy|alsa|pulseaudio|jack|coreaudio|wasapi] [--latency seconds]\n", exe);
@ -51,9 +51,9 @@ static int pulse_frames_left = -1;
static const double PI = 3.14159265358979323846264338328;
static double seconds_offset = 0.0;
static SoundIoRingBuffer pulse_rb;
static struct SoundIoRingBuffer pulse_rb;
static void write_time(SoundIoOutStream *outstream, double extra) {
static void write_time(struct SoundIoOutStream *outstream, double extra) {
double latency;
int err;
if ((err = soundio_outstream_get_latency(outstream, &latency))) {

View file

@ -1,9 +1,9 @@
#undef NDEBUG
#include "soundio.hpp"
#include "soundio_private.h"
#include "os.h"
#include "util.hpp"
#include "atomics.hpp"
#include "util.h"
#include "atomics.h"
#include <stdio.h>
#include <string.h>
@ -58,7 +58,7 @@ static void test_create_outstream(void) {
static void test_ring_buffer_basic(void) {
struct SoundIo *soundio = soundio_create();
assert(soundio);
SoundIoRingBuffer *rb = soundio_ring_buffer_create(soundio, 10);
struct SoundIoRingBuffer *rb = soundio_ring_buffer_create(soundio, 10);
assert(rb);
int page_size = soundio_os_page_size();
@ -98,41 +98,41 @@ static void test_ring_buffer_basic(void) {
soundio_destroy(soundio);
}
static SoundIoRingBuffer *rb = nullptr;
static struct SoundIoRingBuffer *rb = NULL;
static const int rb_size = 3528;
static long expected_write_head;
static long expected_read_head;
static atomic_bool rb_done;
static atomic_int rb_write_it;
static atomic_int rb_read_it;
static struct SoundIoAtomicBool rb_done;
static struct SoundIoAtomicInt rb_write_it;
static struct SoundIoAtomicInt rb_read_it;
// just for testing purposes; does not need to be high quality random
static double random_double(void) {
return ((double)rand() / (double)RAND_MAX);
}
static void reader_thread_run(void *) {
while (!rb_done) {
rb_read_it += 1;
static void reader_thread_run(void *arg) {
while (!SOUNDIO_ATOMIC_LOAD(rb_done)) {
SOUNDIO_ATOMIC_FETCH_ADD(rb_read_it, 1);
int fill_count = soundio_ring_buffer_fill_count(rb);
assert(fill_count >= 0);
assert(fill_count <= rb_size);
int amount_to_read = min((int)(random_double() * 2.0 * fill_count), fill_count);
int amount_to_read = soundio_int_min(random_double() * 2.0 * fill_count, fill_count);
soundio_ring_buffer_advance_read_ptr(rb, amount_to_read);
expected_read_head += amount_to_read;
}
}
static void writer_thread_run(void *) {
while (!rb_done) {
rb_write_it += 1;
static void writer_thread_run(void *arg) {
while (!SOUNDIO_ATOMIC_LOAD(rb_done)) {
SOUNDIO_ATOMIC_FETCH_ADD(rb_write_it, 1);
int fill_count = soundio_ring_buffer_fill_count(rb);
assert(fill_count >= 0);
assert(fill_count <= rb_size);
int free_count = rb_size - fill_count;
assert(free_count >= 0);
assert(free_count <= rb_size);
int value = min((int)(random_double() * 2.0 * free_count), free_count);
int value = soundio_int_min(random_double() * 2.0 * free_count, free_count);
soundio_ring_buffer_advance_write_ptr(rb, value);
expected_write_head += value;
}
@ -144,18 +144,18 @@ static void test_ring_buffer_threaded(void) {
rb = soundio_ring_buffer_create(soundio, rb_size);
expected_write_head = 0;
expected_read_head = 0;
rb_read_it = 0;
rb_write_it = 0;
rb_done = false;
SOUNDIO_ATOMIC_STORE(rb_read_it, 0);
SOUNDIO_ATOMIC_STORE(rb_write_it, 0);
SOUNDIO_ATOMIC_STORE(rb_done, false);
SoundIoOsThread *reader_thread;
ok_or_panic(soundio_os_thread_create(reader_thread_run, nullptr, nullptr, &reader_thread));
struct SoundIoOsThread *reader_thread;
ok_or_panic(soundio_os_thread_create(reader_thread_run, NULL, NULL, &reader_thread));
SoundIoOsThread *writer_thread;
ok_or_panic(soundio_os_thread_create(writer_thread_run, nullptr, nullptr, &writer_thread));
struct SoundIoOsThread *writer_thread;
ok_or_panic(soundio_os_thread_create(writer_thread_run, NULL, NULL, &writer_thread));
while (rb_read_it < 100000 || rb_write_it < 100000) {}
rb_done = true;
while (SOUNDIO_ATOMIC_LOAD(rb_read_it) < 100000 || SOUNDIO_ATOMIC_LOAD(rb_write_it) < 100000) {}
SOUNDIO_ATOMIC_STORE(rb_done, true);
soundio_os_thread_destroy(reader_thread);
soundio_os_thread_destroy(writer_thread);
@ -219,10 +219,10 @@ struct Test {
static struct Test tests[] = {
{"os_get_time", test_os_get_time},
{"create output stream", test_create_outstream},
{"ring buffer basic", test_ring_buffer_basic},
{"ring buffer threaded", test_ring_buffer_threaded},
{"mirrored memory", test_mirrored_memory},
{"soundio_device_nearest_sample_rate", test_nearest_sample_rate},
{"ring buffer basic", test_ring_buffer_basic},
{"ring buffer threaded", test_ring_buffer_threaded},
{NULL, NULL},
};
@ -233,7 +233,7 @@ static void exec_test(struct Test *test) {
}
int main(int argc, char *argv[]) {
const char *match = nullptr;
const char *match = NULL;
if (argc == 2)
match = argv[1];