зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1367646 - Update cubeb from upstream to 087dc94. r=kinetik
MozReview-Commit-ID: E1D2XCtugqW --HG-- extra : rebase_source : 20d630e763aa840d1a07e0edf128206dd8b679e8
This commit is contained in:
Родитель
0f2aff9431
Коммит
9224fdaf13
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче