Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cmake Support for MSVC builds. #281

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
cmake_minimum_required(VERSION 2.8.5)
# Copyright (c) 2023 Andrew Kelley
# This file is MIT licensed.
# See http://opensource.org/licenses/MIT

cmake_minimum_required(VERSION 3.0.0)

project(libsoundio C)
set(CMAKE_MODULE_PATH ${libsoundio_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})

Expand All @@ -23,6 +28,7 @@ set(LIBSOUNDIO_VERSION_PATCH 0)
set(LIBSOUNDIO_VERSION "${LIBSOUNDIO_VERSION_MAJOR}.${LIBSOUNDIO_VERSION_MINOR}.${LIBSOUNDIO_VERSION_PATCH}")
message("Configuring libsoundio version ${LIBSOUNDIO_VERSION}")


if(NOT SOUNDIO_STATIC_LIBNAME)
set(SOUNDIO_STATIC_LIBNAME soundio)
endif()
Expand Down Expand Up @@ -203,7 +209,6 @@ if(MSVC)
set(EXAMPLE_CFLAGS "/W4")
set(TEST_CFLAGS "${LIB_CFLAGS}")
set(TEST_LDFLAGS " ")
set(LIBM " ")
else()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror -pedantic")
set(LIB_CFLAGS "-std=c11 -fvisibility=hidden -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes -D_REENTRANT -D_POSIX_C_SOURCE=200809L -Wno-missing-braces")
Expand Down Expand Up @@ -386,3 +391,5 @@ message(
"* CoreAudio (optional) : ${STATUS_COREAUDIO}\n"
"* WASAPI (optional) : ${STATUS_WASAPI}\n"
)


4 changes: 4 additions & 0 deletions example/sio_microphone.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ static int prioritized_sample_rates[] = {
};


#ifndef _MSC_VER
__attribute__ ((cold))
__attribute__ ((noreturn))
__attribute__ ((format (printf, 1, 2)))
static void panic(const char *format, ...) {
#else
__declspec(noreturn) static void panic(const char *format, ...) {
#endif
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
Expand Down
6 changes: 6 additions & 0 deletions example/sio_record.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
#include <string.h>
#include <math.h>
#include <errno.h>

#ifndef _MSC_VER
#include <unistd.h>
#else
#include <Windows.h>
#define sleep(x) Sleep(x * 1000)
#endif

struct RecordContext {
struct SoundIoRingBuffer *ring_buffer;
Expand Down
183 changes: 173 additions & 10 deletions src/atomics.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,23 @@
#ifndef SOUNDIO_ATOMICS_H
#define SOUNDIO_ATOMICS_H

#ifdef __cplusplus
#define SOUNDIO_USE_CPP_ATOMICS
#else // ifdef __cplusplus

#ifdef _MSC_VER
#define SOUNDIO_USE_MSVC_NATIVE_C_ATOMICS
#else
#define SOUNDIO_USE_UNIX_ATOMICS
#endif // ifdef _MSC_VER

#endif // ifdef __cplusplus


// Simple wrappers around atomic values so that the compiler will catch it if
// I accidentally use operators such as +, -, += on them.

#ifdef __cplusplus
#ifdef SOUNDIO_USE_CPP_ATOMICS

#include <atomic>

Expand All @@ -35,15 +48,38 @@ struct SoundIoAtomicULong {
std::atomic<unsigned long> 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_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_LOAD_BOOL SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_BOOL SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_INT SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_INT SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_INT SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_INT SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_LONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_LONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_LONG SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_ULONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_ULONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG SOUNDIO_ATOMIC_EXCHANGE_

#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
#endif

#ifdef SOUNDIO_USE_UNIX_ATOMICS

#include <stdatomic.h>

Expand All @@ -67,14 +103,141 @@ struct SoundIoAtomicULong {
atomic_ulong 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_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

#define SOUNDIO_ATOMIC_LOAD_BOOL SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_BOOL SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_INT SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_INT SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_INT SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_INT SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_LONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_LONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_LONG SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_ULONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_ULONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG SOUNDIO_ATOMIC_EXCHANGE_

#endif

#ifdef SOUNDIO_USE_MSVC_NATIVE_C_ATOMICS
// When building for native msvc, we can leverage builtin atomics.

#ifdef _WIN64
#define SOUNDIO_MSVC_POINTER_SIZE 8
#else
#define SOUNDIO_MSVC_POINTER_SIZE 4
#endif

struct SoundIoAtomicLong {
long x;
};

struct SoundIoAtomicInt {
int x;
};

struct SoundIoAtomicBool {
char x;
};

struct SoundIoAtomicFlag {
long x;
};

struct SoundIoAtomicULong {
unsigned long x;
};

// When sticking to raw C and msvc, we rely on MSVC compiler intrinsics and are unable to
// Automatically deduce types at compile time. Must use the correct macro for the correct function.
//
// No headers needed. We use _Interlocked* family of compiler intrinsics.
// Implementation referenced from the fantastic turf library's `atomic_msvc.h`

// How the living hell is it that to this day and age. msvc does not support typeof which both clang
// and gcc support.
//
// guess this is why c11 in msvc can't implement stdatomic.h right now
#define SOUNDIO_ATOMIC_LOAD_BOOL(a) (char) *((volatile char*) &(a.x))
#define SOUNDIO_ATOMIC_STORE_BOOL(a, value) (*((volatile char*) &(a.x))) = value
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL(a, delta) _InterlockedExchangeAdd8((volatile char*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL(a, value) _InterlockedExchange8((volatile char*) (&a.x), value)

#define SOUNDIO_ATOMIC_LOAD_INT(a) (int) *((volatile int*) &(a.x))
#define SOUNDIO_ATOMIC_STORE_INT(a, value) *((volatile int*) &(a.x)) = value
#define SOUNDIO_ATOMIC_FETCH_ADD_INT(a, delta) _InterlockedExchangeAdd((volatile LONG*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_INT(a, value) _InterlockedExchange((volatile LONG*) (&a.x), value)

#define SOUNDIO_ATOMIC_LOAD_LONG(a) SoundIoMSVCLoadLong(&a)
#define SOUNDIO_ATOMIC_STORE_LONG(a, value) SoundIoMSVCStoreLong((struct SoundIoAtomicLong*) &a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG(a, delta) _InterlockedExchangeAdd64((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_LONG(a, value) _InterlockedExchange64((long*) (&a.x), delta)

#define SOUNDIO_ATOMIC_LOAD_ULONG(a) SoundIoMSVCLoadLong(&a)
#define SOUNDIO_ATOMIC_STORE_ULONG(a, value) SoundIoMSVCStoreLong((struct SoundIoAtomicULong*) &a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG(a, delta) _InterlockedExchangeAdd64((volatile long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG(a, value) _InterlockedExchange64((volatile long*) (&a.x), delta)

#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) _interlockedbittestandset(&a.x, 0)
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) _interlockedbittestandreset(&a.x, 0)
#define SOUNDIO_ATOMIC_FLAG_INIT {1}

#define SOUNDIO_ATOMIC_LOAD(a) error
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) error
#define SOUNDIO_ATOMIC_STORE(a, value) error
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) error

static long SoundIoMSVCLoadLong(struct SoundIoAtomicLong* a)
{
#if SOUNDIO_MSVC_POINTER_SIZE == 8
return ((volatile struct SoundIoAtomicLong*) a)->x;
#else

uint64_t result;
__asm {
mov esi, object;
mov ebx, eax;
mov ecx, edx;
lock cmpxchg8b [esi];
mov dword ptr result, eax;
mov dword ptr result[4], edx;
}
return result;

#endif
}

static void SoundIoMSVCStoreLong(struct SoundIoAtomicLong* a, long value)
{
#if SOUNDIO_MSVC_POINTER_SIZE == 8
((volatile struct SoundIoAtomicLong*) a)->x = value;
#else
__asm {
mov esi, object;
mov ebx, dword ptr value;
mov ecx, dword ptr value[4];
retry:
cmpxchg8b [esi];
jne retry;
}
#endif
}

#endif

#endif //SOUNDIO_ATOMICS_H

2 changes: 1 addition & 1 deletion src/channel_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ enum SoundIoChannelId soundio_parse_channel_id(const char *str, int str_len) {
const char *alias = channel_names[id][i];
if (!alias)
break;
int alias_len = strlen(alias);
int alias_len = (int) strlen(alias);
if (soundio_streql(alias, alias_len, str, str_len))
return (enum SoundIoChannelId)id;
}
Expand Down
22 changes: 11 additions & 11 deletions src/coreaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ static OSStatus on_devices_changed(AudioObjectID in_object_id, UInt32 in_number_
struct SoundIoPrivate *si = (struct SoundIoPrivate*)in_client_data;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;

SOUNDIO_ATOMIC_STORE(sica->device_scan_queued, true);
SOUNDIO_ATOMIC_STORE_BOOL(sica->device_scan_queued, true);
soundio_os_cond_signal(sica->scan_devices_cond, NULL);

return noErr;
Expand All @@ -121,7 +121,7 @@ static OSStatus on_service_restarted(AudioObjectID in_object_id, UInt32 in_numbe
struct SoundIoPrivate *si = (struct SoundIoPrivate*)in_client_data;
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;

SOUNDIO_ATOMIC_STORE(sica->service_restarted, true);
SOUNDIO_ATOMIC_STORE_BOOL(sica->service_restarted, true);
soundio_os_cond_signal(sica->scan_devices_cond, NULL);

return noErr;
Expand Down Expand Up @@ -794,7 +794,7 @@ static void shutdown_backend(struct SoundIoPrivate *si, int err) {
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
soundio_os_mutex_lock(sica->mutex);
sica->shutdown_err = err;
SOUNDIO_ATOMIC_STORE(sica->have_devices_flag, true);
SOUNDIO_ATOMIC_STORE_BOOL(sica->have_devices_flag, true);
soundio_os_mutex_unlock(sica->mutex);
soundio_os_cond_signal(sica->cond, NULL);
soundio_os_cond_signal(sica->have_devices_cond, NULL);
Expand All @@ -806,7 +806,7 @@ static void flush_events_ca(struct SoundIoPrivate *si) {
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;

// block until have devices
while (!SOUNDIO_ATOMIC_LOAD(sica->have_devices_flag))
while (!SOUNDIO_ATOMIC_LOAD_BOOL(sica->have_devices_flag))
soundio_os_cond_wait(sica->have_devices_cond, NULL);

bool change = false;
Expand Down Expand Up @@ -848,7 +848,7 @@ static void wakeup_ca(struct SoundIoPrivate *si) {

static void force_device_scan_ca(struct SoundIoPrivate *si) {
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
SOUNDIO_ATOMIC_STORE(sica->device_scan_queued, true);
SOUNDIO_ATOMIC_STORE_BOOL(sica->device_scan_queued, true);
soundio_os_cond_signal(sica->scan_devices_cond, NULL);
}

Expand All @@ -861,17 +861,17 @@ static void device_thread_run(void *arg) {
for (;;) {
if (!SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(sica->abort_flag))
break;
if (SOUNDIO_ATOMIC_LOAD(sica->service_restarted)) {
if (SOUNDIO_ATOMIC_LOAD_BOOL(sica->service_restarted)) {
shutdown_backend(si, SoundIoErrorBackendDisconnected);
return;
}
if (SOUNDIO_ATOMIC_EXCHANGE(sica->device_scan_queued, false)) {
if (SOUNDIO_ATOMIC_EXCHANGE_BOOL(sica->device_scan_queued, false)) {
err = refresh_devices(si);
if (err) {
shutdown_backend(si, err);
return;
}
if (!SOUNDIO_ATOMIC_EXCHANGE(sica->have_devices_flag, true))
if (!SOUNDIO_ATOMIC_EXCHANGE_BOOL(sica->have_devices_flag, true))
soundio_os_cond_signal(sica->have_devices_cond, NULL);
soundio_os_cond_signal(sica->cond, NULL);
soundio->on_events_signal(soundio);
Expand Down Expand Up @@ -1410,9 +1410,9 @@ int soundio_coreaudio_init(struct SoundIoPrivate *si) {
struct SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
int err;

SOUNDIO_ATOMIC_STORE(sica->have_devices_flag, false);
SOUNDIO_ATOMIC_STORE(sica->device_scan_queued, true);
SOUNDIO_ATOMIC_STORE(sica->service_restarted, false);
SOUNDIO_ATOMIC_STORE_BOOL(sica->have_devices_flag, false);
SOUNDIO_ATOMIC_STORE_BOOL(sica->device_scan_queued, true);
SOUNDIO_ATOMIC_STORE_BOOL(sica->service_restarted, false);
SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(sica->abort_flag);

sica->mutex = soundio_os_mutex_create();
Expand Down
Loading