mirror of
				https://github.com/Ryujinx/libsoundio.git
				synced 2025-11-04 09:34:48 +00:00 
			
		
		
		
	Merge pull request #50 from hotgloupi/master
[RDY] Compile in C++ mode using the <atomic> header
This commit is contained in:
		
						commit
						6b8c306ea1
					
				| 
						 | 
				
			
			@ -18,14 +18,18 @@
 | 
			
		|||
#define SOUNDIO_EXTERN_C
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
#if defined(SOUNDIO_BUILDING_LIBRARY)
 | 
			
		||||
#define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __declspec(dllexport)
 | 
			
		||||
#if defined(SOUNDIO_STATIC_LIBRARY)
 | 
			
		||||
# define SOUNDIO_EXPORT SOUNDIO_EXTERN_C
 | 
			
		||||
#else
 | 
			
		||||
#define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __declspec(dllimport)
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __attribute__((visibility ("default")))
 | 
			
		||||
# if defined(_WIN32)
 | 
			
		||||
#  if defined(SOUNDIO_BUILDING_LIBRARY)
 | 
			
		||||
#   define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __declspec(dllexport)
 | 
			
		||||
#  else
 | 
			
		||||
#   define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __declspec(dllimport)
 | 
			
		||||
#  endif
 | 
			
		||||
# else
 | 
			
		||||
#  define SOUNDIO_EXPORT SOUNDIO_EXTERN_C __attribute__((visibility ("default")))
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
/// \endcond
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										30
									
								
								src/alsa.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/alsa.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -51,7 +51,7 @@ static void destroy_alsa(struct SoundIoPrivate *si) {
 | 
			
		|||
    struct SoundIoAlsa *sia = &si->backend_data.alsa;
 | 
			
		||||
 | 
			
		||||
    if (sia->thread) {
 | 
			
		||||
        atomic_flag_clear(&sia->abort_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(sia->abort_flag);
 | 
			
		||||
        wakeup_device_poll(sia);
 | 
			
		||||
        soundio_os_thread_destroy(sia->thread);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -804,7 +804,7 @@ static void device_thread_run(void *arg) {
 | 
			
		|||
    int err;
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        int poll_num = poll(fds, 2, -1);
 | 
			
		||||
        if (!atomic_flag_test_and_set(&sia->abort_flag))
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(sia->abort_flag))
 | 
			
		||||
            break;
 | 
			
		||||
        if (poll_num == -1) {
 | 
			
		||||
            if (errno == EINTR)
 | 
			
		||||
| 
						 | 
				
			
			@ -980,7 +980,7 @@ static void outstream_destroy_alsa(struct SoundIoPrivate *si, struct SoundIoOutS
 | 
			
		|||
    struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
 | 
			
		||||
 | 
			
		||||
    if (osa->thread) {
 | 
			
		||||
        atomic_flag_clear(&osa->thread_exit_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(osa->thread_exit_flag);
 | 
			
		||||
        wakeup_outstream_poll(osa);
 | 
			
		||||
        soundio_os_thread_destroy(osa->thread);
 | 
			
		||||
        osa->thread = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -1049,7 +1049,7 @@ static int outstream_wait_for_poll(struct SoundIoOutStreamPrivate *os) {
 | 
			
		|||
        if ((err = poll(osa->poll_fds, osa->poll_fd_count_with_extra, -1)) < 0) {
 | 
			
		||||
            return SoundIoErrorStreaming;
 | 
			
		||||
        }
 | 
			
		||||
        if (!atomic_flag_test_and_set(&osa->thread_exit_flag))
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osa->thread_exit_flag))
 | 
			
		||||
            return SoundIoErrorInterrupted;
 | 
			
		||||
        if ((err = snd_pcm_poll_descriptors_revents(osa->handle,
 | 
			
		||||
                        osa->poll_fds, osa->poll_fd_count, &revents)) < 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -1113,7 +1113,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 (!atomic_flag_test_and_set(&osa->thread_exit_flag))
 | 
			
		||||
                    if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osa->thread_exit_flag))
 | 
			
		||||
                        return;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -1133,9 +1133,9 @@ static void outstream_thread_run(void *arg) {
 | 
			
		|||
                    outstream->error_callback(outstream, err);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                if (!atomic_flag_test_and_set(&osa->thread_exit_flag))
 | 
			
		||||
                if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osa->thread_exit_flag))
 | 
			
		||||
                    return;
 | 
			
		||||
                if (!atomic_flag_test_and_set(&osa->clear_buffer_flag)) {
 | 
			
		||||
                if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osa->clear_buffer_flag)) {
 | 
			
		||||
                    if ((err = snd_pcm_drop(osa->handle)) < 0) {
 | 
			
		||||
                        outstream->error_callback(outstream, SoundIoErrorStreaming);
 | 
			
		||||
                        return;
 | 
			
		||||
| 
						 | 
				
			
			@ -1213,12 +1213,12 @@ static void instream_thread_run(void *arg) {
 | 
			
		|||
            case SND_PCM_STATE_PAUSED:
 | 
			
		||||
            {
 | 
			
		||||
                if ((err = instream_wait_for_poll(is)) < 0) {
 | 
			
		||||
                    if (!atomic_flag_test_and_set(&isa->thread_exit_flag))
 | 
			
		||||
                    if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(isa->thread_exit_flag))
 | 
			
		||||
                        return;
 | 
			
		||||
                    instream->error_callback(instream, SoundIoErrorStreaming);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                if (!atomic_flag_test_and_set(&isa->thread_exit_flag))
 | 
			
		||||
                if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(isa->thread_exit_flag))
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                snd_pcm_sframes_t avail = snd_pcm_avail_update(isa->handle);
 | 
			
		||||
| 
						 | 
				
			
			@ -1261,7 +1261,7 @@ static int outstream_open_alsa(struct SoundIoPrivate *si, struct SoundIoOutStrea
 | 
			
		|||
    struct SoundIoOutStream *outstream = &os->pub;
 | 
			
		||||
    struct SoundIoDevice *device = outstream->device;
 | 
			
		||||
 | 
			
		||||
    atomic_flag_test_and_set(&osa->clear_buffer_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osa->clear_buffer_flag);
 | 
			
		||||
 | 
			
		||||
    if (outstream->software_latency == 0.0)
 | 
			
		||||
        outstream->software_latency = 1.0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1426,7 +1426,7 @@ static int outstream_start_alsa(struct SoundIoPrivate *si, struct SoundIoOutStre
 | 
			
		|||
    assert(!osa->thread);
 | 
			
		||||
 | 
			
		||||
    int err;
 | 
			
		||||
    atomic_flag_test_and_set(&osa->thread_exit_flag);
 | 
			
		||||
    SOUNDIO_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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1515,7 +1515,7 @@ static int outstream_clear_buffer_alsa(struct SoundIoPrivate *si,
 | 
			
		|||
        struct SoundIoOutStreamPrivate *os)
 | 
			
		||||
{
 | 
			
		||||
    struct SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
 | 
			
		||||
    atomic_flag_clear(&osa->clear_buffer_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_CLEAR(osa->clear_buffer_flag);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1560,7 +1560,7 @@ static void instream_destroy_alsa(struct SoundIoPrivate *si, struct SoundIoInStr
 | 
			
		|||
    struct SoundIoInStreamAlsa *isa = &is->backend_data.alsa;
 | 
			
		||||
 | 
			
		||||
    if (isa->thread) {
 | 
			
		||||
        atomic_flag_clear(&isa->thread_exit_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(isa->thread_exit_flag);
 | 
			
		||||
        soundio_os_thread_destroy(isa->thread);
 | 
			
		||||
        isa->thread = NULL;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1727,7 +1727,7 @@ static int instream_start_alsa(struct SoundIoPrivate *si, struct SoundIoInStream
 | 
			
		|||
 | 
			
		||||
    assert(!isa->thread);
 | 
			
		||||
 | 
			
		||||
    atomic_flag_test_and_set(&isa->thread_exit_flag);
 | 
			
		||||
    SOUNDIO_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);
 | 
			
		||||
| 
						 | 
				
			
			@ -1857,7 +1857,7 @@ int soundio_alsa_init(struct SoundIoPrivate *si) {
 | 
			
		|||
 | 
			
		||||
    sia->notify_fd = -1;
 | 
			
		||||
    sia->notify_wd = -1;
 | 
			
		||||
    atomic_flag_test_and_set(&sia->abort_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(sia->abort_flag);
 | 
			
		||||
 | 
			
		||||
    sia->mutex = soundio_os_mutex_create();
 | 
			
		||||
    if (!sia->mutex) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ struct SoundIoAlsa {
 | 
			
		|||
    struct SoundIoOsCond *cond;
 | 
			
		||||
 | 
			
		||||
    struct SoundIoOsThread *thread;
 | 
			
		||||
    atomic_flag abort_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag abort_flag;
 | 
			
		||||
    int notify_fd;
 | 
			
		||||
    int notify_wd;
 | 
			
		||||
    bool have_devices_flag;
 | 
			
		||||
| 
						 | 
				
			
			@ -60,11 +60,11 @@ struct SoundIoOutStreamAlsa {
 | 
			
		|||
    struct pollfd *poll_fds;
 | 
			
		||||
    int poll_exit_pipe_fd[2];
 | 
			
		||||
    struct SoundIoOsThread *thread;
 | 
			
		||||
    atomic_flag thread_exit_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag thread_exit_flag;
 | 
			
		||||
    snd_pcm_uframes_t period_size;
 | 
			
		||||
    int write_frame_count;
 | 
			
		||||
    bool is_paused;
 | 
			
		||||
    atomic_flag clear_buffer_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag clear_buffer_flag;
 | 
			
		||||
    struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +79,7 @@ struct SoundIoInStreamAlsa {
 | 
			
		|||
    int poll_fd_count;
 | 
			
		||||
    struct pollfd *poll_fds;
 | 
			
		||||
    struct SoundIoOsThread *thread;
 | 
			
		||||
    atomic_flag thread_exit_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag thread_exit_flag;
 | 
			
		||||
    int period_size;
 | 
			
		||||
    int read_frame_count;
 | 
			
		||||
    bool is_paused;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,36 @@
 | 
			
		|||
// Simple wrappers around atomic values so that the compiler will catch it if
 | 
			
		||||
// I accidentally use operators such as +, -, += on them.
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
 | 
			
		||||
struct SoundIoAtomicLong {
 | 
			
		||||
    std::atomic<long> x;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SoundIoAtomicInt {
 | 
			
		||||
    std::atomic<int> x;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SoundIoAtomicBool {
 | 
			
		||||
    std::atomic<bool> x;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SoundIoAtomicFlag {
 | 
			
		||||
    std::atomic_flag x;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SOUNDIO_ATOMIC_LOAD(a) (a.x.load())
 | 
			
		||||
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) (a.x.fetch_add(delta))
 | 
			
		||||
#define SOUNDIO_ATOMIC_STORE(a, value) (a.x.store(value))
 | 
			
		||||
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) (a.x.exchange(value))
 | 
			
		||||
#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) (a.x.test_and_set())
 | 
			
		||||
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) (a.x.clear())
 | 
			
		||||
#define SOUNDIO_ATOMIC_FLAG_INIT {ATOMIC_FLAG_INIT}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#include <stdatomic.h>
 | 
			
		||||
 | 
			
		||||
struct SoundIoAtomicLong {
 | 
			
		||||
| 
						 | 
				
			
			@ -25,9 +55,18 @@ struct SoundIoAtomicBool {
 | 
			
		|||
    atomic_bool x;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SoundIoAtomicFlag {
 | 
			
		||||
    atomic_flag 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)
 | 
			
		||||
#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) atomic_flag_test_and_set(&a.x)
 | 
			
		||||
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) atomic_flag_clear(&a.x)
 | 
			
		||||
#define SOUNDIO_ATOMIC_FLAG_INIT {ATOMIC_FLAG_INIT}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,14 +10,14 @@
 | 
			
		|||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		||||
    [SoundIoChannelLayoutIdMono] = {
 | 
			
		||||
    {
 | 
			
		||||
        "Mono",
 | 
			
		||||
        1,
 | 
			
		||||
        {
 | 
			
		||||
            SoundIoChannelIdFrontCenter,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutIdStereo] = {
 | 
			
		||||
    {
 | 
			
		||||
        "Stereo",
 | 
			
		||||
        2,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdFrontRight,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId2Point1] = {
 | 
			
		||||
    {
 | 
			
		||||
        "2.1",
 | 
			
		||||
        3,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId3Point0] = {
 | 
			
		||||
    {
 | 
			
		||||
        "3.0",
 | 
			
		||||
        3,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdFrontCenter,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId3Point0Back] = {
 | 
			
		||||
    {
 | 
			
		||||
        "3.0 (back)",
 | 
			
		||||
        3,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +52,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdBackCenter,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId3Point1] = {
 | 
			
		||||
    {
 | 
			
		||||
        "3.1",
 | 
			
		||||
        4,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId4Point0] = {
 | 
			
		||||
    {
 | 
			
		||||
        "4.0",
 | 
			
		||||
        4,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdBackCenter,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutIdQuad] = {
 | 
			
		||||
    {
 | 
			
		||||
        "Quad",
 | 
			
		||||
        4,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdBackRight,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutIdQuadSide] = {
 | 
			
		||||
    {
 | 
			
		||||
        "Quad (side)",
 | 
			
		||||
        4,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdSideRight,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId4Point1] = {
 | 
			
		||||
    {
 | 
			
		||||
        "4.1",
 | 
			
		||||
        5,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId5Point0Back] = {
 | 
			
		||||
    {
 | 
			
		||||
        "5.0 (back)",
 | 
			
		||||
        5,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdBackRight,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId5Point0Side] = {
 | 
			
		||||
    {
 | 
			
		||||
        "5.0 (side)",
 | 
			
		||||
        5,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +125,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdSideRight,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId5Point1] = {
 | 
			
		||||
    {
 | 
			
		||||
        "5.1",
 | 
			
		||||
        6,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +137,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId5Point1Back] = {
 | 
			
		||||
    {
 | 
			
		||||
        "5.1 (back)",
 | 
			
		||||
        6,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -149,7 +149,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId6Point0Side] = {
 | 
			
		||||
    {
 | 
			
		||||
        "6.0 (side)",
 | 
			
		||||
        6,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +161,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdBackCenter,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId6Point0Front] = {
 | 
			
		||||
    {
 | 
			
		||||
        "6.0 (front)",
 | 
			
		||||
        6,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +173,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdFrontRightCenter,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutIdHexagonal] = {
 | 
			
		||||
    {
 | 
			
		||||
        "Hexagonal",
 | 
			
		||||
        6,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +185,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdBackCenter,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId6Point1] = {
 | 
			
		||||
    {
 | 
			
		||||
        "6.1",
 | 
			
		||||
        7,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +198,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId6Point1Back] = {
 | 
			
		||||
    {
 | 
			
		||||
        "6.1 (back)",
 | 
			
		||||
        7,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -211,7 +211,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId6Point1Front] = {
 | 
			
		||||
    {
 | 
			
		||||
        "6.1 (front)",
 | 
			
		||||
        7,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +224,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId7Point0] = {
 | 
			
		||||
    {
 | 
			
		||||
        "7.0",
 | 
			
		||||
        7,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -237,7 +237,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdBackRight,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId7Point0Front] = {
 | 
			
		||||
    {
 | 
			
		||||
        "7.0 (front)",
 | 
			
		||||
        7,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -250,7 +250,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdFrontRightCenter,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId7Point1] = {
 | 
			
		||||
    {
 | 
			
		||||
        "7.1",
 | 
			
		||||
        8,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +264,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId7Point1Wide] = {
 | 
			
		||||
    {
 | 
			
		||||
        "7.1 (wide)",
 | 
			
		||||
        8,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -278,7 +278,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutId7Point1WideBack] = {
 | 
			
		||||
    {
 | 
			
		||||
        "7.1 (wide) (back)",
 | 
			
		||||
        8,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +292,7 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
            SoundIoChannelIdLfe,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelLayoutIdOctagonal] = {
 | 
			
		||||
    {
 | 
			
		||||
        "Octagonal",
 | 
			
		||||
        8,
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -309,352 +309,77 @@ static struct SoundIoChannelLayout builtin_channel_layouts[] = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
#define CHANNEL_NAME_ALIAS_COUNT 3
 | 
			
		||||
static const char *channel_names[][CHANNEL_NAME_ALIAS_COUNT] = {
 | 
			
		||||
    [SoundIoChannelIdInvalid] = {
 | 
			
		||||
        "(Invalid Channel)",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontLeft] = {
 | 
			
		||||
        "Front Left",
 | 
			
		||||
        "FL",
 | 
			
		||||
        "front-left",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontRight] = {
 | 
			
		||||
        "Front Right",
 | 
			
		||||
        "FR",
 | 
			
		||||
        "front-right",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontCenter] = {
 | 
			
		||||
        "Front Center",
 | 
			
		||||
        "FC",
 | 
			
		||||
        "front-center",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdLfe] = {
 | 
			
		||||
        "LFE",
 | 
			
		||||
        "LFE",
 | 
			
		||||
        "lfe",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdBackLeft] = {
 | 
			
		||||
        "Back Left",
 | 
			
		||||
        "BL",
 | 
			
		||||
        "rear-left",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdBackRight] = {
 | 
			
		||||
        "Back Right",
 | 
			
		||||
        "BR",
 | 
			
		||||
        "rear-right",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontLeftCenter] = {
 | 
			
		||||
        "Front Left Center",
 | 
			
		||||
        "FLC",
 | 
			
		||||
        "front-left-of-center",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontRightCenter] = {
 | 
			
		||||
        "Front Right Center",
 | 
			
		||||
        "FRC",
 | 
			
		||||
        "front-right-of-center",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdBackCenter] = {
 | 
			
		||||
        "Back Center",
 | 
			
		||||
        "BC",
 | 
			
		||||
        "rear-center",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdSideLeft] = {
 | 
			
		||||
        "Side Left",
 | 
			
		||||
        "SL",
 | 
			
		||||
        "side-left",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdSideRight] = {
 | 
			
		||||
        "Side Right",
 | 
			
		||||
        "SR",
 | 
			
		||||
        "side-right",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopCenter] = {
 | 
			
		||||
        "Top Center",
 | 
			
		||||
        "TC",
 | 
			
		||||
        "top-center",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopFrontLeft] = {
 | 
			
		||||
        "Top Front Left",
 | 
			
		||||
        "TFL",
 | 
			
		||||
        "top-front-left",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopFrontCenter] = {
 | 
			
		||||
        "Top Front Center",
 | 
			
		||||
        "TFC",
 | 
			
		||||
        "top-front-center",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopFrontRight] = {
 | 
			
		||||
        "Top Front Right",
 | 
			
		||||
        "TFR",
 | 
			
		||||
        "top-front-right",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopBackLeft] = {
 | 
			
		||||
        "Top Back Left",
 | 
			
		||||
        "TBL",
 | 
			
		||||
        "top-rear-left",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopBackCenter] = {
 | 
			
		||||
        "Top Back Center",
 | 
			
		||||
        "TBC",
 | 
			
		||||
        "top-rear-center",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopBackRight] = {
 | 
			
		||||
        "Top Back Right",
 | 
			
		||||
        "TBR",
 | 
			
		||||
        "top-rear-right",
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdBackLeftCenter] = {
 | 
			
		||||
        "Back Left Center",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdBackRightCenter] = {
 | 
			
		||||
        "Back Right Center",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontLeftWide] = {
 | 
			
		||||
        "Front Left Wide",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontRightWide] = {
 | 
			
		||||
        "Front Right Wide",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontLeftHigh] = {
 | 
			
		||||
        "Front Left High",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontCenterHigh] = {
 | 
			
		||||
        "Front Center High",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdFrontRightHigh] = {
 | 
			
		||||
        "Front Right High",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopFrontLeftCenter] = {
 | 
			
		||||
        "Top Front Left Center",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopFrontRightCenter] = {
 | 
			
		||||
        "Top Front Right Center",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopSideLeft] = {
 | 
			
		||||
        "Top Side Left",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdTopSideRight] = {
 | 
			
		||||
        "Top Side Right",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdLeftLfe] = {
 | 
			
		||||
        "Left LFE",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdRightLfe] = {
 | 
			
		||||
        "Right LFE",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdLfe2] = {
 | 
			
		||||
        "LFE 2",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdBottomCenter] = {
 | 
			
		||||
        "Bottom Center",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdBottomLeftCenter] = {
 | 
			
		||||
        "Bottom Left Center",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdBottomRightCenter] = {
 | 
			
		||||
        "Bottom Right Center",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdMsMid] = {
 | 
			
		||||
        "Mid/Side Mid",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdMsSide] = {
 | 
			
		||||
        "Mid/Side Side",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAmbisonicW] = {
 | 
			
		||||
        "Ambisonic W",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAmbisonicX] = {
 | 
			
		||||
        "Ambisonic X",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAmbisonicY] = {
 | 
			
		||||
        "Ambisonic Y",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAmbisonicZ] = {
 | 
			
		||||
        "Ambisonic Z",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdXyX] = {
 | 
			
		||||
        "X-Y X",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdXyY] = {
 | 
			
		||||
        "X-Y Y",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdHeadphonesLeft] = {
 | 
			
		||||
        "Headphones Left",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdHeadphonesRight] = {
 | 
			
		||||
        "Headphones Right",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdClickTrack] = {
 | 
			
		||||
        "Click Track",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdForeignLanguage] = {
 | 
			
		||||
        "Foreign Language",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdHearingImpaired] = {
 | 
			
		||||
        "Hearing Impaired",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdNarration] = {
 | 
			
		||||
        "Narration",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdHaptic] = {
 | 
			
		||||
        "Haptic",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdDialogCentricMix] = {
 | 
			
		||||
        "Dialog Centric Mix",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux] = {
 | 
			
		||||
        "Aux",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux0] = {
 | 
			
		||||
        "Aux 0",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux1] = {
 | 
			
		||||
        "Aux 1",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux2] = {
 | 
			
		||||
        "Aux 2",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux3] = {
 | 
			
		||||
        "Aux 3",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux4] = {
 | 
			
		||||
        "Aux 4",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux5] = {
 | 
			
		||||
        "Aux 5",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux6] = {
 | 
			
		||||
        "Aux 6",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux7] = {
 | 
			
		||||
        "Aux 7",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux8] = {
 | 
			
		||||
        "Aux 8",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux9] = {
 | 
			
		||||
        "Aux 9",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux10] = {
 | 
			
		||||
        "Aux 10",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux11] = {
 | 
			
		||||
        "Aux 11",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux12] = {
 | 
			
		||||
        "Aux 12",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux13] = {
 | 
			
		||||
        "Aux 13",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux14] = {
 | 
			
		||||
        "Aux 14",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
    [SoundIoChannelIdAux15] = {
 | 
			
		||||
        "Aux 15",
 | 
			
		||||
        NULL,
 | 
			
		||||
        NULL,
 | 
			
		||||
    },
 | 
			
		||||
typedef const char *channel_names_t[CHANNEL_NAME_ALIAS_COUNT];
 | 
			
		||||
static channel_names_t channel_names[] = {
 | 
			
		||||
    {"(Invalid Channel)", NULL, NULL},
 | 
			
		||||
    {"Front Left", "FL", "front-left"},
 | 
			
		||||
    {"Front Right", "FR", "front-right"},
 | 
			
		||||
    {"Front Center", "FC", "front-center"},
 | 
			
		||||
    {"LFE", "LFE", "lfe"},
 | 
			
		||||
    {"Back Left", "BL", "rear-left"},
 | 
			
		||||
    {"Back Right", "BR", "rear-right"},
 | 
			
		||||
    {"Front Left Center", "FLC", "front-left-of-center"},
 | 
			
		||||
    {"Front Right Center", "FRC", "front-right-of-center"},
 | 
			
		||||
    {"Back Center", "BC", "rear-center"},
 | 
			
		||||
    {"Side Left", "SL", "side-left"},
 | 
			
		||||
    {"Side Right", "SR", "side-right"},
 | 
			
		||||
    {"Top Center", "TC", "top-center"},
 | 
			
		||||
    {"Top Front Left", "TFL", "top-front-left"},
 | 
			
		||||
    {"Top Front Center", "TFC", "top-front-center"},
 | 
			
		||||
    {"Top Front Right", "TFR", "top-front-right"},
 | 
			
		||||
    {"Top Back Left", "TBL", "top-rear-left"},
 | 
			
		||||
    {"Top Back Center", "TBC", "top-rear-center"},
 | 
			
		||||
    {"Top Back Right", "TBR", "top-rear-right"},
 | 
			
		||||
    {"Back Left Center", NULL, NULL},
 | 
			
		||||
    {"Back Right Center", NULL, NULL},
 | 
			
		||||
    {"Front Left Wide", NULL, NULL},
 | 
			
		||||
    {"Front Right Wide", NULL, NULL},
 | 
			
		||||
    {"Front Left High", NULL, NULL},
 | 
			
		||||
    {"Front Center High", NULL, NULL},
 | 
			
		||||
    {"Front Right High", NULL, NULL},
 | 
			
		||||
    {"Top Front Left Center", NULL, NULL},
 | 
			
		||||
    {"Top Front Right Center", NULL, NULL},
 | 
			
		||||
    {"Top Side Left", NULL, NULL},
 | 
			
		||||
    {"Top Side Right", NULL, NULL},
 | 
			
		||||
    {"Left LFE", NULL, NULL},
 | 
			
		||||
    {"Right LFE", NULL, NULL},
 | 
			
		||||
    {"LFE 2", NULL, NULL},
 | 
			
		||||
    {"Bottom Center", NULL, NULL},
 | 
			
		||||
    {"Bottom Left Center", NULL, NULL},
 | 
			
		||||
    {"Bottom Right Center", NULL, NULL},
 | 
			
		||||
    {"Mid/Side Mid", NULL, NULL},
 | 
			
		||||
    {"Mid/Side Side", NULL, NULL},
 | 
			
		||||
    {"Ambisonic W", NULL, NULL},
 | 
			
		||||
    {"Ambisonic X", NULL, NULL},
 | 
			
		||||
    {"Ambisonic Y", NULL, NULL},
 | 
			
		||||
    {"Ambisonic Z", NULL, NULL},
 | 
			
		||||
    {"X-Y X", NULL, NULL},
 | 
			
		||||
    {"X-Y Y", NULL, NULL},
 | 
			
		||||
    {"Headphones Left", NULL, NULL},
 | 
			
		||||
    {"Headphones Right", NULL, NULL},
 | 
			
		||||
    {"Click Track", NULL, NULL},
 | 
			
		||||
    {"Foreign Language", NULL, NULL},
 | 
			
		||||
    {"Hearing Impaired", NULL, NULL},
 | 
			
		||||
    {"Narration", NULL, NULL},
 | 
			
		||||
    {"Haptic", NULL, NULL},
 | 
			
		||||
    {"Dialog Centric Mix", NULL, NULL},
 | 
			
		||||
    {"Aux", NULL, NULL},
 | 
			
		||||
    {"Aux 0", NULL, NULL},
 | 
			
		||||
    {"Aux 1", NULL, NULL},
 | 
			
		||||
    {"Aux 2", NULL, NULL},
 | 
			
		||||
    {"Aux 3", NULL, NULL},
 | 
			
		||||
    {"Aux 4", NULL, NULL},
 | 
			
		||||
    {"Aux 5", NULL, NULL},
 | 
			
		||||
    {"Aux 6", NULL, NULL},
 | 
			
		||||
    {"Aux 7", NULL, NULL},
 | 
			
		||||
    {"Aux 8", NULL, NULL},
 | 
			
		||||
    {"Aux 9", NULL, NULL},
 | 
			
		||||
    {"Aux 10", NULL, NULL},
 | 
			
		||||
    {"Aux 11", NULL, NULL},
 | 
			
		||||
    {"Aux 12", NULL, NULL},
 | 
			
		||||
    {"Aux 13", NULL, NULL},
 | 
			
		||||
    {"Aux 14", NULL, NULL},
 | 
			
		||||
    {"Aux 15", NULL, NULL},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char *soundio_get_channel_name(enum SoundIoChannelId id) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -152,7 +152,7 @@ static void destroy_ca(struct SoundIoPrivate *si) {
 | 
			
		|||
    SoundIoListAudioDeviceID_deinit(&sica->registered_listeners);
 | 
			
		||||
 | 
			
		||||
    if (sica->thread) {
 | 
			
		||||
        atomic_flag_clear(&sica->abort_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(sica->abort_flag);
 | 
			
		||||
        soundio_os_cond_signal(sica->scan_devices_cond, NULL);
 | 
			
		||||
        soundio_os_thread_destroy(sica->thread);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -846,7 +846,7 @@ static void device_thread_run(void *arg) {
 | 
			
		|||
    int err;
 | 
			
		||||
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        if (!atomic_flag_test_and_set(&sica->abort_flag))
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(sica->abort_flag))
 | 
			
		||||
            break;
 | 
			
		||||
        if (SOUNDIO_ATOMIC_LOAD(sica->service_restarted)) {
 | 
			
		||||
            shutdown_backend(si, SoundIoErrorBackendDisconnected);
 | 
			
		||||
| 
						 | 
				
			
			@ -1348,7 +1348,7 @@ int soundio_coreaudio_init(struct SoundIoPrivate *si) {
 | 
			
		|||
    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);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(sica->abort_flag);
 | 
			
		||||
 | 
			
		||||
    sica->mutex = soundio_os_mutex_create();
 | 
			
		||||
    if (!sica->mutex) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ struct SoundIoCoreAudio {
 | 
			
		|||
    struct SoundIoOsMutex *mutex;
 | 
			
		||||
    struct SoundIoOsCond *cond;
 | 
			
		||||
    struct SoundIoOsThread *thread;
 | 
			
		||||
    atomic_flag abort_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag abort_flag;
 | 
			
		||||
 | 
			
		||||
    // this one is ready to be read with flush_events. protected by mutex
 | 
			
		||||
    struct SoundIoDevicesInfo *ready_devices_info;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								src/dummy.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/dummy.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -25,14 +25,14 @@ static void playback_thread_run(void *arg) {
 | 
			
		|||
    double start_time = soundio_os_get_time();
 | 
			
		||||
    long frames_consumed = 0;
 | 
			
		||||
 | 
			
		||||
    while (atomic_flag_test_and_set(&osd->abort_flag)) {
 | 
			
		||||
    while (SOUNDIO_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, NULL, relative_time);
 | 
			
		||||
        if (!atomic_flag_test_and_set(&osd->clear_buffer_flag)) {
 | 
			
		||||
        if (!SOUNDIO_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;
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +84,7 @@ static void capture_thread_run(void *arg) {
 | 
			
		|||
 | 
			
		||||
    long frames_consumed = 0;
 | 
			
		||||
    double start_time = soundio_os_get_time();
 | 
			
		||||
    while (atomic_flag_test_and_set(&isd->abort_flag)) {
 | 
			
		||||
    while (SOUNDIO_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 +
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +161,7 @@ static void outstream_destroy_dummy(struct SoundIoPrivate *si, struct SoundIoOut
 | 
			
		|||
    struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
 | 
			
		||||
 | 
			
		||||
    if (osd->thread) {
 | 
			
		||||
        atomic_flag_clear(&osd->abort_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(osd->abort_flag);
 | 
			
		||||
        soundio_os_cond_signal(osd->cond, NULL);
 | 
			
		||||
        soundio_os_thread_destroy(osd->thread);
 | 
			
		||||
        osd->thread = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +177,7 @@ static int outstream_open_dummy(struct SoundIoPrivate *si, struct SoundIoOutStre
 | 
			
		|||
    struct SoundIoOutStream *outstream = &os->pub;
 | 
			
		||||
    struct SoundIoDevice *device = outstream->device;
 | 
			
		||||
 | 
			
		||||
    atomic_flag_test_and_set(&osd->clear_buffer_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osd->clear_buffer_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_STORE(osd->pause_requested, false);
 | 
			
		||||
 | 
			
		||||
    if (outstream->software_latency == 0.0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -216,7 +216,7 @@ static int outstream_start_dummy(struct SoundIoPrivate *si, struct SoundIoOutStr
 | 
			
		|||
    struct SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
 | 
			
		||||
    struct SoundIo *soundio = &si->pub;
 | 
			
		||||
    assert(!osd->thread);
 | 
			
		||||
    atomic_flag_test_and_set(&osd->abort_flag);
 | 
			
		||||
    SOUNDIO_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)))
 | 
			
		||||
| 
						 | 
				
			
			@ -257,7 +257,7 @@ static int outstream_end_write_dummy(struct SoundIoPrivate *si, struct SoundIoOu
 | 
			
		|||
 | 
			
		||||
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_ATOMIC_FLAG_CLEAR(osd->clear_buffer_flag);
 | 
			
		||||
    soundio_os_cond_signal(osd->cond, NULL);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -275,7 +275,7 @@ static void instream_destroy_dummy(struct SoundIoPrivate *si, struct SoundIoInSt
 | 
			
		|||
    struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
 | 
			
		||||
 | 
			
		||||
    if (isd->thread) {
 | 
			
		||||
        atomic_flag_clear(&isd->abort_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(isd->abort_flag);
 | 
			
		||||
        soundio_os_cond_signal(isd->cond, NULL);
 | 
			
		||||
        soundio_os_thread_destroy(isd->thread);
 | 
			
		||||
        isd->thread = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -331,7 +331,7 @@ static int instream_start_dummy(struct SoundIoPrivate *si, struct SoundIoInStrea
 | 
			
		|||
    struct SoundIoInStreamDummy *isd = &is->backend_data.dummy;
 | 
			
		||||
    struct SoundIo *soundio = &si->pub;
 | 
			
		||||
    assert(!isd->thread);
 | 
			
		||||
    atomic_flag_test_and_set(&isd->abort_flag);
 | 
			
		||||
    SOUNDIO_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)))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,14 +27,14 @@ struct SoundIoDeviceDummy { int make_the_struct_not_empty; };
 | 
			
		|||
struct SoundIoOutStreamDummy {
 | 
			
		||||
    struct SoundIoOsThread *thread;
 | 
			
		||||
    struct SoundIoOsCond *cond;
 | 
			
		||||
    atomic_flag abort_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag abort_flag;
 | 
			
		||||
    double period_duration;
 | 
			
		||||
    int buffer_frame_count;
 | 
			
		||||
    int frames_left;
 | 
			
		||||
    int write_frame_count;
 | 
			
		||||
    struct SoundIoRingBuffer ring_buffer;
 | 
			
		||||
    double playback_start_time;
 | 
			
		||||
    atomic_flag clear_buffer_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag clear_buffer_flag;
 | 
			
		||||
    struct SoundIoAtomicBool pause_requested;
 | 
			
		||||
    struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ struct SoundIoOutStreamDummy {
 | 
			
		|||
struct SoundIoInStreamDummy {
 | 
			
		||||
    struct SoundIoOsThread *thread;
 | 
			
		||||
    struct SoundIoOsCond *cond;
 | 
			
		||||
    atomic_flag abort_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag abort_flag;
 | 
			
		||||
    double period_duration;
 | 
			
		||||
    int frames_left;
 | 
			
		||||
    int read_frame_count;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								src/jack.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/jack.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -11,7 +11,7 @@
 | 
			
		|||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
static atomic_flag global_msg_callback_flag = ATOMIC_FLAG_INIT;
 | 
			
		||||
static struct SoundIoAtomicFlag global_msg_callback_flag = SOUNDIO_ATOMIC_FLAG_INIT;
 | 
			
		||||
 | 
			
		||||
struct SoundIoJackPort {
 | 
			
		||||
    const char *full_name;
 | 
			
		||||
| 
						 | 
				
			
			@ -315,9 +315,9 @@ static void my_flush_events(struct SoundIoPrivate *si, bool wait) {
 | 
			
		|||
    if (cb_shutdown) {
 | 
			
		||||
        soundio->on_backend_disconnect(soundio, SoundIoErrorBackendDisconnected);
 | 
			
		||||
    } else {
 | 
			
		||||
        if (!atomic_flag_test_and_set(&sij->refresh_devices_flag)) {
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(sij->refresh_devices_flag)) {
 | 
			
		||||
            if ((err = refresh_devices(si))) {
 | 
			
		||||
                atomic_flag_clear(&sij->refresh_devices_flag);
 | 
			
		||||
                SOUNDIO_ATOMIC_FLAG_CLEAR(sij->refresh_devices_flag);
 | 
			
		||||
            } else {
 | 
			
		||||
                soundio->on_devices_change(soundio);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -344,7 +344,7 @@ static void wakeup_jack(struct SoundIoPrivate *si) {
 | 
			
		|||
static void force_device_scan_jack(struct SoundIoPrivate *si) {
 | 
			
		||||
    struct SoundIo *soundio = &si->pub;
 | 
			
		||||
    struct SoundIoJack *sij = &si->backend_data.jack;
 | 
			
		||||
    atomic_flag_clear(&sij->refresh_devices_flag);
 | 
			
		||||
    SOUNDIO_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);
 | 
			
		||||
| 
						 | 
				
			
			@ -806,7 +806,7 @@ static int instream_get_latency_jack(struct SoundIoPrivate *si, struct SoundIoIn
 | 
			
		|||
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_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);
 | 
			
		||||
| 
						 | 
				
			
			@ -869,12 +869,12 @@ int soundio_jack_init(struct SoundIoPrivate *si) {
 | 
			
		|||
    struct SoundIoJack *sij = &si->backend_data.jack;
 | 
			
		||||
    struct SoundIo *soundio = &si->pub;
 | 
			
		||||
 | 
			
		||||
    if (!atomic_flag_test_and_set(&global_msg_callback_flag)) {
 | 
			
		||||
    if (!SOUNDIO_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);
 | 
			
		||||
        atomic_flag_clear(&global_msg_callback_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(global_msg_callback_flag);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sij->mutex = soundio_os_mutex_create();
 | 
			
		||||
| 
						 | 
				
			
			@ -923,7 +923,7 @@ int soundio_jack_init(struct SoundIoPrivate *si) {
 | 
			
		|||
    }
 | 
			
		||||
    jack_on_shutdown(sij->client, shutdown_callback, si);
 | 
			
		||||
 | 
			
		||||
    atomic_flag_clear(&sij->refresh_devices_flag);
 | 
			
		||||
    SOUNDIO_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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ struct SoundIoJack {
 | 
			
		|||
    jack_client_t *client;
 | 
			
		||||
    struct SoundIoOsMutex *mutex;
 | 
			
		||||
    struct SoundIoOsCond *cond;
 | 
			
		||||
    atomic_flag refresh_devices_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag refresh_devices_flag;
 | 
			
		||||
    int sample_rate;
 | 
			
		||||
    int period_size;
 | 
			
		||||
    bool is_shutdown;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										40
									
								
								src/list.h
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								src/list.h
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -25,28 +25,28 @@
 | 
			
		|||
 | 
			
		||||
#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 int SOUNDIO_ATTR_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 int SOUNDIO_ATTR_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 int SOUNDIO_ATTR_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)) \
 | 
			
		||||
    static_kw int SOUNDIO_ATTR_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)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    static_kw void Name##_deinit(struct Name *s) { \
 | 
			
		||||
        free(s->items); \
 | 
			
		||||
    } \
 | 
			
		||||
\
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    __attribute__ ((warn_unused_result)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    SOUNDIO_ATTR_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) \
 | 
			
		||||
| 
						 | 
				
			
			@ -61,8 +61,8 @@
 | 
			
		|||
        return 0; \
 | 
			
		||||
    } \
 | 
			
		||||
\
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    __attribute__ ((warn_unused_result)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    SOUNDIO_ATTR_WARN_UNUSED_RESULT \
 | 
			
		||||
    static_kw int Name##_append(struct Name *s, Type item) { \
 | 
			
		||||
        int err = Name##_ensure_capacity(s, s->length + 1); \
 | 
			
		||||
        if (err) \
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +72,7 @@
 | 
			
		|||
        return 0; \
 | 
			
		||||
    } \
 | 
			
		||||
\
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    static_kw Type Name##_val_at(struct Name *s, int index) {                                            \
 | 
			
		||||
        assert(index >= 0);                                                              \
 | 
			
		||||
        assert(index < s->length);                                                          \
 | 
			
		||||
| 
						 | 
				
			
			@ -82,22 +82,22 @@
 | 
			
		|||
    /* remember that the pointer to this item is invalid after you \
 | 
			
		||||
     * modify the length of the list \
 | 
			
		||||
     */ \
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    SOUNDIO_ATTR_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)) \
 | 
			
		||||
    SOUNDIO_ATTR_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)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    SOUNDIO_ATTR_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);                                           \
 | 
			
		||||
| 
						 | 
				
			
			@ -107,30 +107,30 @@
 | 
			
		|||
        return 0;                                                                        \
 | 
			
		||||
    }                                                                                    \
 | 
			
		||||
\
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    __attribute__ ((warn_unused_result)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    SOUNDIO_ATTR_WARN_UNUSED_RESULT \
 | 
			
		||||
    static_kw int Name##_add_one(struct Name *s) { \
 | 
			
		||||
        return Name##_resize(s, s->length + 1); \
 | 
			
		||||
    } \
 | 
			
		||||
\
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    static_kw Type Name##_last_val(struct Name *s) {                                                   \
 | 
			
		||||
        assert(s->length >= 1);                                                             \
 | 
			
		||||
        return s->items[s->length - 1];                                                        \
 | 
			
		||||
    }                                                                                    \
 | 
			
		||||
\
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    static_kw Type *Name##_last_ptr(struct Name *s) {                                                  \
 | 
			
		||||
        assert(s->length >= 1);                                                             \
 | 
			
		||||
        return &s->items[s->length - 1];                                                       \
 | 
			
		||||
    }                                                                                    \
 | 
			
		||||
\
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    static_kw void Name##_clear(struct Name *s) {                                                      \
 | 
			
		||||
        s->length = 0;                                                                      \
 | 
			
		||||
    }                                                                                    \
 | 
			
		||||
\
 | 
			
		||||
    __attribute__ ((unused)) \
 | 
			
		||||
    SOUNDIO_ATTR_UNUSED \
 | 
			
		||||
    static_kw Type Name##_swap_remove(struct Name *s, int index) { \
 | 
			
		||||
        assert(index >= 0); \
 | 
			
		||||
        assert(index < s->length); \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -667,7 +667,7 @@ static int outstream_open_pa(struct SoundIoPrivate *si, struct SoundIoOutStreamP
 | 
			
		|||
 | 
			
		||||
    struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
 | 
			
		||||
    SOUNDIO_ATOMIC_STORE(ospa->stream_ready, false);
 | 
			
		||||
    atomic_flag_test_and_set(&ospa->clear_buffer_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(ospa->clear_buffer_flag);
 | 
			
		||||
 | 
			
		||||
    assert(sipa->pulse_context);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -783,7 +783,7 @@ static int outstream_end_write_pa(struct SoundIoPrivate *si, struct SoundIoOutSt
 | 
			
		|||
    struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
 | 
			
		||||
    pa_stream *stream = ospa->stream;
 | 
			
		||||
 | 
			
		||||
    pa_seek_mode_t seek_mode = atomic_flag_test_and_set(&ospa->clear_buffer_flag) ? PA_SEEK_RELATIVE : PA_SEEK_RELATIVE_ON_READ;
 | 
			
		||||
    pa_seek_mode_t seek_mode = SOUNDIO_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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -794,7 +794,7 @@ static int outstream_clear_buffer_pa(struct SoundIoPrivate *si,
 | 
			
		|||
        struct SoundIoOutStreamPrivate *os)
 | 
			
		||||
{
 | 
			
		||||
    struct SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
 | 
			
		||||
    atomic_flag_clear(&ospa->clear_buffer_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_CLEAR(ospa->clear_buffer_flag);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ struct SoundIoOutStreamPulseAudio {
 | 
			
		|||
    pa_buffer_attr buffer_attr;
 | 
			
		||||
    char *write_ptr;
 | 
			
		||||
    size_t write_byte_count;
 | 
			
		||||
    atomic_flag clear_buffer_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag clear_buffer_flag;
 | 
			
		||||
    struct SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,36 +33,42 @@ static const enum SoundIoBackend available_backends[] = {
 | 
			
		|||
    SoundIoBackendDummy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int (*backend_init_fns[])(struct SoundIoPrivate *) = {
 | 
			
		||||
    [SoundIoBackendNone] = NULL,
 | 
			
		||||
#ifdef SOUNDIO_HAVE_JACK
 | 
			
		||||
    [SoundIoBackendJack] = soundio_jack_init,
 | 
			
		||||
#else
 | 
			
		||||
    [SoundIoBackendJack] = NULL,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SOUNDIO_HAVE_PULSEAUDIO
 | 
			
		||||
    [SoundIoBackendPulseAudio] = soundio_pulseaudio_init,
 | 
			
		||||
#else
 | 
			
		||||
    [SoundIoBackendPulseAudio] = NULL,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SOUNDIO_HAVE_ALSA
 | 
			
		||||
    [SoundIoBackendAlsa] = soundio_alsa_init,
 | 
			
		||||
#else
 | 
			
		||||
    [SoundIoBackendAlsa] = NULL,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SOUNDIO_HAVE_COREAUDIO
 | 
			
		||||
    [SoundIoBackendCoreAudio] = soundio_coreaudio_init,
 | 
			
		||||
#else
 | 
			
		||||
    [SoundIoBackendCoreAudio] = NULL,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SOUNDIO_HAVE_WASAPI
 | 
			
		||||
    [SoundIoBackendWasapi] = soundio_wasapi_init,
 | 
			
		||||
#else
 | 
			
		||||
    [SoundIoBackendWasapi] = NULL,
 | 
			
		||||
#endif
 | 
			
		||||
    [SoundIoBackendDummy] = soundio_dummy_init,
 | 
			
		||||
};
 | 
			
		||||
typedef int (*backend_init_t)(struct SoundIoPrivate *);
 | 
			
		||||
static backend_init_t backend_init_fns[] = {
 | 
			
		||||
    NULL, // None backend
 | 
			
		||||
 | 
			
		||||
#ifdef SOUNDIO_HAVE_JACK
 | 
			
		||||
    &soundio_jack_init,
 | 
			
		||||
#else
 | 
			
		||||
    NULL,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SOUNDIO_HAVE_PULSEAUDIO
 | 
			
		||||
    &soundio_pulseaudio_init,
 | 
			
		||||
#else
 | 
			
		||||
    NULL,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SOUNDIO_HAVE_ALSA
 | 
			
		||||
    &soundio_alsa_init,
 | 
			
		||||
#else
 | 
			
		||||
    NULL,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SOUNDIO_HAVE_COREAUDIO
 | 
			
		||||
    &soundio_coreaudio_init,
 | 
			
		||||
#else
 | 
			
		||||
    NULL,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SOUNDIO_HAVE_WASAPI
 | 
			
		||||
    soundio_wasapi_init,
 | 
			
		||||
#else
 | 
			
		||||
    NULL,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    &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)
 | 
			
		||||
| 
						 | 
				
			
			@ -171,9 +177,9 @@ 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 struct SoundIoAtomicFlag rtprio_seen = SOUNDIO_ATOMIC_FLAG_INIT;
 | 
			
		||||
static void default_emit_rtprio_warning(void) {
 | 
			
		||||
    if (!atomic_flag_test_and_set(&rtprio_seen)) {
 | 
			
		||||
    if (!SOUNDIO_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");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										30
									
								
								src/util.h
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/util.h
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -13,14 +13,29 @@
 | 
			
		|||
#include <assert.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#define ALLOCATE_NONZERO(Type, count) malloc((count) * sizeof(Type))
 | 
			
		||||
#define ALLOCATE_NONZERO(Type, count) ((Type*)malloc((count) * sizeof(Type)))
 | 
			
		||||
 | 
			
		||||
#define ALLOCATE(Type, count) calloc(count, sizeof(Type))
 | 
			
		||||
#define ALLOCATE(Type, count) ((Type*)calloc(count, sizeof(Type)))
 | 
			
		||||
 | 
			
		||||
#define REALLOCATE_NONZERO(Type, old, new_count) realloc(old, (new_count) * sizeof(Type))
 | 
			
		||||
#define REALLOCATE_NONZERO(Type, old, new_count) ((Type*)realloc(old, (new_count) * sizeof(Type)))
 | 
			
		||||
 | 
			
		||||
#define ARRAY_LENGTH(array) (sizeof(array)/sizeof((array)[0]))
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
#define SOUNDIO_ATTR_COLD
 | 
			
		||||
#define SOUNDIO_ATTR_NORETURN __declspec(noreturn)
 | 
			
		||||
#define SOUNDIO_ATTR_FORMAT(...)
 | 
			
		||||
#define SOUNDIO_ATTR_UNUSED __pragma(warning(suppress:4100))
 | 
			
		||||
#define SOUNDIO_ATTR_WARN_UNUSED_RESULT _Check_return_
 | 
			
		||||
#else
 | 
			
		||||
#define SOUNDIO_ATTR_COLD __attribute__((cold))
 | 
			
		||||
#define SOUNDIO_ATTR_NORETURN __attribute__((noreturn))
 | 
			
		||||
#define SOUNDIO_ATTR_FORMAT(...) __attribute__((format(__VA_ARGS__)))
 | 
			
		||||
#define SOUNDIO_ATTR_UNUSED __attribute__((unused))
 | 
			
		||||
#define SOUNDIO_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline int soundio_int_min(int a, int b) {
 | 
			
		||||
    return (a <= b) ? a : b;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -45,13 +60,14 @@ static inline double soundio_double_clamp(double min_value, double value, double
 | 
			
		|||
    return soundio_double_max(soundio_double_min(value, max_value), min_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SOUNDIO_ATTR_NORETURN
 | 
			
		||||
void soundio_panic(const char *format, ...)
 | 
			
		||||
    __attribute__((cold))
 | 
			
		||||
    __attribute__ ((noreturn))
 | 
			
		||||
    __attribute__ ((format (printf, 1, 2)));
 | 
			
		||||
    SOUNDIO_ATTR_COLD
 | 
			
		||||
    SOUNDIO_ATTR_FORMAT(printf, 1, 2)
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
char *soundio_alloc_sprintf(int *len, const char *format, ...)
 | 
			
		||||
    __attribute__ ((format (printf, 2, 3)));
 | 
			
		||||
    SOUNDIO_ATTR_FORMAT(printf, 2, 3);
 | 
			
		||||
 | 
			
		||||
static inline char *soundio_str_dupe(const char *str, int str_len) {
 | 
			
		||||
    char *out = ALLOCATE_NONZERO(char, str_len + 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										167
									
								
								src/wasapi.c
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								src/wasapi.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -5,11 +5,94 @@
 | 
			
		|||
 * See http://opensource.org/licenses/MIT
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define INITGUID
 | 
			
		||||
#define CINTERFACE
 | 
			
		||||
#define COBJMACROS
 | 
			
		||||
#define CONST_VTABLE
 | 
			
		||||
#include <initguid.h>
 | 
			
		||||
#include <audioclient.h>
 | 
			
		||||
#include <endpointvolume.h>
 | 
			
		||||
#include <mmdeviceapi.h>
 | 
			
		||||
#include <mmreg.h>
 | 
			
		||||
#include <functiondiscoverykeys_devpkey.h>
 | 
			
		||||
 | 
			
		||||
#include "wasapi.h"
 | 
			
		||||
#include "soundio_private.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
// In C++ mode, IsEqualGUID() takes its arguments by reference
 | 
			
		||||
#define IS_EQUAL_GUID(a, b) IsEqualGUID(*(a), *(b))
 | 
			
		||||
#define IS_EQUAL_IID(a, b) IsEqualIID((a), *(b))
 | 
			
		||||
 | 
			
		||||
// And some constants are passed by reference
 | 
			
		||||
#define IID_IAUDIOCLIENT                      (IID_IAudioClient)
 | 
			
		||||
#define IID_IMMENDPOINT                       (IID_IMMEndpoint)
 | 
			
		||||
#define IID_IAUDIOCLOCKADJUSTMENT             (IID_IAudioClockAdjustment)
 | 
			
		||||
#define IID_IAUDIOSESSIONCONTROL              (IID_IAudioSessionControl)
 | 
			
		||||
#define IID_IAUDIORENDERCLIENT                (IID_IAudioRenderClient)
 | 
			
		||||
#define IID_IMMDEVICEENUMERATOR               (IID_IMMDeviceEnumerator)
 | 
			
		||||
#define IID_IAUDIOCAPTURECLIENT               (IID_IAudioCaptureClient)
 | 
			
		||||
#define CLSID_MMDEVICEENUMERATOR              (CLSID_MMDeviceEnumerator)
 | 
			
		||||
#define PKEY_DEVICE_FRIENDLYNAME              (PKEY_Device_FriendlyName)
 | 
			
		||||
#define PKEY_AUDIOENGINE_DEVICEFORMAT         (PKEY_AudioEngine_DeviceFormat)
 | 
			
		||||
 | 
			
		||||
// And some GUID are never implemented (Ignoring the INITGUID define)
 | 
			
		||||
static const CLSID CLSID_MMDeviceEnumerator  = __uuidof(MMDeviceEnumerator);
 | 
			
		||||
static const IID   IID_IMMDeviceEnumerator   = {
 | 
			
		||||
    //MIDL_INTERFACE("A95664D2-9614-4F35-A746-DE8DB63617E6")
 | 
			
		||||
    0xa95664d2, 0x9614, 0x4f35, {0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6}
 | 
			
		||||
};
 | 
			
		||||
static const IID   IID_IMMNotificationClient = {
 | 
			
		||||
    //MIDL_INTERFACE("7991EEC9-7E89-4D85-8390-6C703CEC60C0")
 | 
			
		||||
    0x7991eec9, 0x7e89, 0x4d85, {0x83, 0x90, 0x6c, 0x70, 0x3c, 0xec, 0x60, 0xc0}
 | 
			
		||||
};
 | 
			
		||||
static const IID   IID_IAudioClient = {
 | 
			
		||||
    //MIDL_INTERFACE("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2")
 | 
			
		||||
    0x1cb9ad4c, 0xdbfa, 0x4c32, {0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2}
 | 
			
		||||
};
 | 
			
		||||
static const IID   IID_IAudioRenderClient    = {
 | 
			
		||||
    //MIDL_INTERFACE("F294ACFC-3146-4483-A7BF-ADDCA7C260E2")
 | 
			
		||||
    0xf294acfc, 0x3146, 0x4483, {0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2}
 | 
			
		||||
};
 | 
			
		||||
static const IID   IID_IAudioSessionControl  = {
 | 
			
		||||
    //MIDL_INTERFACE("F4B1A599-7266-4319-A8CA-E70ACB11E8CD")
 | 
			
		||||
    0xf4b1a599, 0x7266, 0x4319, {0xa8, 0xca, 0xe7, 0x0a, 0xcb, 0x11, 0xe8, 0xcd}
 | 
			
		||||
};
 | 
			
		||||
static const IID   IID_IAudioSessionEvents   = {
 | 
			
		||||
    //MIDL_INTERFACE("24918ACC-64B3-37C1-8CA9-74A66E9957A8")
 | 
			
		||||
    0x24918acc, 0x64b3, 0x37c1, {0x8c, 0xa9, 0x74, 0xa6, 0x6e, 0x99, 0x57, 0xa8}
 | 
			
		||||
};
 | 
			
		||||
static const IID IID_IMMEndpoint = {
 | 
			
		||||
    //MIDL_INTERFACE("1BE09788-6894-4089-8586-9A2A6C265AC5")
 | 
			
		||||
    0x1be09788, 0x6894, 0x4089, {0x85, 0x86, 0x9a, 0x2a, 0x6c, 0x26, 0x5a, 0xc5}
 | 
			
		||||
};
 | 
			
		||||
static const IID IID_IAudioClockAdjustment = {
 | 
			
		||||
    //MIDL_INTERFACE("f6e4c0a0-46d9-4fb8-be21-57a3ef2b626c")
 | 
			
		||||
    0xf6e4c0a0, 0x46d9, 0x4fb8, {0xbe, 0x21, 0x57, 0xa3, 0xef, 0x2b, 0x62, 0x6c}
 | 
			
		||||
};
 | 
			
		||||
static const IID IID_IAudioCaptureClient = {
 | 
			
		||||
    //MIDL_INTERFACE("C8ADBD64-E71E-48a0-A4DE-185C395CD317")
 | 
			
		||||
    0xc8adbd64, 0xe71e, 0x48a0, {0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#define IS_EQUAL_GUID(a, b) IsEqualGUID((a), (b))
 | 
			
		||||
#define IS_EQUAL_IID(a, b) IsEqualIID((a), (b))
 | 
			
		||||
 | 
			
		||||
#define IID_IAUDIOCLIENT (&IID_IAudioClient)
 | 
			
		||||
#define IID_IMMENDPOINT (&IID_IMMEndpoint)
 | 
			
		||||
#define PKEY_DEVICE_FRIENDLYNAME (&PKEY_Device_FriendlyName)
 | 
			
		||||
#define PKEY_AUDIOENGINE_DEVICEFORMAT (&PKEY_AudioEngine_DeviceFormat)
 | 
			
		||||
#define CLSID_MMDEVICEENUMERATOR (&CLSID_MMDeviceEnumerator)
 | 
			
		||||
#define IID_IAUDIOCLOCKADJUSTMENT (&IID_IAudioClockAdjustment)
 | 
			
		||||
#define IID_IAUDIOSESSIONCONTROL (&IID_IAudioSessionControl)
 | 
			
		||||
#define IID_IAUDIORENDERCLIENT (&IID_IAudioRenderClient)
 | 
			
		||||
#define IID_IMMDEVICEENUMERATOR (&IID_IMMDeviceEnumerator)
 | 
			
		||||
#define IID_IAUDIOCAPTURECLIENT (&IID_IAudioCaptureClient)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Attempting to use the Windows-supplied versions of these constants resulted
 | 
			
		||||
// in `undefined reference` linker errors.
 | 
			
		||||
const static GUID SOUNDIO_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {
 | 
			
		||||
| 
						 | 
				
			
			@ -204,8 +287,8 @@ static void from_wave_format_layout(WAVEFORMATEXTENSIBLE *wave_format, struct So
 | 
			
		|||
 | 
			
		||||
static enum SoundIoFormat from_wave_format_format(WAVEFORMATEXTENSIBLE *wave_format) {
 | 
			
		||||
    assert(wave_format->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE);
 | 
			
		||||
    bool is_pcm = IsEqualGUID(&wave_format->SubFormat, &SOUNDIO_KSDATAFORMAT_SUBTYPE_PCM);
 | 
			
		||||
    bool is_float = IsEqualGUID(&wave_format->SubFormat, &SOUNDIO_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
 | 
			
		||||
    bool is_pcm = IS_EQUAL_GUID(&wave_format->SubFormat, &SOUNDIO_KSDATAFORMAT_SUBTYPE_PCM);
 | 
			
		||||
    bool is_float = IS_EQUAL_GUID(&wave_format->SubFormat, &SOUNDIO_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
 | 
			
		||||
 | 
			
		||||
    if (wave_format->Samples.wValidBitsPerSample == wave_format->Format.wBitsPerSample) {
 | 
			
		||||
        if (wave_format->Format.wBitsPerSample == 8) {
 | 
			
		||||
| 
						 | 
				
			
			@ -352,7 +435,7 @@ static double from_reference_time(REFERENCE_TIME rt) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static REFERENCE_TIME to_reference_time(double seconds) {
 | 
			
		||||
    return seconds * 10000000.0 + 0.5;
 | 
			
		||||
    return (REFERENCE_TIME)(seconds * 10000000.0 + 0.5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void destruct_device(struct SoundIoDevicePrivate *dev) {
 | 
			
		||||
| 
						 | 
				
			
			@ -707,7 +790,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
 | 
			
		|||
            IUnknown_Release(rd.audio_client);
 | 
			
		||||
            rd.audio_client = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        if (FAILED(hr = IMMDevice_Activate(rd.mm_device, &IID_IAudioClient,
 | 
			
		||||
        if (FAILED(hr = IMMDevice_Activate(rd.mm_device, IID_IAUDIOCLIENT,
 | 
			
		||||
                        CLSCTX_ALL, NULL, (void**)&rd.audio_client)))
 | 
			
		||||
        {
 | 
			
		||||
            deinit_refresh_devices(&rd);
 | 
			
		||||
| 
						 | 
				
			
			@ -733,7 +816,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
 | 
			
		|||
            IMMEndpoint_Release(rd.endpoint);
 | 
			
		||||
            rd.endpoint = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        if (FAILED(hr = IMMDevice_QueryInterface(rd.mm_device, &IID_IMMEndpoint, (void**)&rd.endpoint))) {
 | 
			
		||||
        if (FAILED(hr = IMMDevice_QueryInterface(rd.mm_device, IID_IMMENDPOINT, (void**)&rd.endpoint))) {
 | 
			
		||||
            deinit_refresh_devices(&rd);
 | 
			
		||||
            return SoundIoErrorOpeningDevice;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -763,7 +846,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
 | 
			
		|||
        PropVariantInit(&rd.prop_variant_value);
 | 
			
		||||
        rd.prop_variant_value_inited = true;
 | 
			
		||||
        if (FAILED(hr = IPropertyStore_GetValue(rd.prop_store,
 | 
			
		||||
                        &PKEY_Device_FriendlyName, &rd.prop_variant_value)))
 | 
			
		||||
                        PKEY_DEVICE_FRIENDLYNAME, &rd.prop_variant_value)))
 | 
			
		||||
        {
 | 
			
		||||
            deinit_refresh_devices(&rd);
 | 
			
		||||
            return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -793,7 +876,7 @@ static int refresh_devices(struct SoundIoPrivate *si) {
 | 
			
		|||
        }
 | 
			
		||||
        PropVariantInit(&rd.prop_variant_value);
 | 
			
		||||
        rd.prop_variant_value_inited = true;
 | 
			
		||||
        if (FAILED(hr = IPropertyStore_GetValue(rd.prop_store, &PKEY_AudioEngine_DeviceFormat,
 | 
			
		||||
        if (FAILED(hr = IPropertyStore_GetValue(rd.prop_store, PKEY_AUDIOENGINE_DEVICEFORMAT,
 | 
			
		||||
                        &rd.prop_variant_value)))
 | 
			
		||||
        {
 | 
			
		||||
            deinit_refresh_devices(&rd);
 | 
			
		||||
| 
						 | 
				
			
			@ -839,9 +922,9 @@ static int refresh_devices(struct SoundIoPrivate *si) {
 | 
			
		|||
            // Let's pick some reasonable min and max values.
 | 
			
		||||
            rd.device_shared->sample_rate_count = 1;
 | 
			
		||||
            rd.device_shared->sample_rates = &dev_shared->prealloc_sample_rate_range;
 | 
			
		||||
            rd.device_shared->sample_rates[0].min = min(SOUNDIO_MIN_SAMPLE_RATE,
 | 
			
		||||
            rd.device_shared->sample_rates[0].min = soundio_int_min(SOUNDIO_MIN_SAMPLE_RATE,
 | 
			
		||||
                    rd.device_shared->sample_rate_current);
 | 
			
		||||
            rd.device_shared->sample_rates[0].max = max(SOUNDIO_MAX_SAMPLE_RATE,
 | 
			
		||||
            rd.device_shared->sample_rates[0].max = soundio_int_max(SOUNDIO_MAX_SAMPLE_RATE,
 | 
			
		||||
                    rd.device_shared->sample_rate_current);
 | 
			
		||||
        } else {
 | 
			
		||||
            // Shared mode input stream: mix format is all we can do.
 | 
			
		||||
| 
						 | 
				
			
			@ -935,8 +1018,8 @@ static void device_thread_run(void *arg) {
 | 
			
		|||
    struct SoundIoWasapi *siw = &si->backend_data.wasapi;
 | 
			
		||||
    int err;
 | 
			
		||||
 | 
			
		||||
    HRESULT hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
 | 
			
		||||
            CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void**)&siw->device_enumerator);
 | 
			
		||||
    HRESULT hr = CoCreateInstance(CLSID_MMDEVICEENUMERATOR, NULL,
 | 
			
		||||
            CLSCTX_ALL, IID_IMMDEVICEENUMERATOR, (void**)&siw->device_enumerator);
 | 
			
		||||
    if (FAILED(hr)) {
 | 
			
		||||
        shutdown_backend(si, SoundIoErrorSystemResources);
 | 
			
		||||
        return;
 | 
			
		||||
| 
						 | 
				
			
			@ -1048,7 +1131,7 @@ static void outstream_destroy_wasapi(struct SoundIoPrivate *si, struct SoundIoOu
 | 
			
		|||
    struct SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
 | 
			
		||||
 | 
			
		||||
    if (osw->thread) {
 | 
			
		||||
        atomic_flag_clear(&osw->thread_exit_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(osw->thread_exit_flag);
 | 
			
		||||
        if (osw->h_event)
 | 
			
		||||
            SetEvent(osw->h_event);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1088,7 +1171,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
 | 
			
		|||
    struct SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi;
 | 
			
		||||
    HRESULT hr;
 | 
			
		||||
 | 
			
		||||
    if (FAILED(hr = IMMDevice_Activate(dw->mm_device, &IID_IAudioClient,
 | 
			
		||||
    if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAUDIOCLIENT,
 | 
			
		||||
                    CLSCTX_ALL, NULL, (void**)&osw->audio_client)))
 | 
			
		||||
    {
 | 
			
		||||
        return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1135,7 +1218,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
 | 
			
		|||
            }
 | 
			
		||||
            IUnknown_Release(osw->audio_client);
 | 
			
		||||
            osw->audio_client = NULL;
 | 
			
		||||
            if (FAILED(hr = IMMDevice_Activate(dw->mm_device, &IID_IAudioClient,
 | 
			
		||||
            if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAUDIOCLIENT,
 | 
			
		||||
                            CLSCTX_ALL, NULL, (void**)&osw->audio_client)))
 | 
			
		||||
            {
 | 
			
		||||
                return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1195,7 +1278,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
 | 
			
		|||
            return SoundIoErrorOpeningDevice;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (osw->need_resample) {
 | 
			
		||||
        if (FAILED(hr = IAudioClient_GetService(osw->audio_client, &IID_IAudioClockAdjustment,
 | 
			
		||||
        if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_IAUDIOCLOCKADJUSTMENT,
 | 
			
		||||
                        (void**)&osw->audio_clock_adjustment)))
 | 
			
		||||
        {
 | 
			
		||||
            return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1208,7 +1291,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if (outstream->name) {
 | 
			
		||||
        if (FAILED(hr = IAudioClient_GetService(osw->audio_client, &IID_IAudioSessionControl,
 | 
			
		||||
        if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_IAUDIOSESSIONCONTROL,
 | 
			
		||||
                        (void **)&osw->audio_session_control)))
 | 
			
		||||
        {
 | 
			
		||||
            return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1225,7 +1308,7 @@ static int outstream_do_open(struct SoundIoPrivate *si, struct SoundIoOutStreamP
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (FAILED(hr = IAudioClient_GetService(osw->audio_client, &IID_IAudioRenderClient,
 | 
			
		||||
    if (FAILED(hr = IAudioClient_GetService(osw->audio_client, IID_IAUDIORENDERCLIENT,
 | 
			
		||||
                    (void **)&osw->audio_render_client)))
 | 
			
		||||
    {
 | 
			
		||||
        return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1250,7 +1333,7 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
 | 
			
		|||
        outstream->error_callback(outstream, SoundIoErrorStreaming);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    int frame_count_min = max(0, (int)osw->min_padding_frames - (int)frames_used);
 | 
			
		||||
    int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
 | 
			
		||||
    outstream->write_callback(outstream, frame_count_min, osw->writable_frame_count);
 | 
			
		||||
 | 
			
		||||
    if (FAILED(hr = IAudioClient_Start(osw->audio_client))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1268,13 +1351,13 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
 | 
			
		|||
        double wait_time = time_until_underrun / 2.0;
 | 
			
		||||
        soundio_os_mutex_lock(osw->mutex);
 | 
			
		||||
        soundio_os_cond_timed_wait(osw->cond, osw->mutex, wait_time);
 | 
			
		||||
        if (!atomic_flag_test_and_set(&osw->thread_exit_flag)) {
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag)) {
 | 
			
		||||
            soundio_os_mutex_unlock(osw->mutex);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        soundio_os_mutex_unlock(osw->mutex);
 | 
			
		||||
        bool reset_buffer = false;
 | 
			
		||||
        if (!atomic_flag_test_and_set(&osw->clear_buffer_flag)) {
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->clear_buffer_flag)) {
 | 
			
		||||
            if (!osw->is_paused) {
 | 
			
		||||
                if (FAILED(hr = IAudioClient_Stop(osw->audio_client))) {
 | 
			
		||||
                    outstream->error_callback(outstream, SoundIoErrorStreaming);
 | 
			
		||||
| 
						 | 
				
			
			@ -1286,10 +1369,10 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
 | 
			
		|||
                outstream->error_callback(outstream, SoundIoErrorStreaming);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            atomic_flag_clear(&osw->pause_resume_flag);
 | 
			
		||||
            SOUNDIO_ATOMIC_FLAG_CLEAR(osw->pause_resume_flag);
 | 
			
		||||
            reset_buffer = true;
 | 
			
		||||
        }
 | 
			
		||||
        if (!atomic_flag_test_and_set(&osw->pause_resume_flag)) {
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->pause_resume_flag)) {
 | 
			
		||||
            bool pause = SOUNDIO_ATOMIC_LOAD(osw->desired_pause_state);
 | 
			
		||||
            if (pause && !osw->is_paused) {
 | 
			
		||||
                if (FAILED(hr = IAudioClient_Stop(osw->audio_client))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1314,7 +1397,7 @@ static void outstream_shared_run(struct SoundIoOutStreamPrivate *os) {
 | 
			
		|||
        if (osw->writable_frame_count > 0) {
 | 
			
		||||
            if (frames_used == 0 && !reset_buffer)
 | 
			
		||||
                outstream->underflow_callback(outstream);
 | 
			
		||||
            int frame_count_min = max(0, (int)osw->min_padding_frames - (int)frames_used);
 | 
			
		||||
            int frame_count_min = soundio_int_max(0, (int)osw->min_padding_frames - (int)frames_used);
 | 
			
		||||
            outstream->write_callback(outstream, frame_count_min, osw->writable_frame_count);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1335,9 +1418,9 @@ static void outstream_raw_run(struct SoundIoOutStreamPrivate *os) {
 | 
			
		|||
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        WaitForSingleObject(osw->h_event, INFINITE);
 | 
			
		||||
        if (!atomic_flag_test_and_set(&osw->thread_exit_flag))
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag))
 | 
			
		||||
            return;
 | 
			
		||||
        if (!atomic_flag_test_and_set(&osw->pause_resume_flag)) {
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->pause_resume_flag)) {
 | 
			
		||||
            bool pause = SOUNDIO_ATOMIC_LOAD(osw->desired_pause_state);
 | 
			
		||||
            if (pause && !osw->is_paused) {
 | 
			
		||||
                if (FAILED(hr = IAudioClient_Stop(osw->audio_client))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1382,7 +1465,7 @@ static void outstream_thread_run(void *arg) {
 | 
			
		|||
    osw->open_complete = true;
 | 
			
		||||
    soundio_os_cond_signal(osw->cond, osw->mutex);
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        if (!atomic_flag_test_and_set(&osw->thread_exit_flag)) {
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag)) {
 | 
			
		||||
            soundio_os_mutex_unlock(osw->mutex);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1407,8 +1490,8 @@ static int outstream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStr
 | 
			
		|||
    struct SoundIoDevice *device = outstream->device;
 | 
			
		||||
    struct SoundIo *soundio = &si->pub;
 | 
			
		||||
 | 
			
		||||
    atomic_flag_test_and_set(&osw->pause_resume_flag);
 | 
			
		||||
    atomic_flag_test_and_set(&osw->clear_buffer_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->pause_resume_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->clear_buffer_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_STORE(osw->desired_pause_state, false);
 | 
			
		||||
 | 
			
		||||
    // All the COM functions are supposed to be called from the same thread. libsoundio API does not
 | 
			
		||||
| 
						 | 
				
			
			@ -1443,7 +1526,7 @@ static int outstream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoOutStr
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    atomic_flag_test_and_set(&osw->thread_exit_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(osw->thread_exit_flag);
 | 
			
		||||
    int err;
 | 
			
		||||
    if ((err = soundio_os_thread_create(outstream_thread_run, os,
 | 
			
		||||
                    soundio->emit_rtprio_warning, &osw->thread)))
 | 
			
		||||
| 
						 | 
				
			
			@ -1469,7 +1552,7 @@ static int outstream_pause_wasapi(struct SoundIoPrivate *si, struct SoundIoOutSt
 | 
			
		|||
    struct SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
 | 
			
		||||
 | 
			
		||||
    SOUNDIO_ATOMIC_STORE(osw->desired_pause_state, pause);
 | 
			
		||||
    atomic_flag_clear(&osw->pause_resume_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_CLEAR(osw->pause_resume_flag);
 | 
			
		||||
    if (osw->h_event) {
 | 
			
		||||
        SetEvent(osw->h_event);
 | 
			
		||||
    } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1534,7 +1617,7 @@ static int outstream_clear_buffer_wasapi(struct SoundIoPrivate *si, struct Sound
 | 
			
		|||
    if (osw->h_event) {
 | 
			
		||||
        return SoundIoErrorIncompatibleDevice;
 | 
			
		||||
    } else {
 | 
			
		||||
        atomic_flag_clear(&osw->clear_buffer_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(osw->clear_buffer_flag);
 | 
			
		||||
        soundio_os_mutex_lock(osw->mutex);
 | 
			
		||||
        soundio_os_cond_signal(osw->cond, osw->mutex);
 | 
			
		||||
        soundio_os_mutex_unlock(osw->mutex);
 | 
			
		||||
| 
						 | 
				
			
			@ -1573,7 +1656,7 @@ static void instream_destroy_wasapi(struct SoundIoPrivate *si, struct SoundIoInS
 | 
			
		|||
    struct SoundIoInStreamWasapi *isw = &is->backend_data.wasapi;
 | 
			
		||||
 | 
			
		||||
    if (isw->thread) {
 | 
			
		||||
        atomic_flag_clear(&isw->thread_exit_flag);
 | 
			
		||||
        SOUNDIO_ATOMIC_FLAG_CLEAR(isw->thread_exit_flag);
 | 
			
		||||
        if (isw->h_event)
 | 
			
		||||
            SetEvent(isw->h_event);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1609,7 +1692,7 @@ static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPri
 | 
			
		|||
    struct SoundIoDeviceWasapi *dw = &dev->backend_data.wasapi;
 | 
			
		||||
    HRESULT hr;
 | 
			
		||||
 | 
			
		||||
    if (FAILED(hr = IMMDevice_Activate(dw->mm_device, &IID_IAudioClient,
 | 
			
		||||
    if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAUDIOCLIENT,
 | 
			
		||||
                    CLSCTX_ALL, NULL, (void**)&isw->audio_client)))
 | 
			
		||||
    {
 | 
			
		||||
        return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1657,7 +1740,7 @@ static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPri
 | 
			
		|||
            }
 | 
			
		||||
            IUnknown_Release(isw->audio_client);
 | 
			
		||||
            isw->audio_client = NULL;
 | 
			
		||||
            if (FAILED(hr = IMMDevice_Activate(dw->mm_device, &IID_IAudioClient,
 | 
			
		||||
            if (FAILED(hr = IMMDevice_Activate(dw->mm_device, IID_IAUDIOCLIENT,
 | 
			
		||||
                            CLSCTX_ALL, NULL, (void**)&isw->audio_client)))
 | 
			
		||||
            {
 | 
			
		||||
                return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1711,7 +1794,7 @@ static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPri
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if (instream->name) {
 | 
			
		||||
        if (FAILED(hr = IAudioClient_GetService(isw->audio_client, &IID_IAudioSessionControl,
 | 
			
		||||
        if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAUDIOSESSIONCONTROL,
 | 
			
		||||
                        (void **)&isw->audio_session_control)))
 | 
			
		||||
        {
 | 
			
		||||
            return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1728,7 +1811,7 @@ static int instream_do_open(struct SoundIoPrivate *si, struct SoundIoInStreamPri
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (FAILED(hr = IAudioClient_GetService(isw->audio_client, &IID_IAudioCaptureClient,
 | 
			
		||||
    if (FAILED(hr = IAudioClient_GetService(isw->audio_client, IID_IAUDIOCAPTURECLIENT,
 | 
			
		||||
                    (void **)&isw->audio_capture_client)))
 | 
			
		||||
    {
 | 
			
		||||
        return SoundIoErrorOpeningDevice;
 | 
			
		||||
| 
						 | 
				
			
			@ -1750,7 +1833,7 @@ static void instream_raw_run(struct SoundIoInStreamPrivate *is) {
 | 
			
		|||
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        WaitForSingleObject(isw->h_event, INFINITE);
 | 
			
		||||
        if (!atomic_flag_test_and_set(&isw->thread_exit_flag))
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(isw->thread_exit_flag))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        instream->read_callback(instream, isw->buffer_frame_count, isw->buffer_frame_count);
 | 
			
		||||
| 
						 | 
				
			
			@ -1771,7 +1854,7 @@ static void instream_shared_run(struct SoundIoInStreamPrivate *is) {
 | 
			
		|||
    for (;;) {
 | 
			
		||||
        soundio_os_mutex_lock(isw->mutex);
 | 
			
		||||
        soundio_os_cond_timed_wait(isw->cond, isw->mutex, instream->software_latency / 2.0);
 | 
			
		||||
        if (!atomic_flag_test_and_set(&isw->thread_exit_flag)) {
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(isw->thread_exit_flag)) {
 | 
			
		||||
            soundio_os_mutex_unlock(isw->mutex);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1813,7 +1896,7 @@ static void instream_thread_run(void *arg) {
 | 
			
		|||
    isw->open_complete = true;
 | 
			
		||||
    soundio_os_cond_signal(isw->cond, isw->mutex);
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        if (!atomic_flag_test_and_set(&isw->thread_exit_flag)) {
 | 
			
		||||
        if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(isw->thread_exit_flag)) {
 | 
			
		||||
            soundio_os_mutex_unlock(isw->mutex);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1870,7 +1953,7 @@ static int instream_open_wasapi(struct SoundIoPrivate *si, struct SoundIoInStrea
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    atomic_flag_test_and_set(&isw->thread_exit_flag);
 | 
			
		||||
    SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(isw->thread_exit_flag);
 | 
			
		||||
    int err;
 | 
			
		||||
    if ((err = soundio_os_thread_create(instream_thread_run, is,
 | 
			
		||||
                    soundio->emit_rtprio_warning, &isw->thread)))
 | 
			
		||||
| 
						 | 
				
			
			@ -1938,7 +2021,7 @@ static int instream_begin_read_wasapi(struct SoundIoPrivate *si, struct SoundIoI
 | 
			
		|||
            isw->read_buf = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isw->read_frame_count = min(*frame_count, isw->read_buf_frames_left);
 | 
			
		||||
    isw->read_frame_count = soundio_int_min(*frame_count, isw->read_buf_frames_left);
 | 
			
		||||
    *frame_count = isw->read_frame_count;
 | 
			
		||||
 | 
			
		||||
    if (isw->read_buf) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2017,7 +2100,7 @@ static inline struct SoundIoPrivate *soundio_MMNotificationClient_si(IMMNotifica
 | 
			
		|||
static STDMETHODIMP soundio_MMNotificationClient_QueryInterface(IMMNotificationClient *client,
 | 
			
		||||
        REFIID riid, void **ppv)
 | 
			
		||||
{
 | 
			
		||||
    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMMNotificationClient)) {
 | 
			
		||||
    if (IS_EQUAL_IID(riid, &IID_IUnknown) || IS_EQUAL_IID(riid, &IID_IMMNotificationClient)) {
 | 
			
		||||
        *ppv = client;
 | 
			
		||||
        IUnknown_AddRef(client);
 | 
			
		||||
        return S_OK;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								src/wasapi.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/wasapi.h
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -13,14 +13,13 @@
 | 
			
		|||
#include "list.h"
 | 
			
		||||
#include "atomics.h"
 | 
			
		||||
 | 
			
		||||
#define INITGUID
 | 
			
		||||
#define CINTERFACE
 | 
			
		||||
#define COBJMACROS
 | 
			
		||||
#ifndef WIN32_LEAN_AND_MEAN
 | 
			
		||||
#define WIN32_LEAN_AND_MEAN
 | 
			
		||||
#endif
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#include <mmdeviceapi.h>
 | 
			
		||||
#include <functiondiscoverykeys_devpkey.h>
 | 
			
		||||
#include <mmreg.h>
 | 
			
		||||
#include <audioclient.h>
 | 
			
		||||
#include <audiosessiontypes.h>
 | 
			
		||||
#include <audiopolicy.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -63,15 +62,15 @@ struct SoundIoOutStreamWasapi {
 | 
			
		|||
    struct SoundIoOsMutex *mutex;
 | 
			
		||||
    struct SoundIoOsCond *cond;
 | 
			
		||||
    struct SoundIoOsCond *start_cond;
 | 
			
		||||
    atomic_flag thread_exit_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag thread_exit_flag;
 | 
			
		||||
    bool is_raw;
 | 
			
		||||
    int writable_frame_count;
 | 
			
		||||
    UINT32 buffer_frame_count;
 | 
			
		||||
    int write_frame_count;
 | 
			
		||||
    HANDLE h_event;
 | 
			
		||||
    struct SoundIoAtomicBool desired_pause_state;
 | 
			
		||||
    atomic_flag pause_resume_flag;
 | 
			
		||||
    atomic_flag clear_buffer_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag pause_resume_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag clear_buffer_flag;
 | 
			
		||||
    bool is_paused;
 | 
			
		||||
    bool open_complete;
 | 
			
		||||
    int open_err;
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +88,7 @@ struct SoundIoInStreamWasapi {
 | 
			
		|||
    struct SoundIoOsMutex *mutex;
 | 
			
		||||
    struct SoundIoOsCond *cond;
 | 
			
		||||
    struct SoundIoOsCond *start_cond;
 | 
			
		||||
    atomic_flag thread_exit_flag;
 | 
			
		||||
    struct SoundIoAtomicFlag thread_exit_flag;
 | 
			
		||||
    bool is_raw;
 | 
			
		||||
    int readable_frame_count;
 | 
			
		||||
    UINT32 buffer_frame_count;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue