Bug 1367646 - Update cubeb from upstream to 087dc94. r=kinetik

MozReview-Commit-ID: E1D2XCtugqW

--HG--
extra : rebase_source : 20d630e763aa840d1a07e0edf128206dd8b679e8
This commit is contained in:
Dan Glastonbury 2017-05-25 14:45:04 +10:00
Родитель 0f2aff9431
Коммит 9224fdaf13
24 изменённых файлов: 422 добавлений и 308 удалений

Просмотреть файл

@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
The git commit ID used was 96cdb173f86dfc86cbd21d097b24ec1e256d69fc (2017-05-22 11:55:15 +0300)
The git commit ID used was 087dc942a9a3bb5cbb88e3763cde7fe709db99e9 (2017-05-29 15:51:19 +1200)

Просмотреть файл

@ -70,7 +70,7 @@ layout_info const layout_infos[CUBEB_LAYOUT_MAX] = {
int has_available_input_device(cubeb * ctx)
{
cubeb_device_collection * devices;
cubeb_device_collection devices;
int input_device_available = 0;
int r;
/* Bail out early if the host does not have input devices. */
@ -80,14 +80,14 @@ int has_available_input_device(cubeb * ctx)
return 0;
}
if (devices->count == 0) {
if (devices.count == 0) {
fprintf(stderr, "no input device available, skipping test.\n");
cubeb_device_collection_destroy(ctx, devices);
cubeb_device_collection_destroy(ctx, &devices);
return 0;
}
for (uint32_t i = 0; i < devices->count; i++) {
input_device_available |= (devices->device[i]->state ==
for (uint32_t i = 0; i < devices.count; i++) {
input_device_available |= (devices.device[i].state ==
CUBEB_DEVICE_STATE_ENABLED);
}
@ -96,7 +96,7 @@ int has_available_input_device(cubeb * ctx)
"available, skipping\n");
}
cubeb_device_collection_destroy(ctx, devices);
cubeb_device_collection_destroy(ctx, &devices);
return !!input_device_available;
}
@ -108,4 +108,26 @@ void print_log(const char * msg, ...)
va_end(args);
}
/** Initialize cubeb with backend override.
* Create call cubeb_init passing value for CUBEB_BACKEND env var as
* override. */
int common_init(cubeb ** ctx, char const * ctx_name)
{
int r;
char const * backend;
char const * ctx_backend;
backend = getenv("CUBEB_BACKEND");
r = cubeb_init(ctx, ctx_name, backend);
if (r == CUBEB_OK && backend) {
ctx_backend = cubeb_get_backend_id(*ctx);
if (strcmp(backend, ctx_backend) != 0) {
fprintf(stderr, "Requested backend `%s', got `%s'\n",
backend, ctx_backend);
}
}
return r;
}
#endif /* TEST_COMMON */

Просмотреть файл

@ -100,7 +100,7 @@ int run_test(int num_channels, layout_info layout, int sampling_rate, int is_flo
cubeb *ctx = NULL;
r = cubeb_init(&ctx, "Cubeb audio test: channels", NULL);
r = common_init(&ctx, "Cubeb audio test: channels");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
return r;
@ -150,7 +150,7 @@ int run_panning_volume_test(int is_float)
cubeb *ctx = NULL;
r = cubeb_init(&ctx, "Cubeb audio test", NULL);
r = common_init(&ctx, "Cubeb audio test");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
return r;

Просмотреть файл

@ -13,6 +13,7 @@
#include <string.h>
#include <memory>
#include "cubeb/cubeb.h"
#include "common.h"
static void
print_device_info(cubeb_device_info * info, FILE * f)
@ -101,16 +102,39 @@ print_device_collection(cubeb_device_collection * collection, FILE * f)
uint32_t i;
for (i = 0; i < collection->count; i++)
print_device_info(collection->device[i], f);
print_device_info(&collection->device[i], f);
}
TEST(cubeb, destroy_default_collection)
{
int r;
cubeb * ctx = NULL;
cubeb_device_collection collection{ nullptr, 0 };
r = common_init(&ctx, "Cubeb audio test");
ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library";
std::unique_ptr<cubeb, decltype(&cubeb_destroy)>
cleanup_cubeb_at_exit(ctx, cubeb_destroy);
ASSERT_EQ(collection.device, nullptr);
ASSERT_EQ(collection.count, (size_t) 0);
r = cubeb_device_collection_destroy(ctx, &collection);
if (r != CUBEB_ERROR_NOT_SUPPORTED) {
ASSERT_EQ(r, CUBEB_OK);
ASSERT_EQ(collection.device, nullptr);
ASSERT_EQ(collection.count, (size_t) 0);
}
}
TEST(cubeb, enumerate_devices)
{
int r;
cubeb * ctx = NULL;
cubeb_device_collection * collection = NULL;
cubeb_device_collection collection;
r = cubeb_init(&ctx, "Cubeb audio test", NULL);
r = common_init(&ctx, "Cubeb audio test");
ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library";
std::unique_ptr<cubeb, decltype(&cubeb_destroy)>
@ -127,9 +151,9 @@ TEST(cubeb, enumerate_devices)
}
ASSERT_EQ(r, CUBEB_OK) << "Error enumerating devices " << r;
fprintf(stdout, "Found %u input devices\n", collection->count);
print_device_collection(collection, stdout);
cubeb_device_collection_destroy(ctx, collection);
fprintf(stdout, "Found %zu input devices\n", collection.count);
print_device_collection(&collection, stdout);
cubeb_device_collection_destroy(ctx, &collection);
fprintf(stdout, "Enumerating output devices for backend %s\n",
cubeb_get_backend_id(ctx));
@ -137,7 +161,7 @@ TEST(cubeb, enumerate_devices)
r = cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection);
ASSERT_EQ(r, CUBEB_OK) << "Error enumerating devices " << r;
fprintf(stdout, "Found %u output devices\n", collection->count);
print_device_collection(collection, stdout);
cubeb_device_collection_destroy(ctx, collection);
fprintf(stdout, "Found %zu output devices\n", collection.count);
print_device_collection(&collection, stdout);
cubeb_device_collection_destroy(ctx, &collection);
}

Просмотреть файл

@ -83,7 +83,7 @@ TEST(cubeb, duplex)
user_state_duplex stream_state = { false };
uint32_t latency_frames = 0;
r = cubeb_init(&ctx, "Cubeb duplex example", NULL);
r = common_init(&ctx, "Cubeb duplex example");
ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library";
std::unique_ptr<cubeb, decltype(&cubeb_destroy)>

Просмотреть файл

@ -2,6 +2,7 @@
#include <stdlib.h>
#include <memory>
#include "cubeb/cubeb.h"
#include "common.h"
TEST(cubeb, latency)
{
@ -10,9 +11,8 @@ TEST(cubeb, latency)
uint32_t max_channels;
uint32_t preferred_rate;
uint32_t latency_frames;
cubeb_channel_layout layout;
r = cubeb_init(&ctx, "Cubeb audio test", NULL);
r = common_init(&ctx, "Cubeb audio test");
ASSERT_EQ(r, CUBEB_OK);
std::unique_ptr<cubeb, decltype(&cubeb_destroy)>
@ -30,15 +30,11 @@ TEST(cubeb, latency)
ASSERT_GT(preferred_rate, 0u);
}
r = cubeb_get_preferred_channel_layout(ctx, &layout);
ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED ||
(r == CUBEB_ERROR && layout == CUBEB_LAYOUT_UNDEFINED));
cubeb_stream_params params = {
CUBEB_SAMPLE_FLOAT32NE,
preferred_rate,
max_channels,
(r == CUBEB_OK) ? layout : CUBEB_LAYOUT_UNDEFINED
CUBEB_LAYOUT_UNDEFINED
#if defined(__ANDROID__)
, CUBEB_STREAM_TYPE_MUSIC
#endif

Просмотреть файл

@ -88,6 +88,7 @@ audio_input audio_inputs[CUBEB_LAYOUT_MAX] = {
{ CUBEB_LAYOUT_3F4_LFE, { L, R, C, LFE, RLS, RRS, LS, RS } }
};
// The test cases must be aligned with cubeb_downmix.
void
downmix_test(float const * data, cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
{
@ -126,7 +127,14 @@ downmix_test(float const * data, cubeb_channel_layout in_layout, cubeb_channel_l
unsigned int const inframes = 10;
vector<float> in(in_params.channels * inframes);
#if defined(__APPLE__)
// The mixed buffer size doesn't be changed based on the channel layout set on OSX.
// Please see the comment above downmix_3f2 in cubeb_mixer.cpp.
vector<float> out(in_params.channels * inframes);
#else
// In normal case, the mixed buffer size is based on the mixing channel layout.
vector<float> out(out_params.channels * inframes);
#endif
for (unsigned int offset = 0 ; offset < inframes * in_params.channels ; offset += in_params.channels) {
for (unsigned int i = 0 ; i < in_params.channels ; ++i) {
@ -138,7 +146,7 @@ downmix_test(float const * data, cubeb_channel_layout in_layout, cubeb_channel_l
std::unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)>
mixer(cubeb_mixer_create(in_params.format, CUBEB_MIXER_DIRECTION_DOWNMIX), cubeb_mixer_destroy);
cubeb_mixer_mix(mixer.get(), in.data(), inframes, out.data(), &in_params, &out_params);
cubeb_mixer_mix(mixer.get(), inframes, in.data(), in.size(), out.data(), out.size(), &in_params, &out_params);
uint32_t in_layout_mask = 0;
for (unsigned int i = 0 ; i < in_params.channels; ++i) {
@ -157,22 +165,27 @@ downmix_test(float const * data, cubeb_channel_layout in_layout, cubeb_channel_l
if ((in_layout == CUBEB_LAYOUT_3F2 || in_layout == CUBEB_LAYOUT_3F2_LFE) &&
out_layout >= CUBEB_LAYOUT_MONO && out_layout <= CUBEB_LAYOUT_2F2_LFE) {
auto & downmix_results = DOWNMIX_3F2_RESULTS[in_layout - CUBEB_LAYOUT_3F2][out_layout - CUBEB_LAYOUT_MONO];
fprintf(stderr, "[3f2] Expect: %lf, Get: %lf\n", downmix_results[index], out[index]);
ASSERT_EQ(downmix_results[index], out[index]);
fprintf(stderr, "[3f2] Expect: %lf, Get: %lf\n", downmix_results[index], out[i]);
ASSERT_EQ(downmix_results[index], out[i]);
continue;
}
#if defined(__APPLE__)
// We only support downmix for audio 5.1 on OS X currently.
return;
#endif
// mix_remap
if (out_layout_mask & in_layout_mask) {
uint32_t mask = 1 << CHANNEL_INDEX_TO_ORDER[out_layout][index];
fprintf(stderr, "[map channels] Expect: %lf, Get: %lf\n", (mask & in_layout_mask) ? audio_inputs[out_layout].data[index] : 0, out[index]);
ASSERT_EQ((mask & in_layout_mask) ? audio_inputs[out_layout].data[index] : 0, out[index]);
fprintf(stderr, "[map channels] Expect: %lf, Get: %lf\n", (mask & in_layout_mask) ? audio_inputs[out_layout].data[index] : 0, out[i]);
ASSERT_EQ((mask & in_layout_mask) ? audio_inputs[out_layout].data[index] : 0, out[i]);
continue;
}
// downmix_fallback
fprintf(stderr, "[fallback] Expect: %lf, Get: %lf\n", audio_inputs[in_layout].data[index], out[index]);
ASSERT_EQ(audio_inputs[in_layout].data[index], out[index]);
fprintf(stderr, "[fallback] Expect: %lf, Get: %lf\n", audio_inputs[in_layout].data[index], out[i]);
ASSERT_EQ(audio_inputs[in_layout].data[index], out[i]);
}
}

Просмотреть файл

@ -58,7 +58,7 @@ TEST(cubeb, overload_callback)
int r;
uint32_t latency_frames = 0;
r = cubeb_init(&ctx, "Cubeb callback overload", NULL);
r = common_init(&ctx, "Cubeb callback overload");
ASSERT_EQ(r, CUBEB_OK);
std::unique_ptr<cubeb, decltype(&cubeb_destroy)>

Просмотреть файл

@ -77,7 +77,7 @@ TEST(cubeb, record)
int r;
user_state_record stream_state = { false };
r = cubeb_init(&ctx, "Cubeb record example", NULL);
r = common_init(&ctx, "Cubeb record example");
ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library";
std::unique_ptr<cubeb, decltype(&cubeb_destroy)>

Просмотреть файл

@ -77,7 +77,7 @@ TEST(cubeb, init_destroy_context)
cubeb * ctx;
char const* backend_id;
r = cubeb_init(&ctx, "test_sanity", NULL);
r = common_init(&ctx, "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);
@ -98,7 +98,7 @@ TEST(cubeb, init_destroy_multiple_contexts)
ASSERT_EQ(ARRAY_LENGTH(ctx), ARRAY_LENGTH(order));
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
r = cubeb_init(&ctx[i], NULL, NULL);
r = common_init(&ctx[i], NULL);
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx[i], nullptr);
}
@ -114,9 +114,10 @@ TEST(cubeb, context_variables)
int r;
cubeb * ctx;
uint32_t value;
cubeb_channel_layout layout;
cubeb_stream_params params;
r = cubeb_init(&ctx, "test_context_variables", NULL);
r = common_init(&ctx, "test_context_variables");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);
@ -139,6 +140,11 @@ TEST(cubeb, context_variables)
ASSERT_TRUE(value > 0);
}
r = cubeb_get_preferred_channel_layout(ctx, &layout);
ASSERT_TRUE(r == CUBEB_ERROR_NOT_SUPPORTED ||
(r == CUBEB_OK && layout != CUBEB_LAYOUT_UNDEFINED) ||
(r == CUBEB_ERROR && layout == CUBEB_LAYOUT_UNDEFINED));
cubeb_destroy(ctx);
}
@ -149,7 +155,7 @@ TEST(cubeb, init_destroy_stream)
cubeb_stream * stream;
cubeb_stream_params params;
r = cubeb_init(&ctx, "test_sanity", NULL);
r = common_init(&ctx, "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);
@ -178,7 +184,7 @@ TEST(cubeb, init_destroy_multiple_streams)
cubeb_stream * stream[8];
cubeb_stream_params params;
r = cubeb_init(&ctx, "test_sanity", NULL);
r = common_init(&ctx, "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);
@ -211,7 +217,7 @@ TEST(cubeb, configure_stream)
cubeb_stream * stream;
cubeb_stream_params params;
r = cubeb_init(&ctx, "test_sanity", NULL);
r = common_init(&ctx, "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);
@ -247,7 +253,7 @@ test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
cubeb_stream * stream[8];
cubeb_stream_params params;
r = cubeb_init(&ctx, "test_sanity", NULL);
r = common_init(&ctx, "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);
@ -347,7 +353,7 @@ TEST(cubeb, init_destroy_multiple_contexts_and_streams)
#endif
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
r = cubeb_init(&ctx[i], "test_sanity", NULL);
r = common_init(&ctx[i], "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx[i], nullptr);
@ -375,7 +381,7 @@ TEST(cubeb, basic_stream_operations)
cubeb_stream_params params;
uint64_t position;
r = cubeb_init(&ctx, "test_sanity", NULL);
r = common_init(&ctx, "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);
@ -426,7 +432,7 @@ TEST(cubeb, stream_position)
total_frames_written = 0;
r = cubeb_init(&ctx, "test_sanity", NULL);
r = common_init(&ctx, "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);
@ -562,7 +568,7 @@ TEST(cubeb, drain)
delay_callback = 0;
total_frames_written = 0;
r = cubeb_init(&ctx, "test_sanity", NULL);
r = common_init(&ctx, "test_sanity");
ASSERT_EQ(r, CUBEB_OK);
ASSERT_NE(ctx, nullptr);

Просмотреть файл

@ -84,7 +84,7 @@ TEST(cubeb, tone)
cubeb_stream_params params;
int r;
r = cubeb_init(&ctx, "Cubeb tone example", NULL);
r = common_init(&ctx, "Cubeb tone example");
ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library";
std::unique_ptr<cubeb, decltype(&cubeb_destroy)>

Просмотреть файл

@ -8,6 +8,7 @@
#define CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382
#include <stdint.h>
#include <stdlib.h>
#include "cubeb_export.h"
#if defined(__cplusplus)
@ -352,16 +353,16 @@ typedef struct {
unsigned int max_rate; /**< Maximum sample rate supported. */
unsigned int min_rate; /**< Minimum sample rate supported. */
unsigned int latency_lo; /**< Lowest possible latency in frames. */
unsigned int latency_hi; /**< Higest possible latency in frames. */
unsigned int latency_lo; /**< Lowest possible latency in frames. */
unsigned int latency_hi; /**< Higest possible latency in frames. */
} cubeb_device_info;
/** Device collection.
* Returned by `cubeb_enumerate_devices` and destroyed by
* `cubeb_device_collection_destroy`. */
typedef struct {
uint32_t count; /**< Device count in collection. */
cubeb_device_info * device[1]; /**< Array of pointers to device info. */
cubeb_device_info * device; /**< Array of pointers to device info. */
size_t count; /**< Device count in collection. */
} cubeb_device_collection;
/** User supplied data callback.
@ -612,7 +613,7 @@ CUBEB_EXPORT int cubeb_stream_register_device_changed_callback(cubeb_stream * st
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_enumerate_devices(cubeb * context,
cubeb_device_type devtype,
cubeb_device_collection ** collection);
cubeb_device_collection * collection);
/** Destroy a cubeb_device_collection, and its `cubeb_device_info`.
@param context

Просмотреть файл

@ -51,8 +51,9 @@ struct cubeb_ops {
int (* get_preferred_sample_rate)(cubeb * context, uint32_t * rate);
int (* get_preferred_channel_layout)(cubeb * context, cubeb_channel_layout * layout);
int (* enumerate_devices)(cubeb * context, cubeb_device_type type,
cubeb_device_collection ** collection);
int (* device_collection_destroy)(cubeb * context, cubeb_device_collection * collection);
cubeb_device_collection * collection);
int (* device_collection_destroy)(cubeb * context,
cubeb_device_collection * collection);
void (* destroy)(cubeb * context);
int (* stream_init)(cubeb * context,
cubeb_stream ** stream,

Просмотреть файл

@ -550,7 +550,7 @@ void log_device(cubeb_device_info * device_info)
int cubeb_enumerate_devices(cubeb * context,
cubeb_device_type devtype,
cubeb_device_collection ** collection)
cubeb_device_collection * collection)
{
int rv;
if ((devtype & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) == 0)
@ -563,8 +563,8 @@ int cubeb_enumerate_devices(cubeb * context,
rv = context->ops->enumerate_devices(context, devtype, collection);
if (g_cubeb_log_callback) {
for (uint32_t i = 0; i < (*collection)->count; i++) {
log_device((*collection)->device[i]);
for (size_t i = 0; i < collection->count; i++) {
log_device(&collection->device[i]);
}
}
@ -574,13 +574,24 @@ int cubeb_enumerate_devices(cubeb * context,
int cubeb_device_collection_destroy(cubeb * context,
cubeb_device_collection * collection)
{
int r;
if (context == NULL || collection == NULL)
return CUBEB_ERROR_INVALID_PARAMETER;
if (!context->ops->device_collection_destroy)
return CUBEB_ERROR_NOT_SUPPORTED;
return context->ops->device_collection_destroy(context, collection);
if (!collection->device)
return CUBEB_OK;
r = context->ops->device_collection_destroy(context, collection);
if (r == CUBEB_OK) {
collection->device = NULL;
collection->count = 0;
}
return r;
}
int cubeb_register_device_collection_changed(cubeb * context,

Просмотреть файл

@ -1288,8 +1288,10 @@ alsa_stream_set_volume(cubeb_stream * stm, float volume)
static int
alsa_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_collection ** collection)
cubeb_device_collection * collection)
{
cubeb_device_info* device = NULL;
if (!context)
return CUBEB_ERROR;
@ -1306,35 +1308,45 @@ alsa_enumerate_devices(cubeb * context, cubeb_device_type type,
return CUBEB_ERROR;
}
*collection = (cubeb_device_collection *) calloc(1, sizeof(cubeb_device_collection) + 1*sizeof(cubeb_device_info *));
assert(*collection);
char const * a_name = "default";
(*collection)->device[0] = (cubeb_device_info *) calloc(1, sizeof(cubeb_device_info));
assert((*collection)->device[0]);
device = (cubeb_device_info *) calloc(1, sizeof(cubeb_device_info));
assert(device);
if (!device)
return CUBEB_ERROR;
(*collection)->device[0]->device_id = strdup(a_name);
(*collection)->device[0]->devid = (*collection)->device[0]->device_id;
(*collection)->device[0]->friendly_name = strdup(a_name);
(*collection)->device[0]->group_id = strdup(a_name);
(*collection)->device[0]->vendor_name = strdup(a_name);
(*collection)->device[0]->type = type;
(*collection)->device[0]->state = CUBEB_DEVICE_STATE_ENABLED;
(*collection)->device[0]->preferred = CUBEB_DEVICE_PREF_ALL;
(*collection)->device[0]->format = CUBEB_DEVICE_FMT_S16NE;
(*collection)->device[0]->default_format = CUBEB_DEVICE_FMT_S16NE;
(*collection)->device[0]->max_channels = max_channels;
(*collection)->device[0]->min_rate = rate;
(*collection)->device[0]->max_rate = rate;
(*collection)->device[0]->default_rate = rate;
(*collection)->device[0]->latency_lo = 0;
(*collection)->device[0]->latency_hi = 0;
device->device_id = a_name;
device->devid = (cubeb_devid) device->device_id;
device->friendly_name = a_name;
device->group_id = a_name;
device->vendor_name = a_name;
device->type = type;
device->state = CUBEB_DEVICE_STATE_ENABLED;
device->preferred = CUBEB_DEVICE_PREF_ALL;
device->format = CUBEB_DEVICE_FMT_S16NE;
device->default_format = CUBEB_DEVICE_FMT_S16NE;
device->max_channels = max_channels;
device->min_rate = rate;
device->max_rate = rate;
device->default_rate = rate;
device->latency_lo = 0;
device->latency_hi = 0;
(*collection)->count = 1;
collection->device = device;
collection->count = 1;
return CUBEB_OK;
}
static int
alsa_device_collection_destroy(cubeb * context,
cubeb_device_collection * collection)
{
assert(collection->count == 1);
(void) context;
free(collection->device);
return CUBEB_OK;
}
static struct cubeb_ops const alsa_ops = {
.init = alsa_init,
.get_backend_id = alsa_get_backend_id,
@ -1343,7 +1355,7 @@ static struct cubeb_ops const alsa_ops = {
.get_preferred_sample_rate = alsa_get_preferred_sample_rate,
.get_preferred_channel_layout = NULL,
.enumerate_devices = alsa_enumerate_devices,
.device_collection_destroy = cubeb_utils_default_device_collection_destroy,
.device_collection_destroy = alsa_device_collection_destroy,
.destroy = alsa_destroy,
.stream_init = alsa_stream_init,
.stream_destroy = alsa_stream_destroy,

Просмотреть файл

@ -29,7 +29,6 @@
#endif
#include "cubeb_resampler.h"
#include "cubeb_ring_array.h"
#include "cubeb_utils.h"
#include <algorithm>
#include <atomic>
#include <vector>
@ -388,8 +387,9 @@ is_extra_input_needed(cubeb_stream * stm)
static void
audiounit_mix_output_buffer(cubeb_stream * stm,
long output_frames,
void * output_buffer,
long output_frames)
unsigned long output_buffer_length)
{
cubeb_stream_params output_mixer_params = {
stm->output_stream_params.format,
@ -400,7 +400,9 @@ audiounit_mix_output_buffer(cubeb_stream * stm,
// The downmixing(from 5.1) supports in-place conversion, so we can use
// the same buffer for both input and output of the mixer.
cubeb_mixer_mix(stm->mixer.get(), output_buffer, output_frames, output_buffer,
cubeb_mixer_mix(stm->mixer.get(), output_frames,
output_buffer, output_buffer_length,
output_buffer, output_buffer_length,
&stm->output_stream_params, &output_mixer_params);
}
@ -522,7 +524,8 @@ audiounit_output_callback(void * user_ptr,
}
/* Mixing */
audiounit_mix_output_buffer(stm, output_buffer, output_frames);
unsigned long output_buffer_length = outBufferList->mBuffers[0].mDataByteSize;
audiounit_mix_output_buffer(stm, output_frames, output_buffer, output_buffer_length);
return noErr;
}
@ -2918,11 +2921,12 @@ audiounit_strref_to_cstr_utf8(CFStringRef strref)
}
len = CFStringGetLength(strref);
size = CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8);
ret = static_cast<char *>(malloc(size));
// Add 1 to size to allow for '\0' termination character.
size = CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1;
ret = new char[size];
if (!CFStringGetCString(strref, ret, size, kCFStringEncodingUTF8)) {
free(ret);
delete [] ret;
ret = NULL;
}
@ -3019,12 +3023,11 @@ audiounit_get_device_presentation_latency(AudioObjectID devid, AudioObjectProper
return dev + stream + offset;
}
static cubeb_device_info *
audiounit_create_device_from_hwdev(AudioObjectID devid, cubeb_device_type type)
static int
audiounit_create_device_from_hwdev(cubeb_device_info * ret, AudioObjectID devid, cubeb_device_type type)
{
AudioObjectPropertyAddress adr = { 0, 0, kAudioObjectPropertyElementMaster };
UInt32 size, ch, latency;
cubeb_device_info * ret;
CFStringRef str = NULL;
AudioValueRange range;
@ -3033,15 +3036,14 @@ audiounit_create_device_from_hwdev(AudioObjectID devid, cubeb_device_type type)
} else if (type == CUBEB_DEVICE_TYPE_INPUT) {
adr.mScope = kAudioDevicePropertyScopeInput;
} else {
return NULL;
return CUBEB_ERROR;
}
ch = audiounit_get_channel_count(devid, adr.mScope);
if (ch == 0) {
return NULL;
return CUBEB_ERROR;
}
ret = new cubeb_device_info;
PodZero(ret, 1);
size = sizeof(CFStringRef);
@ -3050,7 +3052,7 @@ audiounit_create_device_from_hwdev(AudioObjectID devid, cubeb_device_type type)
ret->device_id = audiounit_strref_to_cstr_utf8(str);
static_assert(sizeof(cubeb_devid) >= sizeof(decltype(devid)), "cubeb_devid can't represent devid");
ret->devid = reinterpret_cast<cubeb_devid>(devid);
ret->group_id = strdup(ret->device_id);
ret->group_id = ret->device_id;
CFRelease(str);
}
@ -3108,12 +3110,12 @@ audiounit_create_device_from_hwdev(AudioObjectID devid, cubeb_device_type type)
ret->latency_hi = 100 * ret->default_rate / 1000; /* Default to 100ms */
}
return ret;
return CUBEB_OK;
}
static int
audiounit_enumerate_devices(cubeb * /* context */, cubeb_device_type type,
cubeb_device_collection ** collection)
cubeb_device_collection * collection)
{
std::vector<AudioObjectID> hwdevs;
uint32_t i;
@ -3124,26 +3126,52 @@ audiounit_enumerate_devices(cubeb * /* context */, cubeb_device_type type,
return CUBEB_ERROR;
}
*collection = static_cast<cubeb_device_collection *>(malloc(sizeof(cubeb_device_collection) +
sizeof(cubeb_device_info*) * (hwdevs.size() > 0 ? hwdevs.size() - 1 : 0)));
(*collection)->count = 0;
auto devices = new cubeb_device_info[hwdevs.size()];
collection->count = 0;
if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
for (i = 0; i < hwdevs.size(); i++) {
cubeb_device_info * cur = audiounit_create_device_from_hwdev(hwdevs[i], CUBEB_DEVICE_TYPE_OUTPUT);
if (cur != nullptr)
(*collection)->device[(*collection)->count++] = cur;
auto device = &devices[collection->count];
auto err = audiounit_create_device_from_hwdev(device, hwdevs[i], CUBEB_DEVICE_TYPE_OUTPUT);
if (err != CUBEB_OK) {
continue;
}
collection->count += 1;
}
}
if (type & CUBEB_DEVICE_TYPE_INPUT) {
for (i = 0; i < hwdevs.size(); i++) {
cubeb_device_info * cur = audiounit_create_device_from_hwdev(hwdevs[i], CUBEB_DEVICE_TYPE_INPUT);
if (cur != nullptr)
(*collection)->device[(*collection)->count++] = cur;
auto device = &devices[collection->count];
auto err = audiounit_create_device_from_hwdev(device, hwdevs[i], CUBEB_DEVICE_TYPE_INPUT);
if (err != CUBEB_OK) {
continue;
}
collection->count += 1;
}
}
if (collection->count > 0) {
collection->device = devices;
} else {
delete [] devices;
collection->device = NULL;
}
return CUBEB_OK;
}
static int
audiounit_device_collection_destroy(cubeb * /* context */,
cubeb_device_collection * collection)
{
for (size_t i = 0; i < collection->count; i++) {
delete [] collection->device[i].device_id;
delete [] collection->device[i].friendly_name;
delete [] collection->device[i].vendor_name;
}
delete [] collection->device;
return CUBEB_OK;
}
@ -3305,7 +3333,7 @@ cubeb_ops const audiounit_ops = {
/*.get_preferred_sample_rate =*/ audiounit_get_preferred_sample_rate,
/*.get_preferred_channel_layout =*/ audiounit_get_preferred_channel_layout,
/*.enumerate_devices =*/ audiounit_enumerate_devices,
/*.device_collection_destroy =*/ cubeb_utils_default_device_collection_destroy,
/*.device_collection_destroy =*/ audiounit_device_collection_destroy,
/*.destroy =*/ audiounit_destroy,
/*.stream_init =*/ audiounit_stream_init,
/*.stream_destroy =*/ audiounit_stream_destroy,

Просмотреть файл

@ -93,7 +93,7 @@ static int cbjack_stream_device_destroy(cubeb_stream * stream,
cubeb_device * device);
static int cbjack_stream_get_current_device(cubeb_stream * stm, cubeb_device ** const device);
static int cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_collection ** collection);
cubeb_device_collection * collection);
static int cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
cubeb_devid input_device,
cubeb_stream_params * input_stream_params,
@ -180,7 +180,6 @@ struct cubeb {
cubeb_stream streams[MAX_STREAMS];
unsigned int active_streams;
cubeb_device_info * devinfo[2];
cubeb_device_collection_changed_callback collection_changed_callback;
bool active;
@ -974,68 +973,63 @@ cbjack_stream_device_destroy(cubeb_stream * /*stream*/,
static int
cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_collection ** collection)
cubeb_device_collection * collection)
{
if (!context)
return CUBEB_ERROR;
uint32_t rate;
uint8_t i = 0;
uint8_t j;
cbjack_get_preferred_sample_rate(context, &rate);
const char * j_in = "JACK capture";
const char * j_out = "JACK playback";
cubeb_device_info * devices = new cubeb_device_info[2];
reinterpret_cast<cubeb_device_info *>(calloc(2, sizeof(cubeb_device_info)));
collection->count = 0;
if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
context->devinfo[i] = (cubeb_device_info *) malloc(sizeof(cubeb_device_info));
context->devinfo[i]->device_id = strdup(j_out);
context->devinfo[i]->devid = (cubeb_devid) context->devinfo[i]->device_id;
context->devinfo[i]->friendly_name = strdup(j_out);
context->devinfo[i]->group_id = strdup(j_out);
context->devinfo[i]->vendor_name = strdup(j_out);
context->devinfo[i]->type = CUBEB_DEVICE_TYPE_OUTPUT;
context->devinfo[i]->state = CUBEB_DEVICE_STATE_ENABLED;
context->devinfo[i]->preferred = CUBEB_DEVICE_PREF_ALL;
context->devinfo[i]->format = CUBEB_DEVICE_FMT_F32NE;
context->devinfo[i]->default_format = CUBEB_DEVICE_FMT_F32NE;
context->devinfo[i]->max_channels = MAX_CHANNELS;
context->devinfo[i]->min_rate = rate;
context->devinfo[i]->max_rate = rate;
context->devinfo[i]->default_rate = rate;
context->devinfo[i]->latency_lo = 0;
context->devinfo[i]->latency_hi = 0;
i++;
cubeb_device_info * cur = &devices[collection->count];
cur->device_id = strdup(j_out);
cur->devid = (cubeb_devid) cur->device_id;
cur->friendly_name = strdup(j_out);
cur->group_id = strdup(j_out);
cur->vendor_name = strdup(j_out);
cur->type = CUBEB_DEVICE_TYPE_OUTPUT;
cur->state = CUBEB_DEVICE_STATE_ENABLED;
cur->preferred = CUBEB_DEVICE_PREF_ALL;
cur->format = CUBEB_DEVICE_FMT_F32NE;
cur->default_format = CUBEB_DEVICE_FMT_F32NE;
cur->max_channels = MAX_CHANNELS;
cur->min_rate = rate;
cur->max_rate = rate;
cur->default_rate = rate;
cur->latency_lo = 0;
cur->latency_hi = 0;
collection->count +=1 ;
}
if (type & CUBEB_DEVICE_TYPE_INPUT) {
context->devinfo[i] = (cubeb_device_info *) malloc(sizeof(cubeb_device_info));
context->devinfo[i]->device_id = strdup(j_in);
context->devinfo[i]->devid = (cubeb_devid) context->devinfo[i]->device_id;
context->devinfo[i]->friendly_name = strdup(j_in);
context->devinfo[i]->group_id = strdup(j_in);
context->devinfo[i]->vendor_name = strdup(j_in);
context->devinfo[i]->type = CUBEB_DEVICE_TYPE_INPUT;
context->devinfo[i]->state = CUBEB_DEVICE_STATE_ENABLED;
context->devinfo[i]->preferred = CUBEB_DEVICE_PREF_ALL;
context->devinfo[i]->format = CUBEB_DEVICE_FMT_F32NE;
context->devinfo[i]->default_format = CUBEB_DEVICE_FMT_F32NE;
context->devinfo[i]->max_channels = MAX_CHANNELS;
context->devinfo[i]->min_rate = rate;
context->devinfo[i]->max_rate = rate;
context->devinfo[i]->default_rate = rate;
context->devinfo[i]->latency_lo = 0;
context->devinfo[i]->latency_hi = 0;
i++;
cubeb_device_info * cur = &devices[collection->count];
cur->device_id = strdup(j_in);
cur->devid = (cubeb_devid) cur->device_id;
cur->friendly_name = strdup(j_in);
cur->group_id = strdup(j_in);
cur->vendor_name = strdup(j_in);
cur->type = CUBEB_DEVICE_TYPE_INPUT;
cur->state = CUBEB_DEVICE_STATE_ENABLED;
cur->preferred = CUBEB_DEVICE_PREF_ALL;
cur->format = CUBEB_DEVICE_FMT_F32NE;
cur->default_format = CUBEB_DEVICE_FMT_F32NE;
cur->max_channels = MAX_CHANNELS;
cur->min_rate = rate;
cur->max_rate = rate;
cur->default_rate = rate;
cur->latency_lo = 0;
cur->latency_hi = 0;
collection->count += 1;
}
*collection = (cubeb_device_collection *)
malloc(sizeof(cubeb_device_collection) +
i * sizeof(cubeb_device_info *));
collection->device = devices;
(*collection)->count = i;
for (j = 0; j < i; j++) {
(*collection)->device[j] = context->devinfo[j];
}
return CUBEB_OK;
}

Просмотреть файл

@ -249,7 +249,10 @@ static float const DOWNMIX_MATRIX_3F2_LFE[SUPPORTED_LAYOUT_NUM][MAX_OUTPUT_CHANN
// |<-- dummy -->| |<-- dummy -->|
template<typename T>
bool
downmix_3f2(T const * const in, unsigned long inframes, T * out, cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
downmix_3f2(unsigned long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
{
if ((in_layout != CUBEB_LAYOUT_3F2 && in_layout != CUBEB_LAYOUT_3F2_LFE) ||
out_layout < CUBEB_LAYOUT_MONO || out_layout > CUBEB_LAYOUT_2F2_LFE) {
@ -271,9 +274,11 @@ downmix_3f2(T const * const in, unsigned long inframes, T * out, cubeb_channel_l
// 3F2-LFE has 6 channels: L, R, C, LFE, LS, RS, while 3F2 has only 5
// channels: L, R, C, LS, RS. Thus, we need to append 0 to LFE(index 3)
// to simulate a 3F2-LFE data when input layout is 3F2.
assert((in_layout == CUBEB_LAYOUT_3F2_LFE || k < 3) ? (i + k < in_len) : (k == 3) ? true : (i + k - 1 < in_len));
T data = (in_layout == CUBEB_LAYOUT_3F2_LFE) ? in[i + k] : (k == 3) ? 0 : in[i + ((k < 3) ? k : k - 1)];
sample += downmix_matrix[j][k] * data;
}
assert(out_index + j < out_len);
out[out_index + j] = sample;
}
#if defined(USE_AUDIOUNIT)
@ -289,7 +294,11 @@ downmix_3f2(T const * const in, unsigned long inframes, T * out, cubeb_channel_l
/* Map the audio data by channel name. */
template<class T>
bool
mix_remap(T const * const in, unsigned long inframes, T * out, cubeb_channel_layout in_layout, cubeb_channel_layout out_layout) {
mix_remap(long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
{
assert(in_layout != out_layout);
// We might overwrite the data before we copied them to the mapped index
@ -321,7 +330,9 @@ mix_remap(T const * const in, unsigned long inframes, T * out, cubeb_channel_lay
cubeb_channel channel = CHANNEL_INDEX_TO_ORDER[out_layout][j];
uint32_t channel_mask = 1 << channel;
int channel_index = CHANNEL_ORDER_TO_INDEX[in_layout][channel];
assert(out_index + j < out_len);
if (in_layout_mask & channel_mask) {
assert(i + channel_index < in_len);
assert(channel_index != -1);
out[out_index + j] = in[i + channel_index];
} else {
@ -337,7 +348,10 @@ mix_remap(T const * const in, unsigned long inframes, T * out, cubeb_channel_lay
/* Drop the extra channels beyond the provided output channels. */
template<typename T>
void
downmix_fallback(T const * const in, unsigned long inframes, T * out, unsigned int in_channels, unsigned int out_channels)
downmix_fallback(long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
unsigned int in_channels, unsigned int out_channels)
{
assert(in_channels >= out_channels);
@ -347,6 +361,7 @@ downmix_fallback(T const * const in, unsigned long inframes, T * out, unsigned i
for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += out_channels) {
for (unsigned int j = 0; j < out_channels; ++j) {
assert(i + j < in_len && out_index + j < out_len);
out[out_index + j] = in[i + j];
}
}
@ -355,7 +370,9 @@ downmix_fallback(T const * const in, unsigned long inframes, T * out, unsigned i
template<typename T>
void
cubeb_downmix(T const * const in, long inframes, T * out,
cubeb_downmix(long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
@ -375,36 +392,40 @@ cubeb_downmix(T const * const in, long inframes, T * out,
// then we use fallback downmix mechanism.
if (out_channels == CUBEB_CHANNEL_LAYOUT_MAPS[out_layout].channels &&
in_channels == CUBEB_CHANNEL_LAYOUT_MAPS[in_layout].channels) {
if (downmix_3f2(in, inframes, out, in_layout, out_layout)) {
if (downmix_3f2(inframes, in, in_len, out, out_len, in_layout, out_layout)) {
return;
}
// We only support downmix for audio 5.1 currently.
#if defined(USE_AUDIOUNIT)
// We only support downmix for audio 5.1 on OS X currently.
return;
#endif
if (mix_remap(in, inframes, out, in_layout, out_layout)) {
if (mix_remap(inframes, in, in_len, out, out_len, in_layout, out_layout)) {
return;
}
}
downmix_fallback(in, inframes, out, in_channels, out_channels);
downmix_fallback(inframes, in, in_len, out, out_len, in_channels, out_channels);
}
/* Upmix function, copies a mono channel into L and R. */
template<typename T>
void
mono_to_stereo(T const * in, long insamples, T * out, unsigned int out_channels)
mono_to_stereo(long insamples, T const * in, unsigned long in_len,
T * out, unsigned long out_len, unsigned int out_channels)
{
for (long i = 0, j = 0; i < insamples; ++i, j += out_channels) {
assert(i < in_len && j + 1 < out_len);
out[j] = out[j + 1] = in[i];
}
}
template<typename T>
void
cubeb_upmix(T const * in, long inframes, T * out,
cubeb_upmix(long inframes,
T const * const in, unsigned long in_len,
T * out, unsigned long out_len,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
@ -419,12 +440,13 @@ cubeb_upmix(T const * in, long inframes, T * out,
/* Either way, if we have 2 or more channels, the first two are L and R. */
/* If we are playing a mono stream over stereo speakers, copy the data over. */
if (in_channels == 1 && out_channels >= 2) {
mono_to_stereo(in, inframes, out, out_channels);
mono_to_stereo(inframes, in, in_len, out, out_len, out_channels);
} else {
/* Copy through. */
for (unsigned int i = 0, o = 0; i < inframes * in_channels;
i += in_channels, o += out_channels) {
for (unsigned int j = 0; j < in_channels; ++j) {
assert(i + j < in_len && o + j < out_len);
out[o + j] = in[i + j];
}
}
@ -438,6 +460,7 @@ cubeb_upmix(T const * in, long inframes, T * out,
/* Put silence in remaining channels. */
for (long i = 0, o = 0; i < inframes; ++i, o += out_channels) {
for (unsigned int j = 2; j < out_channels; ++j) {
assert(o + j < out_len);
out[o + j] = 0.0;
}
}
@ -471,7 +494,9 @@ cubeb_should_mix(cubeb_stream_params const * stream, cubeb_stream_params const *
}
struct cubeb_mixer {
virtual void mix(void * input_buffer, long frames, void * output_buffer,
virtual void mix(long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long output_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params) = 0;
virtual ~cubeb_mixer() {};
@ -484,7 +509,9 @@ struct cubeb_mixer_impl : public cubeb_mixer {
{
}
void mix(void * input_buffer, long frames, void * output_buffer,
void mix(long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long output_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
@ -497,10 +524,10 @@ struct cubeb_mixer_impl : public cubeb_mixer {
if ((direction & CUBEB_MIXER_DIRECTION_DOWNMIX) &&
cubeb_should_downmix(stream_params, mixer_params)) {
cubeb_downmix(in, frames, out, stream_params, mixer_params);
cubeb_downmix(frames, in, input_buffer_length, out, output_buffer_length, stream_params, mixer_params);
} else if ((direction & CUBEB_MIXER_DIRECTION_UPMIX) &&
cubeb_should_upmix(stream_params, mixer_params)) {
cubeb_upmix(in, frames, out, stream_params, mixer_params);
cubeb_upmix(frames, in, input_buffer_length, out, output_buffer_length, stream_params, mixer_params);
}
}
@ -530,11 +557,13 @@ void cubeb_mixer_destroy(cubeb_mixer * mixer)
delete mixer;
}
void cubeb_mixer_mix(cubeb_mixer * mixer,
void * const input_buffer, long frames, void * output_buffer,
void cubeb_mixer_mix(cubeb_mixer * mixer, long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long outputput_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
assert(mixer);
mixer->mix(input_buffer, frames, output_buffer, stream_params, mixer_params);
mixer->mix(frames, input_buffer, input_buffer_length, output_buffer, outputput_buffer_length,
stream_params, mixer_params);
}

Просмотреть файл

@ -77,8 +77,9 @@ typedef struct cubeb_mixer cubeb_mixer;
cubeb_mixer * cubeb_mixer_create(cubeb_sample_format format,
unsigned char direction);
void cubeb_mixer_destroy(cubeb_mixer * mixer);
void cubeb_mixer_mix(cubeb_mixer * mixer,
void * input_buffer, long frames, void * output_buffer,
void cubeb_mixer_mix(cubeb_mixer * mixer, long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long outputput_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params);

Просмотреть файл

@ -1148,7 +1148,7 @@ typedef struct {
char * default_sink_name;
char * default_source_name;
cubeb_device_info ** devinfo;
cubeb_device_info * devinfo;
uint32_t max;
uint32_t count;
cubeb * context;
@ -1177,7 +1177,7 @@ pulse_ensure_dev_list_data_list_size (pulse_dev_list_data * list_data)
if (list_data->count == list_data->max) {
list_data->max += 8;
list_data->devinfo = realloc(list_data->devinfo,
sizeof(cubeb_device_info *) * list_data->max);
sizeof(cubeb_device_info) * list_data->max);
}
}
@ -1209,7 +1209,9 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
if (eol || info == NULL)
return;
devinfo = calloc(1, sizeof(cubeb_device_info));
pulse_ensure_dev_list_data_list_size(list_data);
devinfo = &list_data->devinfo[list_data->count];
memset(devinfo, 0, sizeof(cubeb_device_info));
devinfo->device_id = strdup(info->name);
devinfo->devid = (cubeb_devid) devinfo->device_id;
@ -1224,7 +1226,7 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
devinfo->type = CUBEB_DEVICE_TYPE_OUTPUT;
devinfo->state = pulse_get_state_from_sink_port(info->active_port);
devinfo->preferred = (strcmp(info->name, list_data->default_sink_name) == 0) ?
CUBEB_DEVICE_PREF_ALL : CUBEB_DEVICE_PREF_NONE;
CUBEB_DEVICE_PREF_ALL : CUBEB_DEVICE_PREF_NONE;
devinfo->format = CUBEB_DEVICE_FMT_ALL;
devinfo->default_format = pulse_format_to_cubeb_format(info->sample_spec.format);
@ -1236,8 +1238,7 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
devinfo->latency_lo = 0;
devinfo->latency_hi = 0;
pulse_ensure_dev_list_data_list_size (list_data);
list_data->devinfo[list_data->count++] = devinfo;
list_data->count += 1;
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
}
@ -1270,7 +1271,9 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info,
if (eol)
return;
devinfo = calloc(1, sizeof(cubeb_device_info));
pulse_ensure_dev_list_data_list_size(list_data);
devinfo = &list_data->devinfo[list_data->count];
memset(devinfo, 0, sizeof(cubeb_device_info));
devinfo->device_id = strdup(info->name);
devinfo->devid = (cubeb_devid) devinfo->device_id;
@ -1285,7 +1288,7 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info,
devinfo->type = CUBEB_DEVICE_TYPE_INPUT;
devinfo->state = pulse_get_state_from_source_port(info->active_port);
devinfo->preferred = (strcmp(info->name, list_data->default_source_name) == 0) ?
CUBEB_DEVICE_PREF_ALL : CUBEB_DEVICE_PREF_NONE;
CUBEB_DEVICE_PREF_ALL : CUBEB_DEVICE_PREF_NONE;
devinfo->format = CUBEB_DEVICE_FMT_ALL;
devinfo->default_format = pulse_format_to_cubeb_format(info->sample_spec.format);
@ -1297,9 +1300,7 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info,
devinfo->latency_lo = 0;
devinfo->latency_hi = 0;
pulse_ensure_dev_list_data_list_size (list_data);
list_data->devinfo[list_data->count++] = devinfo;
list_data->count += 1;
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
}
@ -1320,11 +1321,10 @@ pulse_server_info_cb(pa_context * c, const pa_server_info * i, void * userdata)
static int
pulse_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_collection ** collection)
cubeb_device_collection * collection)
{
pulse_dev_list_data user_data = { NULL, NULL, NULL, 0, 0, context };
pa_operation * o;
uint32_t i;
WRAP(pa_threaded_mainloop_lock)(context->mainloop);
@ -1355,15 +1355,11 @@ pulse_enumerate_devices(cubeb * context, cubeb_device_type type,
WRAP(pa_threaded_mainloop_unlock)(context->mainloop);
*collection = malloc(sizeof(cubeb_device_collection) +
sizeof(cubeb_device_info *) * (user_data.count > 0 ? user_data.count - 1 : 0));
(*collection)->count = user_data.count;
for (i = 0; i < user_data.count; i++)
(*collection)->device[i] = user_data.devinfo[i];
collection->device = user_data.devinfo;
collection->count = user_data.count;
free(user_data.default_sink_name);
free(user_data.default_source_name);
free(user_data.devinfo);
return CUBEB_OK;
}

Просмотреть файл

@ -29,20 +29,20 @@ struct cubeb {
struct cubeb_stream {
cubeb * context;
pthread_t th; /* to run real-time audio i/o */
pthread_mutex_t mtx; /* protects hdl and pos */
struct sio_hdl *hdl; /* link us to sndio */
int active; /* cubec_start() called */
int conv; /* need float->s16 conversion */
unsigned char *buf; /* data is prepared here */
unsigned int nfr; /* number of frames in buf */
unsigned int bpf; /* bytes per frame */
unsigned int pchan; /* number of play channels */
uint64_t rdpos; /* frame number Joe hears right now */
uint64_t wrpos; /* number of written frames */
pthread_t th; /* to run real-time audio i/o */
pthread_mutex_t mtx; /* protects hdl and pos */
struct sio_hdl *hdl; /* link us to sndio */
int active; /* cubec_start() called */
int conv; /* need float->s16 conversion */
unsigned char *buf; /* data is prepared here */
unsigned int nfr; /* number of frames in buf */
unsigned int bpf; /* bytes per frame */
unsigned int pchan; /* number of play channels */
uint64_t rdpos; /* frame number Joe hears right now */
uint64_t wrpos; /* number of written frames */
cubeb_data_callback data_cb; /* cb to preapare data */
cubeb_state_callback state_cb; /* cb to notify about state changes */
void *arg; /* user arg to {data,state}_cb */
void *arg; /* user arg to {data,state}_cb */
};
static void

Просмотреть файл

@ -19,8 +19,6 @@ device_info_destroy(cubeb_device_info * info)
free((void *) info->friendly_name);
free((void *) info->group_id);
free((void *) info->vendor_name);
free(info);
}
int
@ -33,8 +31,8 @@ cubeb_utils_default_device_collection_destroy(cubeb * context,
(void) context;
for (i = 0; i < collection->count; i++)
device_info_destroy(collection->device[i]);
device_info_destroy(&collection->device[i]);
free(collection);
free(collection->device);
return CUBEB_OK;
}

Просмотреть файл

@ -558,7 +558,12 @@ refill(cubeb_stream * stm, void * input_buffer, long input_frames_count,
XASSERT(out_frames == output_frames_needed || stm->draining || !has_output(stm));
if (has_output(stm) && cubeb_should_mix(&stm->output_stream_params, &stm->output_mix_params)) {
cubeb_mixer_mix(stm->mixer.get(), dest, out_frames, output_buffer,
XASSERT(dest == stm->mix_buffer.data());
unsigned long dest_len = out_frames * stm->output_stream_params.channels;
XASSERT(dest_len <= stm->mix_buffer.size() / stm->bytes_per_sample);
unsigned long output_buffer_len = out_frames * stm->output_mix_params.channels;
cubeb_mixer_mix(stm->mixer.get(), out_frames,
dest, dest_len, output_buffer, output_buffer_len,
&stm->output_stream_params, &stm->output_mix_params);
}
@ -621,11 +626,14 @@ bool get_input_buffer(cubeb_stream * stm)
bool ok = stm->linear_input_buffer->reserve(stm->linear_input_buffer->length() +
packet_size * stm->input_stream_params.channels);
XASSERT(ok);
cubeb_mixer_mix(stm->mixer.get(), input_packet, packet_size,
stm->linear_input_buffer->end(),
unsigned long input_packet_length = packet_size * stm->input_mix_params.channels;
unsigned long linear_input_buffer_length = packet_size * stm->input_stream_params.channels;
cubeb_mixer_mix(stm->mixer.get(), packet_size,
input_packet, input_packet_length,
stm->linear_input_buffer->end(), linear_input_buffer_length,
&stm->input_mix_params,
&stm->input_stream_params);
stm->linear_input_buffer->set_length(stm->linear_input_buffer->length() + packet_size * stm->input_stream_params.channels);
stm->linear_input_buffer->set_length(stm->linear_input_buffer->length() + linear_input_buffer_length);
} else {
stm->linear_input_buffer->push(input_packet,
packet_size * stm->input_stream_params.channels);
@ -723,11 +731,11 @@ refill_callback_duplex(cubeb_stream * stm)
ALOGV("Duplex callback: input frames: %Iu, output frames: %Iu",
stm->linear_input_buffer->length(), output_frames);
input_frames, output_frames);
refill(stm,
stm->linear_input_buffer->data(),
stm->linear_input_buffer->length(),
input_frames,
output_buffer,
output_frames);
@ -745,6 +753,7 @@ bool
refill_callback_input(cubeb_stream * stm)
{
bool rv;
size_t input_frames;
XASSERT(has_input(stm) && !has_output(stm));
@ -753,16 +762,16 @@ refill_callback_input(cubeb_stream * stm)
return rv;
}
// This can happen at the very beginning of the stream.
if (!stm->linear_input_buffer->length()) {
input_frames = stm->linear_input_buffer->length() / stm->input_stream_params.channels;
if (!input_frames) {
return true;
}
ALOGV("Input callback: input frames: %Iu", stm->linear_input_buffer->length());
ALOGV("Input callback: input frames: %Iu", input_frames);
long read = refill(stm,
stm->linear_input_buffer->data(),
stm->linear_input_buffer->length(),
input_frames,
nullptr,
0);
@ -2142,13 +2151,12 @@ wasapi_is_default_device(EDataFlow flow, ERole role, LPCWSTR device_id,
return ret;
}
static cubeb_device_info *
wasapi_create_device(IMMDeviceEnumerator * enumerator, IMMDevice * dev)
static int
wasapi_create_device(cubeb_device_info * ret, IMMDeviceEnumerator * enumerator, IMMDevice * dev)
{
com_ptr<IMMEndpoint> endpoint;
com_ptr<IMMDevice> devnode;
com_ptr<IAudioClient> client;
cubeb_device_info * ret = NULL;
EDataFlow flow;
DWORD state = DEVICE_STATE_NOTPRESENT;
com_ptr<IPropertyStore> propstore;
@ -2163,24 +2171,23 @@ wasapi_create_device(IMMDeviceEnumerator * enumerator, IMMDevice * dev)
};
hr = dev->QueryInterface(IID_PPV_ARGS(endpoint.receive()));
if (FAILED(hr)) return nullptr;
if (FAILED(hr)) return CUBEB_ERROR;
hr = endpoint->GetDataFlow(&flow);
if (FAILED(hr)) return nullptr;
if (FAILED(hr)) return CUBEB_ERROR;
wchar_t * tmp = nullptr;
hr = dev->GetId(&tmp);
if (FAILED(hr)) return nullptr;
if (FAILED(hr)) return CUBEB_ERROR;
com_heap_ptr<wchar_t> device_id(tmp);
hr = dev->OpenPropertyStore(STGM_READ, propstore.receive());
if (FAILED(hr)) return nullptr;
if (FAILED(hr)) return CUBEB_ERROR;
hr = dev->GetState(&state);
if (FAILED(hr)) return nullptr;
ret = (cubeb_device_info *)calloc(1, sizeof(cubeb_device_info));
if (FAILED(hr)) return CUBEB_ERROR;
XASSERT(ret);
ret->device_id = wstr_to_utf8(device_id.get());
ret->devid = reinterpret_cast<cubeb_devid>(ret->device_id);
prop_variant namevar;
@ -2192,7 +2199,7 @@ wasapi_create_device(IMMDeviceEnumerator * enumerator, IMMDevice * dev)
if (devnode) {
com_ptr<IPropertyStore> ps;
hr = devnode->OpenPropertyStore(STGM_READ, ps.receive());
if (FAILED(hr)) return ret;
if (FAILED(hr)) return CUBEB_ERROR;
prop_variant instancevar;
hr = ps->GetValue(PKEY_Device_InstanceId, &instancevar);
@ -2253,23 +2260,20 @@ wasapi_create_device(IMMDeviceEnumerator * enumerator, IMMDevice * dev)
ret->latency_hi = 0;
}
return ret;
return CUBEB_OK;
}
static int
wasapi_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_collection ** out)
cubeb_device_collection * out)
{
auto_com com;
com_ptr<IMMDeviceEnumerator> enumerator;
com_ptr<IMMDeviceCollection> collection;
cubeb_device_info * cur;
HRESULT hr;
UINT cc, i;
EDataFlow flow;
*out = NULL;
if (!com.ok())
return CUBEB_ERROR;
@ -2296,22 +2300,26 @@ wasapi_enumerate_devices(cubeb * context, cubeb_device_type type,
LOG("IMMDeviceCollection::GetCount() failed: %lx", hr);
return CUBEB_ERROR;
}
*out = (cubeb_device_collection *) malloc(sizeof(cubeb_device_collection) +
sizeof(cubeb_device_info*) * (cc > 0 ? cc - 1 : 0));
if (!*out) {
cubeb_device_info * devices =
(cubeb_device_info *) calloc(cc, sizeof(cubeb_device_info));
if (!devices) {
return CUBEB_ERROR;
}
(*out)->count = 0;
out->count = 0;
for (i = 0; i < cc; i++) {
com_ptr<IMMDevice> dev;
hr = collection->Item(i, dev.receive());
if (FAILED(hr)) {
LOG("IMMDeviceCollection::Item(%u) failed: %lx", i-1, hr);
} else if ((cur = wasapi_create_device(enumerator.get(), dev.get())) != NULL) {
(*out)->device[(*out)->count++] = cur;
continue;
}
auto cur = &devices[out->count];
if (wasapi_create_device(cur, enumerator.get(), dev.get()) == CUBEB_OK) {
out->count += 1;
}
}
out->device = devices;
return CUBEB_OK;
}

Просмотреть файл

@ -844,15 +844,10 @@ device_id_idx(UINT devid)
return ret;
}
static cubeb_device_info *
winmm_create_device_from_outcaps2(LPWAVEOUTCAPS2A caps, UINT devid)
static void
winmm_create_device_from_outcaps2(cubeb_device_info * ret, LPWAVEOUTCAPS2A caps, UINT devid)
{
cubeb_device_info * ret;
ret = calloc(1, sizeof(cubeb_device_info));
if (!ret) {
return NULL;
}
XASSERT(ret);
ret->devid = (cubeb_devid) devid;
ret->device_id = device_id_idx(devid);
ret->friendly_name = _strdup(caps->szPname);
@ -868,22 +863,15 @@ winmm_create_device_from_outcaps2(LPWAVEOUTCAPS2A caps, UINT devid)
winmm_query_supported_formats(devid, caps->dwFormats,
&ret->format, &ret->default_format);
/* Hardcoed latency estimates... */
/* Hardcoded latency estimates... */
ret->latency_lo = 100 * ret->default_rate / 1000;
ret->latency_hi = 200 * ret->default_rate / 1000;
return ret;
}
static cubeb_device_info *
winmm_create_device_from_outcaps(LPWAVEOUTCAPSA caps, UINT devid)
static void
winmm_create_device_from_outcaps(cubeb_device_info * ret, LPWAVEOUTCAPSA caps, UINT devid)
{
cubeb_device_info * ret;
ret = calloc(1, sizeof(cubeb_device_info));
if (!ret) {
return NULL;
}
XASSERT(ret);
ret->devid = (cubeb_devid) devid;
ret->device_id = device_id_idx(devid);
ret->friendly_name = _strdup(caps->szPname);
@ -899,11 +887,9 @@ winmm_create_device_from_outcaps(LPWAVEOUTCAPSA caps, UINT devid)
winmm_query_supported_formats(devid, caps->dwFormats,
&ret->format, &ret->default_format);
/* Hardcoed latency estimates... */
/* Hardcoded latency estimates... */
ret->latency_lo = 100 * ret->default_rate / 1000;
ret->latency_hi = 200 * ret->default_rate / 1000;
return ret;
}
static cubeb_device_pref
@ -925,15 +911,10 @@ winmm_query_preferred_in_device(UINT devid)
return ret;
}
static cubeb_device_info *
winmm_create_device_from_incaps2(LPWAVEINCAPS2A caps, UINT devid)
static void
winmm_create_device_from_incaps2(cubeb_device_info * ret, LPWAVEINCAPS2A caps, UINT devid)
{
cubeb_device_info * ret;
ret = calloc(1, sizeof(cubeb_device_info));
if (!ret) {
return NULL;
}
XASSERT(ret);
ret->devid = (cubeb_devid) devid;
ret->device_id = device_id_idx(devid);
ret->friendly_name = _strdup(caps->szPname);
@ -949,22 +930,15 @@ winmm_create_device_from_incaps2(LPWAVEINCAPS2A caps, UINT devid)
winmm_query_supported_formats(devid, caps->dwFormats,
&ret->format, &ret->default_format);
/* Hardcoed latency estimates... */
/* Hardcoded latency estimates... */
ret->latency_lo = 100 * ret->default_rate / 1000;
ret->latency_hi = 200 * ret->default_rate / 1000;
return ret;
}
static cubeb_device_info *
winmm_create_device_from_incaps(LPWAVEINCAPSA caps, UINT devid)
static void
winmm_create_device_from_incaps(cubeb_device_info * ret, LPWAVEINCAPSA caps, UINT devid)
{
cubeb_device_info * ret;
ret = calloc(1, sizeof(cubeb_device_info));
if (!ret) {
return NULL;
}
XASSERT(ret);
ret->devid = (cubeb_devid) devid;
ret->device_id = device_id_idx(devid);
ret->friendly_name = _strdup(caps->szPname);
@ -980,29 +954,25 @@ winmm_create_device_from_incaps(LPWAVEINCAPSA caps, UINT devid)
winmm_query_supported_formats(devid, caps->dwFormats,
&ret->format, &ret->default_format);
/* Hardcoed latency estimates... */
/* Hardcoded latency estimates... */
ret->latency_lo = 100 * ret->default_rate / 1000;
ret->latency_hi = 200 * ret->default_rate / 1000;
return ret;
}
static int
winmm_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_collection ** collection)
cubeb_device_collection * collection)
{
UINT i, incount, outcount, total;
cubeb_device_info * cur;
cubeb_device_info * devices;
cubeb_device_info * dev;
outcount = waveOutGetNumDevs();
incount = waveInGetNumDevs();
total = outcount + incount;
if (total > 0) {
total -= 1;
}
*collection = malloc(sizeof(cubeb_device_collection) +
sizeof(cubeb_device_info*) * total);
(*collection)->count = 0;
devices = calloc(total, sizeof(cubeb_device_info));
collection->count = 0;
if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
WAVEOUTCAPSA woc;
@ -1012,12 +982,13 @@ winmm_enumerate_devices(cubeb * context, cubeb_device_type type,
ZeroMemory(&woc2, sizeof(woc2));
for (i = 0; i < outcount; i++) {
if ((waveOutGetDevCapsA(i, (LPWAVEOUTCAPSA)&woc2, sizeof(woc2)) == MMSYSERR_NOERROR &&
(cur = winmm_create_device_from_outcaps2(&woc2, i)) != NULL) ||
(waveOutGetDevCapsA(i, &woc, sizeof(woc)) == MMSYSERR_NOERROR &&
(cur = winmm_create_device_from_outcaps(&woc, i)) != NULL)
) {
(*collection)->device[(*collection)->count++] = cur;
dev = &devices[collection->count];
if (waveOutGetDevCapsA(i, (LPWAVEOUTCAPSA)&woc2, sizeof(woc2)) == MMSYSERR_NOERROR) {
winmm_create_device_from_outcaps2(dev, &woc2, i);
collection->count += 1;
} else if (waveOutGetDevCapsA(i, &woc, sizeof(woc)) == MMSYSERR_NOERROR) {
winmm_create_device_from_outcaps(dev, &woc, i);
collection->count += 1;
}
}
}
@ -1030,16 +1001,19 @@ winmm_enumerate_devices(cubeb * context, cubeb_device_type type,
ZeroMemory(&wic2, sizeof(wic2));
for (i = 0; i < incount; i++) {
if ((waveInGetDevCapsA(i, (LPWAVEINCAPSA)&wic2, sizeof(wic2)) == MMSYSERR_NOERROR &&
(cur = winmm_create_device_from_incaps2(&wic2, i)) != NULL) ||
(waveInGetDevCapsA(i, &wic, sizeof(wic)) == MMSYSERR_NOERROR &&
(cur = winmm_create_device_from_incaps(&wic, i)) != NULL)
) {
(*collection)->device[(*collection)->count++] = cur;
dev = &devices[collection->count];
if (waveInGetDevCapsA(i, (LPWAVEINCAPSA)&wic2, sizeof(wic2)) == MMSYSERR_NOERROR) {
winmm_create_device_from_incaps2(dev, &wic2, i);
collection->count += 1;
} else if (waveInGetDevCapsA(i, &wic, sizeof(wic)) == MMSYSERR_NOERROR) {
winmm_create_device_from_incaps(dev, &wic, i);
collection->count += 1;
}
}
}
collection->device = devices;
return CUBEB_OK;
}