[SCM] libsoundio/master: Imported Upstream version 1.0.2

andrewrk-guest at users.alioth.debian.org andrewrk-guest at users.alioth.debian.org
Thu Sep 24 17:07:43 UTC 2015


The following commit has been merged in the master branch:
commit 2ac53b1c3d8b68e03f3d85b91b0e9438ab962cc5
Author: Andrew Kelley <superjoe30 at gmail.com>
Date:   Thu Sep 24 09:59:28 2015 -0700

    Imported Upstream version 1.0.2

diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..ed434bd
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,38 @@
+### Version 1.0.2 (2015-09-24)
+
+ * build: fix GNUInstallDirs not working.
+ * docs: fix incorrect docs for `soundio_instream_pause`.
+ * PulseAudio: fix `soundio_outstream_pause` triggering assertion when called
+   from within `write_callback`.
+ * fix mirrored memory not working on Linux (fixes corrupted data in ring
+   buffer).
+ * os: fix crash when creating non high priority thread fails.
+ * docs: fix typos and cleanup.
+ * fix and add test for `soundio_device_nearest_sample_rate`.
+
+### Version 1.0.1 (2015-09-11)
+
+ * libsoundio no longer depends on or links against libm.
+ * ALSA: treat ALSA as unavailable when /dev/snd does not exist.
+ * ALSA: remove duplicate assert.
+ * ALSA: remove stray print statement.
+ * ALSA: pausing returns error code when state is invalid instead of reaching
+   assertion failure in pcm.c.
+ * JACK: fix infinite loop when refreshing devices.
+ * PulseAudio: better clear buffer implementation.
+ * dummy backend: fix sometimes calling `write_callback` with
+  `frame_count_max` equal to 0.
+ * os: fix some variables accidentally not declared static.
+ * macos: fix not cleaning up condition variables.
+ * macos: avoid allocation when getting time.
+ * docs: note that `read_callback` and `write_callback` must be real time safe.
+ * docs: record example demonstrates proper real time safety by not calling
+   fwrite in `read_callback`.
+ * docs: add note to record example about shutting down.
+ * docs: make microphone example latency a command line argument.
+ * build: fix build on linux with clang.
+ * build: static libs, examples, and tests are optional.
+
+### Version 1.0.0 (2015-09-03)
+
+ * Initial public release.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30f8199..a4abb7e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,6 @@
 cmake_minimum_required(VERSION 2.8.5)
+project(libsoundio C CXX)
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
 
 if(CMAKE_VERSION VERSION_LESS 3.0.0)
     set(CMAKE_INSTALL_LIBDIR "lib" CACHE PATH "library install dir (lib)")
@@ -15,12 +17,9 @@ if(NOT CMAKE_BUILD_TYPE)
       "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
 endif()
 
-project(libsoundio C CXX)
-set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
-
 set(LIBSOUNDIO_VERSION_MAJOR 1)
 set(LIBSOUNDIO_VERSION_MINOR 0)
-set(LIBSOUNDIO_VERSION_PATCH 1)
+set(LIBSOUNDIO_VERSION_PATCH 2)
 set(LIBSOUNDIO_VERSION "${LIBSOUNDIO_VERSION_MAJOR}.${LIBSOUNDIO_VERSION_MINOR}.${LIBSOUNDIO_VERSION_PATCH}")
 message("Configuring libsoundio version ${LIBSOUNDIO_VERSION}")
 
diff --git a/README.md b/README.md
index 6235cc1..6aabf99 100644
--- a/README.md
+++ b/README.md
@@ -274,8 +274,3 @@ make doc
 ```
 
 Then look at `html/index.html` in a browser.
-
-## Projects Using libsoundio
-
- * [Genesis](https://github.com/andrewrk/genesis)
- * [Groove Basin](https://github.com/andrewrk/groovebasin) (via [libgroove](https://github.com/andrewrk/libgroove))
diff --git a/soundio/soundio.h b/soundio/soundio.h
index e964636..e39af12 100644
--- a/soundio/soundio.h
+++ b/soundio/soundio.h
@@ -359,7 +359,8 @@ struct SoundIo {
     /// This callback is fired when making thread real-time priority failed. By
     /// default, it will print to stderr only the first time it is called
     /// a message instructing the user how to configure their system to allow
-    /// real-time priority threads.
+    /// real-time priority threads. This must be set to a function not NULL.
+    /// To silence the warning, assign this to a function that does nothing.
     void (*emit_rtprio_warning)(void);
 
     /// Optional: JACK info callback.
@@ -422,10 +423,10 @@ struct SoundIoDevice {
     /// whatever format is most convenient
     /// for you which is supported by the device, because when you are the only
     /// application left, the mixer might decide to switch
-    /// current_format to yours. You can learn the supported formats via formats and
-    /// SoundIoDevice::format_count. If this information is missing due to a
-    /// probe error, formats will be `NULL`. If current_format
-    /// is unavailable, it will be set to #SoundIoFormatInvalid.
+    /// current_format to yours. You can learn the supported formats via
+    /// formats and SoundIoDevice::format_count. If this information is missing
+    /// due to a probe error, formats will be `NULL`. If current_format is
+    /// unavailable, it will be set to #SoundIoFormatInvalid.
     /// Devices are guaranteed to have at least 1 format available.
     enum SoundIoFormat current_format;
 
@@ -489,14 +490,16 @@ struct SoundIoOutStream {
     /// Populated automatically when you call ::soundio_outstream_create.
     struct SoundIoDevice *device;
 
-    /// Defaults to #SoundIoFormatFloat32NE, followed by the first one supported.
+    /// Defaults to #SoundIoFormatFloat32NE, followed by the first one
+    /// supported.
     enum SoundIoFormat format;
 
     /// Sample rate is the number of frames per second.
     /// Defaults to 48000 (and then clamped into range).
     int sample_rate;
 
-    /// Defaults to Stereo, if available, followed by the first layout supported.
+    /// Defaults to Stereo, if available, followed by the first layout
+    /// supported.
     struct SoundIoChannelLayout layout;
 
     /// Ignoring hardware latency, this is the number of seconds it takes for
@@ -546,9 +549,9 @@ struct SoundIoOutStream {
     /// pthread_join, pthread_cond_wait, etc.
     void (*write_callback)(struct SoundIoOutStream *,
             int frame_count_min, int frame_count_max);
-    /// This optional callback happens when the sound device runs out of buffered
-    /// audio data to play. After this occurs, the outstream waits until the
-    /// buffer is full to resume playback.
+    /// This optional callback happens when the sound device runs out of
+    /// buffered audio data to play. After this occurs, the outstream waits
+    /// until the buffer is full to resume playback.
     /// This is called from the SoundIoOutStream::write_callback thread context.
     void (*underflow_callback)(struct SoundIoOutStream *);
     /// Optional callback. `err` is always SoundIoErrorStreaming.
@@ -579,7 +582,8 @@ struct SoundIoOutStream {
     int bytes_per_sample;
 
     /// If setting the channel layout fails for some reason, this field is set
-    /// to an error code. Possible error codes are: #SoundIoErrorIncompatibleDevice
+    /// to an error code. Possible error codes are:
+    /// * #SoundIoErrorIncompatibleDevice
     int layout_error;
 };
 
@@ -588,14 +592,16 @@ struct SoundIoInStream {
     /// Populated automatically when you call ::soundio_outstream_create.
     struct SoundIoDevice *device;
 
-    /// Defaults to SoundIoFormatFloat32NE, followed by the first one supported.
+    /// Defaults to #SoundIoFormatFloat32NE, followed by the first one
+    /// supported.
     enum SoundIoFormat format;
 
     /// Sample rate is the number of frames per second.
     /// Defaults to max(sample_rate_min, min(sample_rate_max, 48000))
     int sample_rate;
 
-    /// Defaults to Stereo, if available, followed by the first layout supported.
+    /// Defaults to Stereo, if available, followed by the first layout
+    /// supported.
     struct SoundIoChannelLayout layout;
 
     /// Ignoring hardware latency, this is the number of seconds it takes for a
@@ -651,7 +657,6 @@ struct SoundIoInStream {
     /// Optional: Hint that this input stream is nonterminal. This is used by
     /// JACK and it means that the data received by the stream will be
     /// passed on or made available to another stream. Defaults to `false`.
-    /// stream. Defaults to `false`.
     bool non_terminal_hint;
 
     /// computed automatically when you call ::soundio_instream_open
@@ -1005,7 +1010,7 @@ SOUNDIO_EXPORT int soundio_outstream_clear_buffer(struct SoundIoOutStream *outst
 /// buffer is not full.
 /// Pausing might put the hardware into a low power state which is ideal if your
 /// software is silent for some time.
-/// This function may be called any thread.
+/// This function may be called from any thread.
 /// Pausing when already paused or unpausing when already unpaused has no
 /// effect and always returns SoundIoErrorNone.
 ///
@@ -1116,7 +1121,7 @@ SOUNDIO_EXPORT int soundio_instream_end_read(struct SoundIoInStream *instream);
 /// If the underyling device supports pausing, this pauses the stream and
 /// prevents SoundIoInStream::read_callback from being called. Otherwise this returns
 /// #SoundIoErrorIncompatibleDevice.
-/// You must call this function only from the SoundIoInStream::read_callback thread context.
+/// This function may be called from any thread.
 /// Pausing when already paused or unpausing when already unpaused has no
 /// effect and always returns SoundIoErrorNone.
 ///
diff --git a/src/alsa.cpp b/src/alsa.cpp
index 27f55d3..d1f675c 100644
--- a/src/alsa.cpp
+++ b/src/alsa.cpp
@@ -9,7 +9,6 @@
 #include "soundio.hpp"
 
 #include <sys/inotify.h>
-#include <math.h>
 
 static snd_pcm_stream_t stream_types[] = {SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE};
 
diff --git a/src/dummy.cpp b/src/dummy.cpp
index 2383f7b..da5a871 100644
--- a/src/dummy.cpp
+++ b/src/dummy.cpp
@@ -10,7 +10,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <math.h>
 
 static void playback_thread_run(void *arg) {
     SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
diff --git a/src/os.cpp b/src/os.cpp
index 742e747..8f3f8a6 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -8,14 +8,12 @@
 #include "os.h"
 #include "soundio_private.h"
 #include "util.hpp"
-#include "atomics.hpp"
 
 #include <stdlib.h>
 #include <time.h>
 #include <assert.h>
 #include <string.h>
 #include <errno.h>
-#include <math.h>
 
 #if defined(_WIN32)
 #define SOUNDIO_OS_WINDOWS
@@ -125,7 +123,7 @@ static INIT_ONCE win32_init_once = INIT_ONCE_STATIC_INIT;
 static double win32_time_resolution;
 static SYSTEM_INFO win32_system_info;
 #else
-static atomic_bool initialized = ATOMIC_VAR_INIT(false);
+static bool initialized = false;
 static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
 #if defined(__MACH__)
 static clock_serv_t cclock;
@@ -236,7 +234,7 @@ int soundio_os_thread_create(
     }
 
     if ((err = pthread_create(&thread->id, &thread->attr, run_pthread, thread))) {
-        if (err == EPERM) {
+        if (err == EPERM && emit_rtprio_warning) {
             emit_rtprio_warning();
             err = pthread_create(&thread->id, NULL, run_pthread, thread);
         }
@@ -586,15 +584,12 @@ int soundio_os_init(void) {
     if (!InitOnceComplete(&win32_init_once, INIT_ONCE_ASYNC, nullptr))
         return SoundIoErrorSystemResources;
 #else
-    if (initialized.load())
-        return 0;
-
     assert_no_err(pthread_mutex_lock(&init_mutex));
-    if (initialized.load()) {
+    if (initialized) {
         assert_no_err(pthread_mutex_unlock(&init_mutex));
         return 0;
     }
-    initialized.store(true);
+    initialized = true;
     if ((err = internal_init()))
         return err;
     assert_no_err(pthread_mutex_unlock(&init_mutex));
@@ -668,26 +663,56 @@ int soundio_os_init_mirrored_memory(struct SoundIoOsMirroredMemory *mem, size_t
         break;
     }
 #else
+    char shm_path[] = "/dev/shm/soundio-XXXXXX";
+    char tmp_path[] = "/tmp/soundio-XXXXXX";
+    char *chosen_path;
+
+    int fd = mkstemp(shm_path);
+    if (fd < 0) {
+        fd = mkstemp(tmp_path);
+        if (fd < 0) {
+            return SoundIoErrorSystemResources;
+        } else {
+            chosen_path = tmp_path;
+        }
+    } else {
+        chosen_path = shm_path;
+    }
+
+    if (unlink(chosen_path)) {
+        close(fd);
+        return SoundIoErrorSystemResources;
+    }
+
+    if (ftruncate(fd, actual_capacity)) {
+        close(fd);
+        return SoundIoErrorSystemResources;
+    }
+
     char *address = (char*)mmap(NULL, actual_capacity * 2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
     if (address == MAP_FAILED)
         return SoundIoErrorNoMem;
 
     char *other_address = (char*)mmap(address, actual_capacity, PROT_READ|PROT_WRITE,
-            MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
+            MAP_FIXED|MAP_SHARED, fd, 0);
     if (other_address != address) {
         munmap(address, 2 * actual_capacity);
+        close(fd);
         return SoundIoErrorNoMem;
     }
 
     other_address = (char*)mmap(address + actual_capacity, actual_capacity,
-            PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
+            PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, fd, 0);
     if (other_address != address + actual_capacity) {
         munmap(address, 2 * actual_capacity);
+        close(fd);
         return SoundIoErrorNoMem;
     }
 
     mem->address = address;
 
+    if (close(fd))
+        return SoundIoErrorSystemResources;
 #endif
 
     mem->capacity = actual_capacity;
diff --git a/src/pulseaudio.cpp b/src/pulseaudio.cpp
index 6561014..3aea0b6 100644
--- a/src/pulseaudio.cpp
+++ b/src/pulseaudio.cpp
@@ -9,7 +9,6 @@
 #include "soundio.hpp"
 
 #include <string.h>
-#include <math.h>
 #include <stdio.h>
 
 
@@ -800,7 +799,9 @@ static int outstream_pause_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, b
     SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio;
     SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
 
-    pa_threaded_mainloop_lock(sipa->main_loop);
+    if (!pa_threaded_mainloop_in_thread(sipa->main_loop)) {
+        pa_threaded_mainloop_lock(sipa->main_loop);
+    }
 
     if (pause != pa_stream_is_corked(ospa->stream)) {
         pa_operation *op = pa_stream_cork(ospa->stream, pause, NULL, NULL);
@@ -811,7 +812,9 @@ static int outstream_pause_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os, b
         pa_operation_unref(op);
     }
 
-    pa_threaded_mainloop_unlock(sipa->main_loop);
+    if (!pa_threaded_mainloop_in_thread(sipa->main_loop)) {
+        pa_threaded_mainloop_unlock(sipa->main_loop);
+    }
 
     return 0;
 }
@@ -1026,7 +1029,9 @@ static int instream_pause_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, boo
     SoundIoInStreamPulseAudio *ispa = &is->backend_data.pulseaudio;
     SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
 
-    pa_threaded_mainloop_lock(sipa->main_loop);
+    if (!pa_threaded_mainloop_in_thread(sipa->main_loop)) {
+        pa_threaded_mainloop_lock(sipa->main_loop);
+    }
 
     if (pause != pa_stream_is_corked(ispa->stream)) {
         pa_operation *op = pa_stream_cork(ispa->stream, pause, NULL, NULL);
@@ -1035,7 +1040,9 @@ static int instream_pause_pa(SoundIoPrivate *si, SoundIoInStreamPrivate *is, boo
         pa_operation_unref(op);
     }
 
-    pa_threaded_mainloop_unlock(sipa->main_loop);
+    if (!pa_threaded_mainloop_in_thread(sipa->main_loop)) {
+        pa_threaded_mainloop_unlock(sipa->main_loop);
+    }
 
     return 0;
 }
diff --git a/src/soundio.cpp b/src/soundio.cpp
index e06c2d8..d6c017a 100644
--- a/src/soundio.cpp
+++ b/src/soundio.cpp
@@ -763,21 +763,29 @@ bool soundio_device_supports_sample_rate(struct SoundIoDevice *device, int sampl
     return false;
 }
 
+static int abs_diff_int(int a, int b) {
+    int x = a - b;
+    return (x >= 0) ? x : -x;
+}
+
 int soundio_device_nearest_sample_rate(struct SoundIoDevice *device, int sample_rate) {
     int best_rate = -1;
     int best_delta = -1;
     for (int i = 0; i < device->sample_rate_count; i += 1) {
         SoundIoSampleRateRange *range = &device->sample_rates[i];
-        if (sample_rate < range->min) {
-            int delta = range->min - sample_rate;
-            if (best_delta == -1 || delta < best_delta) {
-                best_delta = delta;
-                best_rate = range->min;
-            }
-        } else if (best_rate == -1 && sample_rate > range->max) {
-            best_rate = range->max;
-        } else {
-            return sample_rate;
+        int candidate_rate = clamp(range->min, sample_rate, range->max);
+        if (candidate_rate == sample_rate)
+            return candidate_rate;
+
+        int delta = abs_diff_int(candidate_rate, sample_rate);
+        bool best_rate_too_small = best_rate < sample_rate;
+        bool candidate_rate_too_small = candidate_rate < sample_rate;
+        if (best_rate == -1 ||
+            (best_rate_too_small && !candidate_rate_too_small) ||
+            ((best_rate_too_small || !candidate_rate_too_small) && delta < best_delta))
+        {
+            best_rate = candidate_rate;
+            best_delta = delta;
         }
     }
     return best_rate;
diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp
index d8a72c4..3a25255 100644
--- a/test/unit_tests.cpp
+++ b/test/unit_tests.cpp
@@ -15,7 +15,7 @@ static inline void ok_or_panic(int err) {
 }
 
 static void test_os_get_time(void) {
-    soundio_os_init();
+    ok_or_panic(soundio_os_init());
     double prev_time = soundio_os_get_time();
     for (int i = 0; i < 1000; i += 1) {
         double time = soundio_os_get_time();
@@ -165,6 +165,51 @@ static void test_ring_buffer_threaded(void) {
     soundio_destroy(soundio);
 }
 
+static void test_mirrored_memory(void) {
+    struct SoundIoOsMirroredMemory mem;
+    ok_or_panic(soundio_os_init());
+
+    static const int requested_bytes = 1024;
+    ok_or_panic(soundio_os_init_mirrored_memory(&mem, requested_bytes));
+    const int size_bytes = mem.capacity;
+
+    for (int i = 0; i < size_bytes; i += 1) {
+        mem.address[i] = rand() % CHAR_MAX;
+    }
+    for (int i = 0; i < size_bytes; i += 1) {
+        assert(mem.address[i] == mem.address[size_bytes+i]);
+    }
+
+    soundio_os_deinit_mirrored_memory(&mem);
+}
+
+static void test_nearest_sample_rate(void) {
+    struct SoundIoDevice device;
+    struct SoundIoSampleRateRange sample_rates[2] = {
+        {
+            44100,
+            48000
+        },
+        {
+            96000,
+            96000,
+        },
+    };
+
+    device.sample_rate_count = 2;
+    device.sample_rates = sample_rates;
+
+    assert(soundio_device_nearest_sample_rate(&device, 100) == 44100);
+    assert(soundio_device_nearest_sample_rate(&device, 44099) == 44100);
+    assert(soundio_device_nearest_sample_rate(&device, 44100) == 44100);
+    assert(soundio_device_nearest_sample_rate(&device, 45000) == 45000);
+    assert(soundio_device_nearest_sample_rate(&device, 48000) == 48000);
+    assert(soundio_device_nearest_sample_rate(&device, 48001) == 96000);
+    assert(soundio_device_nearest_sample_rate(&device, 90000) == 96000);
+    assert(soundio_device_nearest_sample_rate(&device, 96001) == 96000);
+    assert(soundio_device_nearest_sample_rate(&device, 9999999) == 96000);
+}
+
 struct Test {
     const char *name;
     void (*fn)(void);
@@ -175,6 +220,8 @@ static struct Test tests[] = {
     {"create output stream", test_create_outstream},
     {"ring buffer basic", test_ring_buffer_basic},
     {"ring buffer threaded", test_ring_buffer_threaded},
+    {"mirrored memory", test_mirrored_memory},
+    {"soundio_device_nearest_sample_rate", test_nearest_sample_rate},
     {NULL, NULL},
 };
 

-- 
libsoundio packaging



More information about the pkg-multimedia-commits mailing list