зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1744973 - Update libcubeb to revision 773f16b7e. r=cubeb-reviewers,chunmin
Differential Revision: https://phabricator.services.mozilla.com/D133197
This commit is contained in:
Родитель
9477e32f16
Коммит
8846c0abf1
|
@ -19,5 +19,5 @@ origin:
|
|||
license: "ISC"
|
||||
|
||||
# update.sh will update this value
|
||||
release: "ef5a1ffde99fe98ba0c28dab5128476e8aa384b8 (2021-10-12 08:09:34 +1300)"
|
||||
release: "773f16b7ea308392c05be3e290163d1f636e6024-dirty (2021-12-08 11:09:25 +1300)"
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "cubeb-jni-instances.h"
|
||||
/* clang-format off */
|
||||
#include "jni.h"
|
||||
#include <assert.h>
|
||||
#include "cubeb-jni-instances.h"
|
||||
/* clang-format on */
|
||||
|
||||
#define AUDIO_STREAM_TYPE_MUSIC 3
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#ifdef DISABLE_LIBAAUDIO_DLOPEN
|
||||
#define WRAP(x) x
|
||||
#else
|
||||
#define WRAP(x) cubeb_##x
|
||||
#define WRAP(x) (*cubeb_##x)
|
||||
#define LIBAAUDIO_API_VISIT(X) \
|
||||
X(AAudio_convertResultToText) \
|
||||
X(AAudio_convertStreamStateToText) \
|
||||
|
@ -78,6 +78,7 @@
|
|||
// X(AAudioStream_getContentType) \
|
||||
// X(AAudioStream_getInputPreset) \
|
||||
// X(AAudioStream_getSessionId) \
|
||||
// END: not needed or added later on
|
||||
|
||||
#define MAKE_TYPEDEF(x) static decltype(x) * cubeb_##x;
|
||||
LIBAAUDIO_API_VISIT(MAKE_TYPEDEF)
|
||||
|
@ -1475,7 +1476,7 @@ aaudio_init(cubeb ** context, char const * /* context_name */)
|
|||
|
||||
#define LOAD(x) \
|
||||
{ \
|
||||
WRAP(x) = (decltype(WRAP(x)))(dlsym(libaaudio, #x)); \
|
||||
cubeb_##x = (decltype(x) *)(dlsym(libaaudio, #x)); \
|
||||
if (!WRAP(x)) { \
|
||||
LOG("AAudio: Failed to load %s", #x); \
|
||||
dlclose(libaaudio); \
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#ifdef DISABLE_LIBASOUND_DLOPEN
|
||||
#define WRAP(x) x
|
||||
#else
|
||||
#define WRAP(x) cubeb_##x
|
||||
#define WRAP(x) (*cubeb_##x)
|
||||
#define LIBASOUND_API_VISIT(X) \
|
||||
X(snd_config) \
|
||||
X(snd_config_add) \
|
||||
|
@ -660,11 +660,11 @@ init_local_config_with_workaround(char const * pcm_name)
|
|||
|
||||
lconf = NULL;
|
||||
|
||||
if (*WRAP(snd_config) == NULL) {
|
||||
if (WRAP(snd_config) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = WRAP(snd_config_copy)(&lconf, *WRAP(snd_config));
|
||||
r = WRAP(snd_config_copy)(&lconf, WRAP(snd_config));
|
||||
if (r < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
#include <jack/jack.h>
|
||||
#include <jack/statistics.h>
|
||||
|
||||
#ifdef DISABLE_LIBJACK_DLOPEN
|
||||
#define WRAP(x) x
|
||||
#else
|
||||
#define WRAP(x) (*api_##x)
|
||||
#define JACK_API_VISIT(X) \
|
||||
X(jack_activate) \
|
||||
X(jack_client_close) \
|
||||
|
@ -49,6 +53,8 @@
|
|||
|
||||
#define IMPORT_FUNC(x) static decltype(x) * api_##x;
|
||||
JACK_API_VISIT(IMPORT_FUNC);
|
||||
#undef IMPORT_FUNC
|
||||
#endif
|
||||
|
||||
#define JACK_DEFAULT_IN "JACK capture"
|
||||
#define JACK_DEFAULT_OUT "JACK playback"
|
||||
|
@ -235,6 +241,7 @@ struct cubeb {
|
|||
static int
|
||||
load_jack_lib(cubeb * context)
|
||||
{
|
||||
#ifndef DISABLE_LIBJACK_DLOPEN
|
||||
#ifdef __APPLE__
|
||||
context->libjack = dlopen("libjack.0.dylib", RTLD_LAZY);
|
||||
context->libjack = dlopen("/usr/local/lib/libjack.0.dylib", RTLD_LAZY);
|
||||
|
@ -265,7 +272,7 @@ load_jack_lib(cubeb * context)
|
|||
|
||||
JACK_API_VISIT(LOAD);
|
||||
#undef LOAD
|
||||
|
||||
#endif
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
|
@ -273,18 +280,18 @@ static void
|
|||
cbjack_connect_port_out(cubeb_stream * stream, const size_t out_port,
|
||||
const char * const phys_in_port)
|
||||
{
|
||||
const char * src_port = api_jack_port_name(stream->output_ports[out_port]);
|
||||
const char * src_port = WRAP(jack_port_name)(stream->output_ports[out_port]);
|
||||
|
||||
api_jack_connect(stream->context->jack_client, src_port, phys_in_port);
|
||||
WRAP(jack_connect)(stream->context->jack_client, src_port, phys_in_port);
|
||||
}
|
||||
|
||||
static void
|
||||
cbjack_connect_port_in(cubeb_stream * stream, const char * const phys_out_port,
|
||||
size_t in_port)
|
||||
{
|
||||
const char * src_port = api_jack_port_name(stream->input_ports[in_port]);
|
||||
const char * src_port = WRAP(jack_port_name)(stream->input_ports[in_port]);
|
||||
|
||||
api_jack_connect(stream->context->jack_client, phys_out_port, src_port);
|
||||
WRAP(jack_connect)(stream->context->jack_client, phys_out_port, src_port);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -293,11 +300,11 @@ cbjack_connect_ports(cubeb_stream * stream,
|
|||
{
|
||||
int r = CUBEB_ERROR;
|
||||
const char ** phys_in_ports =
|
||||
api_jack_get_ports(stream->context->jack_client, NULL, NULL,
|
||||
JackPortIsInput | JackPortIsPhysical);
|
||||
WRAP(jack_get_ports)(stream->context->jack_client, NULL, NULL,
|
||||
JackPortIsInput | JackPortIsPhysical);
|
||||
const char ** phys_out_ports =
|
||||
api_jack_get_ports(stream->context->jack_client, NULL, NULL,
|
||||
JackPortIsOutput | JackPortIsPhysical);
|
||||
WRAP(jack_get_ports)(stream->context->jack_client, NULL, NULL,
|
||||
JackPortIsOutput | JackPortIsPhysical);
|
||||
|
||||
if (phys_in_ports == NULL || *phys_in_ports == NULL ||
|
||||
options & CBJACK_CP_OPTIONS_SKIP_OUTPUT) {
|
||||
|
@ -330,10 +337,10 @@ skipplayback:
|
|||
r = CUBEB_OK;
|
||||
end:
|
||||
if (phys_out_ports) {
|
||||
api_jack_free(phys_out_ports);
|
||||
WRAP(jack_free)(phys_out_ports);
|
||||
}
|
||||
if (phys_in_ports) {
|
||||
api_jack_free(phys_in_ports);
|
||||
WRAP(jack_free)(phys_in_ports);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -343,7 +350,7 @@ cbjack_xrun_callback(void * arg)
|
|||
{
|
||||
cubeb * ctx = (cubeb *)arg;
|
||||
|
||||
float delay = api_jack_get_xrun_delayed_usecs(ctx->jack_client);
|
||||
float delay = WRAP(jack_get_xrun_delayed_usecs)(ctx->jack_client);
|
||||
float fragments = ceilf(((delay / 1000000.0) * ctx->jack_sample_rate) /
|
||||
ctx->jack_buffer_size);
|
||||
|
||||
|
@ -368,8 +375,8 @@ cbjack_graph_order_callback(void * arg)
|
|||
continue;
|
||||
|
||||
for (i = 0; i < (int)stm->out_params.channels; ++i) {
|
||||
api_jack_port_get_latency_range(stm->output_ports[i], JackPlaybackLatency,
|
||||
&latency_range);
|
||||
WRAP(jack_port_get_latency_range)
|
||||
(stm->output_ports[i], JackPlaybackLatency, &latency_range);
|
||||
port_latency = latency_range.max;
|
||||
if (port_latency > max_latency)
|
||||
max_latency = port_latency;
|
||||
|
@ -411,13 +418,13 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
|||
// get jack output buffers
|
||||
for (i = 0; i < (int)stm->out_params.channels; i++)
|
||||
bufs_out[i] =
|
||||
(float *)api_jack_port_get_buffer(stm->output_ports[i], nframes);
|
||||
(float *)WRAP(jack_port_get_buffer)(stm->output_ports[i], nframes);
|
||||
}
|
||||
if (stm->devs & IN_ONLY) {
|
||||
// get jack input buffers
|
||||
for (i = 0; i < (int)stm->in_params.channels; i++)
|
||||
bufs_in[i] =
|
||||
(float *)api_jack_port_get_buffer(stm->input_ports[i], nframes);
|
||||
(float *)WRAP(jack_port_get_buffer)(stm->input_ports[i], nframes);
|
||||
}
|
||||
if (stm->pause) {
|
||||
// paused, play silence on output
|
||||
|
@ -684,8 +691,8 @@ jack_init(cubeb ** context, char const * context_name)
|
|||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
api_jack_set_error_function(silent_jack_error_callback);
|
||||
api_jack_set_info_function(silent_jack_error_callback);
|
||||
WRAP(jack_set_error_function)(silent_jack_error_callback);
|
||||
WRAP(jack_set_info_function)(silent_jack_error_callback);
|
||||
|
||||
ctx->ops = &cbjack_ops;
|
||||
|
||||
|
@ -699,7 +706,7 @@ jack_init(cubeb ** context, char const * context_name)
|
|||
jack_client_name = context_name;
|
||||
|
||||
ctx->jack_client =
|
||||
api_jack_client_open(jack_client_name, JackNoStartServer, NULL);
|
||||
WRAP(jack_client_open)(jack_client_name, JackNoStartServer, NULL);
|
||||
|
||||
if (ctx->jack_client == NULL) {
|
||||
cbjack_destroy(ctx);
|
||||
|
@ -708,17 +715,17 @@ jack_init(cubeb ** context, char const * context_name)
|
|||
|
||||
ctx->jack_xruns = 0;
|
||||
|
||||
api_jack_set_process_callback(ctx->jack_client, cbjack_process, ctx);
|
||||
api_jack_set_xrun_callback(ctx->jack_client, cbjack_xrun_callback, ctx);
|
||||
api_jack_set_graph_order_callback(ctx->jack_client,
|
||||
cbjack_graph_order_callback, ctx);
|
||||
WRAP(jack_set_process_callback)(ctx->jack_client, cbjack_process, ctx);
|
||||
WRAP(jack_set_xrun_callback)(ctx->jack_client, cbjack_xrun_callback, ctx);
|
||||
WRAP(jack_set_graph_order_callback)
|
||||
(ctx->jack_client, cbjack_graph_order_callback, ctx);
|
||||
|
||||
if (api_jack_activate(ctx->jack_client)) {
|
||||
if (WRAP(jack_activate)(ctx->jack_client)) {
|
||||
cbjack_destroy(ctx);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
ctx->jack_sample_rate = api_jack_get_sample_rate(ctx->jack_client);
|
||||
ctx->jack_sample_rate = WRAP(jack_get_sample_rate)(ctx->jack_client);
|
||||
ctx->jack_latency = 128 * 1000 / ctx->jack_sample_rate;
|
||||
|
||||
ctx->active = true;
|
||||
|
@ -760,16 +767,16 @@ cbjack_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
|
|||
{
|
||||
if (!ctx->jack_client) {
|
||||
jack_client_t * testclient =
|
||||
api_jack_client_open("test-samplerate", JackNoStartServer, NULL);
|
||||
WRAP(jack_client_open)("test-samplerate", JackNoStartServer, NULL);
|
||||
if (!testclient) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
*rate = api_jack_get_sample_rate(testclient);
|
||||
api_jack_client_close(testclient);
|
||||
*rate = WRAP(jack_get_sample_rate)(testclient);
|
||||
WRAP(jack_client_close)(testclient);
|
||||
|
||||
} else {
|
||||
*rate = api_jack_get_sample_rate(ctx->jack_client);
|
||||
*rate = WRAP(jack_get_sample_rate)(ctx->jack_client);
|
||||
}
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
@ -780,7 +787,7 @@ cbjack_destroy(cubeb * context)
|
|||
context->active = false;
|
||||
|
||||
if (context->jack_client != NULL)
|
||||
api_jack_client_close(context->jack_client);
|
||||
WRAP(jack_client_close)(context->jack_client);
|
||||
|
||||
if (context->libjack)
|
||||
dlclose(context->libjack);
|
||||
|
@ -813,7 +820,7 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
cubeb_state_callback state_callback, void * user_ptr)
|
||||
{
|
||||
int stream_actual_rate = 0;
|
||||
int jack_rate = api_jack_get_sample_rate(context->jack_client);
|
||||
int jack_rate = WRAP(jack_get_sample_rate)(context->jack_client);
|
||||
|
||||
if (output_stream_params &&
|
||||
(output_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
|
||||
|
@ -905,7 +912,7 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
stm->state_callback = state_callback;
|
||||
stm->position = 0;
|
||||
stm->volume = 1.0f;
|
||||
context->jack_buffer_size = api_jack_get_buffer_size(context->jack_client);
|
||||
context->jack_buffer_size = WRAP(jack_get_buffer_size)(context->jack_client);
|
||||
context->fragment_size = context->jack_buffer_size;
|
||||
|
||||
if (stm->devs == NONE) {
|
||||
|
@ -939,9 +946,9 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
for (unsigned int c = 0; c < stm->out_params.channels; c++) {
|
||||
char portname[256];
|
||||
snprintf(portname, 255, "%s_out_%d", stm->stream_name, c);
|
||||
stm->output_ports[c] =
|
||||
api_jack_port_register(stm->context->jack_client, portname,
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
||||
stm->output_ports[c] = WRAP(jack_port_register)(
|
||||
stm->context->jack_client, portname, JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
if (!(output_stream_params->prefs &
|
||||
CUBEB_STREAM_PREF_JACK_NO_AUTO_CONNECT)) {
|
||||
if (cbjack_connect_ports(stm, CBJACK_CP_OPTIONS_SKIP_INPUT) !=
|
||||
|
@ -959,8 +966,8 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
char portname[256];
|
||||
snprintf(portname, 255, "%s_in_%d", stm->stream_name, c);
|
||||
stm->input_ports[c] =
|
||||
api_jack_port_register(stm->context->jack_client, portname,
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
|
||||
WRAP(jack_port_register)(stm->context->jack_client, portname,
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
|
||||
if (!(input_stream_params->prefs &
|
||||
CUBEB_STREAM_PREF_JACK_NO_AUTO_CONNECT)) {
|
||||
if (cbjack_connect_ports(stm, CBJACK_CP_OPTIONS_SKIP_OUTPUT) !=
|
||||
|
@ -991,8 +998,8 @@ cbjack_stream_destroy(cubeb_stream * stream)
|
|||
if (stream->devs == DUPLEX || stream->devs == OUT_ONLY) {
|
||||
for (unsigned int c = 0; c < stream->out_params.channels; c++) {
|
||||
if (stream->output_ports[c]) {
|
||||
api_jack_port_unregister(stream->context->jack_client,
|
||||
stream->output_ports[c]);
|
||||
WRAP(jack_port_unregister)
|
||||
(stream->context->jack_client, stream->output_ports[c]);
|
||||
stream->output_ports[c] = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1001,8 +1008,8 @@ cbjack_stream_destroy(cubeb_stream * stream)
|
|||
if (stream->devs == DUPLEX || stream->devs == IN_ONLY) {
|
||||
for (unsigned int c = 0; c < stream->in_params.channels; c++) {
|
||||
if (stream->input_ports[c]) {
|
||||
api_jack_port_unregister(stream->context->jack_client,
|
||||
stream->input_ports[c]);
|
||||
WRAP(jack_port_unregister)
|
||||
(stream->context->jack_client, stream->input_ports[c]);
|
||||
stream->input_ports[c] = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -410,9 +410,8 @@ sum2(TYPE_SAMPLE * out, uint32_t stride_out, const TYPE_SAMPLE * in1,
|
|||
TYPE_COEFF coeff2, F && operand, uint32_t frames)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<TYPE_COEFF,
|
||||
typename std::result_of<F(TYPE_COEFF)>::type>::value,
|
||||
"function must return the same type as used by matrix_coeff");
|
||||
std::is_same<TYPE_COEFF, decltype(operand(coeff1))>::value,
|
||||
"function must return the same type as used by coeff1 and coeff2");
|
||||
for (uint32_t i = 0; i < frames; i++) {
|
||||
*out = operand(coeff1 * *in1 + coeff2 * *in2);
|
||||
out += stride_out;
|
||||
|
@ -426,10 +425,8 @@ void
|
|||
copy(TYPE_SAMPLE * out, uint32_t stride_out, const TYPE_SAMPLE * in,
|
||||
uint32_t stride_in, TYPE_COEFF coeff, F && operand, uint32_t frames)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<TYPE_COEFF,
|
||||
typename std::result_of<F(TYPE_COEFF)>::type>::value,
|
||||
"function must return the same type as used by matrix_coeff");
|
||||
static_assert(std::is_same<TYPE_COEFF, decltype(operand(coeff))>::value,
|
||||
"function must return the same type as used by coeff");
|
||||
for (uint32_t i = 0; i < frames; i++) {
|
||||
*out = operand(coeff * *in);
|
||||
out += stride_out;
|
||||
|
@ -443,8 +440,7 @@ rematrix(const MixerContext * s, TYPE * aOut, const TYPE * aIn,
|
|||
const TYPE_COEFF (&matrix_coeff)[COLS][COLS], F && aF, uint32_t frames)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<TYPE_COEFF,
|
||||
typename std::result_of<F(TYPE_COEFF)>::type>::value,
|
||||
std::is_same<TYPE_COEFF, decltype(aF(matrix_coeff[0][0]))>::value,
|
||||
"function must return the same type as used by matrix_coeff");
|
||||
|
||||
for (uint32_t out_i = 0; out_i < s->_out_ch_count; out_i++) {
|
||||
|
|
|
@ -96,6 +96,7 @@ struct oss_stream {
|
|||
oss_devnode_t name;
|
||||
int fd;
|
||||
void * buf;
|
||||
unsigned int bufframes;
|
||||
|
||||
struct stream_info {
|
||||
int channels;
|
||||
|
@ -126,9 +127,6 @@ struct cubeb_stream {
|
|||
cubeb_data_callback data_cb;
|
||||
cubeb_state_callback state_cb;
|
||||
uint64_t frames_written /* (m) */;
|
||||
unsigned int nfr; /* Number of frames allocated */
|
||||
unsigned int nfrags;
|
||||
unsigned int bufframes;
|
||||
};
|
||||
|
||||
static char const *
|
||||
|
@ -786,40 +784,72 @@ oss_put_play_frames(cubeb_stream * s, unsigned int nframes)
|
|||
}
|
||||
|
||||
static int
|
||||
oss_wait_playfd_for_space(cubeb_stream * s)
|
||||
oss_wait_fds_for_space(cubeb_stream * s, long * nfrp)
|
||||
{
|
||||
struct pollfd pfd;
|
||||
audio_buf_info bi;
|
||||
struct pollfd pfds[2];
|
||||
long nfr, tnfr;
|
||||
int i;
|
||||
|
||||
pfd.events = POLLOUT | POLLHUP;
|
||||
pfd.revents = 0;
|
||||
pfd.fd = s->play.fd;
|
||||
assert(s->play.fd != -1 || s->record.fd != -1);
|
||||
pfds[0].events = POLLOUT | POLLHUP;
|
||||
pfds[0].revents = 0;
|
||||
pfds[0].fd = s->play.fd;
|
||||
pfds[1].events = POLLIN | POLLHUP;
|
||||
pfds[1].revents = 0;
|
||||
pfds[1].fd = s->record.fd;
|
||||
|
||||
if (poll(&pfd, 1, 2000) == -1) {
|
||||
retry:
|
||||
nfr = LONG_MAX;
|
||||
|
||||
if (poll(pfds, 2, 1000) == -1) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
if (pfd.revents & POLLHUP) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
oss_wait_recfd_for_space(cubeb_stream * s)
|
||||
{
|
||||
struct pollfd pfd;
|
||||
|
||||
pfd.events = POLLIN | POLLHUP;
|
||||
pfd.revents = 0;
|
||||
pfd.fd = s->record.fd;
|
||||
|
||||
if (poll(&pfd, 1, 2000) == -1) {
|
||||
return CUBEB_ERROR;
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (pfds[i].revents & POLLHUP) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (pfd.revents & POLLHUP) {
|
||||
return CUBEB_ERROR;
|
||||
if (s->play.fd != -1) {
|
||||
if (ioctl(s->play.fd, SNDCTL_DSP_GETOSPACE, &bi) == -1) {
|
||||
return CUBEB_STATE_ERROR;
|
||||
}
|
||||
tnfr = bi.bytes / s->play.frame_size;
|
||||
if (tnfr <= 0) {
|
||||
/* too little space - stop polling record, if any */
|
||||
pfds[0].fd = s->play.fd;
|
||||
pfds[1].fd = -1;
|
||||
goto retry;
|
||||
} else if (tnfr > (long)s->play.bufframes) {
|
||||
/* too many frames available - limit */
|
||||
tnfr = (long)s->play.bufframes;
|
||||
}
|
||||
if (nfr > tnfr) {
|
||||
nfr = tnfr;
|
||||
}
|
||||
}
|
||||
if (s->record.fd != -1) {
|
||||
if (ioctl(s->record.fd, SNDCTL_DSP_GETISPACE, &bi) == -1) {
|
||||
return CUBEB_STATE_ERROR;
|
||||
}
|
||||
tnfr = bi.bytes / s->record.frame_size;
|
||||
if (tnfr <= 0) {
|
||||
/* too little space - stop polling playback, if any */
|
||||
pfds[0].fd = -1;
|
||||
pfds[1].fd = s->record.fd;
|
||||
goto retry;
|
||||
} else if (tnfr > (long)s->record.bufframes) {
|
||||
/* too many frames available - limit */
|
||||
tnfr = (long)s->record.bufframes;
|
||||
}
|
||||
if (nfr > tnfr) {
|
||||
nfr = tnfr;
|
||||
}
|
||||
}
|
||||
|
||||
*nfrp = nfr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -840,7 +870,7 @@ oss_audio_loop(cubeb_stream * s, cubeb_state * new_state)
|
|||
}
|
||||
|
||||
trig |= PCM_ENABLE_INPUT;
|
||||
memset(s->record.buf, 0, s->bufframes * s->record.frame_size);
|
||||
memset(s->record.buf, 0, s->record.bufframes * s->record.frame_size);
|
||||
|
||||
if (ioctl(s->record.fd, SNDCTL_DSP_SETTRIGGER, &trig) == -1) {
|
||||
LOG("Error %d occured when setting trigger on record fd", errno);
|
||||
|
@ -877,6 +907,7 @@ oss_audio_loop(cubeb_stream * s, cubeb_state * new_state)
|
|||
oss_linear32_to_float(s->record.buf, s->record.info.channels * nfr);
|
||||
}
|
||||
}
|
||||
|
||||
got = s->data_cb(s, s->user_ptr, s->record.buf, s->play.buf, nfr);
|
||||
if (got == CUBEB_ERROR) {
|
||||
state = CUBEB_STATE_ERROR;
|
||||
|
@ -920,44 +951,9 @@ oss_audio_loop(cubeb_stream * s, cubeb_state * new_state)
|
|||
}
|
||||
}
|
||||
|
||||
nfr = s->bufframes;
|
||||
|
||||
if (record_on) {
|
||||
long mfr;
|
||||
|
||||
if (oss_wait_recfd_for_space(s) != 0) {
|
||||
state = CUBEB_STATE_ERROR;
|
||||
goto breakdown;
|
||||
}
|
||||
|
||||
audio_buf_info bi;
|
||||
if (ioctl(s->record.fd, SNDCTL_DSP_GETISPACE, &bi) == -1) {
|
||||
state = CUBEB_STATE_ERROR;
|
||||
goto breakdown;
|
||||
}
|
||||
|
||||
mfr = (bi.fragsize * bi.fragments) / s->record.frame_size;
|
||||
if (nfr > mfr)
|
||||
nfr = mfr;
|
||||
}
|
||||
|
||||
if (play_on) {
|
||||
long mfr;
|
||||
|
||||
if (oss_wait_playfd_for_space(s) != 0) {
|
||||
state = CUBEB_STATE_ERROR;
|
||||
goto breakdown;
|
||||
}
|
||||
|
||||
audio_buf_info bi;
|
||||
if (ioctl(s->play.fd, SNDCTL_DSP_GETOSPACE, &bi) == -1) {
|
||||
state = CUBEB_STATE_ERROR;
|
||||
goto breakdown;
|
||||
}
|
||||
|
||||
mfr = (bi.fragsize * bi.fragments) / s->play.frame_size;
|
||||
if (nfr > mfr)
|
||||
nfr = mfr;
|
||||
if (oss_wait_fds_for_space(s, &nfr) != 0) {
|
||||
state = CUBEB_STATE_ERROR;
|
||||
goto breakdown;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1015,9 +1011,10 @@ static inline int
|
|||
oss_calc_frag_shift(unsigned int frames, unsigned int frame_size)
|
||||
{
|
||||
int n = 4;
|
||||
int blksize = (frames * frame_size + OSS_NFRAGS - 1) / OSS_NFRAGS;
|
||||
while ((1 << n) < blksize)
|
||||
int blksize = frames * frame_size;
|
||||
while ((1 << n) < blksize) {
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -1037,7 +1034,6 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
cubeb_state_callback state_callback, void * user_ptr)
|
||||
{
|
||||
int ret = CUBEB_OK;
|
||||
unsigned int playnfr = 0, recnfr = 0;
|
||||
cubeb_stream * s = NULL;
|
||||
const char * defdsp;
|
||||
|
||||
|
@ -1051,7 +1047,6 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
}
|
||||
s->state = CUBEB_STATE_STOPPED;
|
||||
s->record.fd = s->play.fd = -1;
|
||||
s->nfr = latency_frames;
|
||||
if (input_device != NULL) {
|
||||
strlcpy(s->record.name, input_device, sizeof(s->record.name));
|
||||
} else {
|
||||
|
@ -1064,6 +1059,8 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
}
|
||||
if (input_stream_params != NULL) {
|
||||
unsigned int nb_channels;
|
||||
uint32_t minframes;
|
||||
|
||||
if (input_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) {
|
||||
LOG("Loopback not supported");
|
||||
ret = CUBEB_ERROR_NOT_SUPPORTED;
|
||||
|
@ -1077,13 +1074,11 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
ret = CUBEB_ERROR_INVALID_PARAMETER;
|
||||
goto error;
|
||||
}
|
||||
if (s->record.fd == -1) {
|
||||
if ((s->record.fd = open(s->record.name, O_RDONLY)) == -1) {
|
||||
LOG("Audio device \"%s\" could not be opened as read-only",
|
||||
s->record.name);
|
||||
ret = CUBEB_ERROR_DEVICE_UNAVAILABLE;
|
||||
goto error;
|
||||
}
|
||||
if ((s->record.fd = open(s->record.name, O_RDONLY)) == -1) {
|
||||
LOG("Audio device \"%s\" could not be opened as read-only",
|
||||
s->record.name);
|
||||
ret = CUBEB_ERROR_DEVICE_UNAVAILABLE;
|
||||
goto error;
|
||||
}
|
||||
if ((ret = oss_copy_params(s->record.fd, s, input_stream_params,
|
||||
&s->record.info)) != CUBEB_OK) {
|
||||
|
@ -1094,11 +1089,17 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
(input_stream_params->format == CUBEB_SAMPLE_FLOAT32NE);
|
||||
s->record.frame_size =
|
||||
s->record.info.channels * (s->record.info.precision / 8);
|
||||
recnfr = (1 << oss_calc_frag_shift(s->nfr, s->record.frame_size)) /
|
||||
s->record.frame_size;
|
||||
s->record.bufframes = latency_frames;
|
||||
|
||||
oss_get_min_latency(context, *input_stream_params, &minframes);
|
||||
if (s->record.bufframes < minframes) {
|
||||
s->record.bufframes = minframes;
|
||||
}
|
||||
}
|
||||
if (output_stream_params != NULL) {
|
||||
unsigned int nb_channels;
|
||||
uint32_t minframes;
|
||||
|
||||
if (output_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) {
|
||||
LOG("Loopback not supported");
|
||||
ret = CUBEB_ERROR_NOT_SUPPORTED;
|
||||
|
@ -1113,13 +1114,11 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
ret = CUBEB_ERROR_INVALID_PARAMETER;
|
||||
goto error;
|
||||
}
|
||||
if (s->play.fd == -1) {
|
||||
if ((s->play.fd = open(s->play.name, O_WRONLY)) == -1) {
|
||||
LOG("Audio device \"%s\" could not be opened as write-only",
|
||||
s->play.name);
|
||||
ret = CUBEB_ERROR_DEVICE_UNAVAILABLE;
|
||||
goto error;
|
||||
}
|
||||
if ((s->play.fd = open(s->play.name, O_WRONLY)) == -1) {
|
||||
LOG("Audio device \"%s\" could not be opened as write-only",
|
||||
s->play.name);
|
||||
ret = CUBEB_ERROR_DEVICE_UNAVAILABLE;
|
||||
goto error;
|
||||
}
|
||||
if ((ret = oss_copy_params(s->play.fd, s, output_stream_params,
|
||||
&s->play.info)) != CUBEB_OK) {
|
||||
|
@ -1128,19 +1127,16 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
}
|
||||
s->play.floating = (output_stream_params->format == CUBEB_SAMPLE_FLOAT32NE);
|
||||
s->play.frame_size = s->play.info.channels * (s->play.info.precision / 8);
|
||||
playnfr = (1 << oss_calc_frag_shift(s->nfr, s->play.frame_size)) /
|
||||
s->play.frame_size;
|
||||
s->play.bufframes = latency_frames;
|
||||
|
||||
oss_get_min_latency(context, *output_stream_params, &minframes);
|
||||
if (s->play.bufframes < minframes) {
|
||||
s->play.bufframes = minframes;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Use the largest nframes among playing and recording streams to set OSS
|
||||
* buffer size. After that, use the smallest allocated nframes among both
|
||||
* direction to allocate our temporary buffers.
|
||||
*/
|
||||
s->nfr = (playnfr > recnfr) ? playnfr : recnfr;
|
||||
s->nfrags = OSS_NFRAGS;
|
||||
if (s->play.fd != -1) {
|
||||
int frag =
|
||||
oss_get_frag_params(oss_calc_frag_shift(s->nfr, s->play.frame_size));
|
||||
int frag = oss_get_frag_params(
|
||||
oss_calc_frag_shift(s->play.bufframes, s->play.frame_size));
|
||||
if (ioctl(s->play.fd, SNDCTL_DSP_SETFRAGMENT, &frag))
|
||||
LOG("Failed to set play fd with SNDCTL_DSP_SETFRAGMENT. frag: 0x%x",
|
||||
frag);
|
||||
|
@ -1148,13 +1144,17 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
if (ioctl(s->play.fd, SNDCTL_DSP_GETOSPACE, &bi))
|
||||
LOG("Failed to get play fd's buffer info.");
|
||||
else {
|
||||
if (bi.fragsize / s->play.frame_size < s->nfr)
|
||||
s->nfr = bi.fragsize / s->play.frame_size;
|
||||
s->play.bufframes = (bi.fragsize * bi.fragstotal) / s->play.frame_size;
|
||||
}
|
||||
|
||||
int lw = s->play.frame_size;
|
||||
if (ioctl(s->play.fd, SNDCTL_DSP_LOW_WATER, &lw))
|
||||
LOG("Audio device \"%s\" (play) could not set trigger threshold",
|
||||
s->play.name);
|
||||
}
|
||||
if (s->record.fd != -1) {
|
||||
int frag =
|
||||
oss_get_frag_params(oss_calc_frag_shift(s->nfr, s->record.frame_size));
|
||||
int frag = oss_get_frag_params(
|
||||
oss_calc_frag_shift(s->record.bufframes, s->record.frame_size));
|
||||
if (ioctl(s->record.fd, SNDCTL_DSP_SETFRAGMENT, &frag))
|
||||
LOG("Failed to set record fd with SNDCTL_DSP_SETFRAGMENT. frag: 0x%x",
|
||||
frag);
|
||||
|
@ -1162,11 +1162,15 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
if (ioctl(s->record.fd, SNDCTL_DSP_GETISPACE, &bi))
|
||||
LOG("Failed to get record fd's buffer info.");
|
||||
else {
|
||||
if (bi.fragsize / s->record.frame_size < s->nfr)
|
||||
s->nfr = bi.fragsize / s->record.frame_size;
|
||||
s->record.bufframes =
|
||||
(bi.fragsize * bi.fragstotal) / s->record.frame_size;
|
||||
}
|
||||
|
||||
int lw = s->record.frame_size;
|
||||
if (ioctl(s->record.fd, SNDCTL_DSP_LOW_WATER, &lw))
|
||||
LOG("Audio device \"%s\" (record) could not set trigger threshold",
|
||||
s->record.name);
|
||||
}
|
||||
s->bufframes = s->nfr * s->nfrags;
|
||||
s->context = context;
|
||||
s->volume = 1.0;
|
||||
s->state_cb = state_callback;
|
||||
|
@ -1188,13 +1192,14 @@ oss_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
s->doorbell = false;
|
||||
|
||||
if (s->play.fd != -1) {
|
||||
if ((s->play.buf = calloc(s->bufframes, s->play.frame_size)) == NULL) {
|
||||
if ((s->play.buf = calloc(s->play.bufframes, s->play.frame_size)) == NULL) {
|
||||
ret = CUBEB_ERROR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (s->record.fd != -1) {
|
||||
if ((s->record.buf = calloc(s->bufframes, s->record.frame_size)) == NULL) {
|
||||
if ((s->record.buf = calloc(s->record.bufframes, s->record.frame_size)) ==
|
||||
NULL) {
|
||||
ret = CUBEB_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#ifdef DISABLE_LIBSNDIO_DLOPEN
|
||||
#define WRAP(x) x
|
||||
#else
|
||||
#define WRAP(x) cubeb_##x
|
||||
#define WRAP(x) (*cubeb_##x)
|
||||
#define LIBSNDIO_API_VISIT(X) \
|
||||
X(sio_close) \
|
||||
X(sio_eof) \
|
||||
|
|
|
@ -73,17 +73,6 @@
|
|||
#define CUBEB_STREAM_MAX 32
|
||||
#define NBUFS 4
|
||||
|
||||
const GUID KSDATAFORMAT_SUBTYPE_PCM = {
|
||||
0x00000001,
|
||||
0x0000,
|
||||
0x0010,
|
||||
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
|
||||
const GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {
|
||||
0x00000003,
|
||||
0x0000,
|
||||
0x0010,
|
||||
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
|
||||
|
||||
struct cubeb_stream_item {
|
||||
SLIST_ENTRY head;
|
||||
cubeb_stream * stream;
|
||||
|
|
Загрузка…
Ссылка в новой задаче