Bug 1105901 - Update cubeb from upstream to pick up compilation fix for glibc 2.20. r=padenot

--HG--
extra : rebase_source : cb04020b3c502f51e2411b1984bb42d8423d524b
This commit is contained in:
Matthew Gregan 2014-12-02 12:04:16 +13:00
parent 87f717717e
commit f151c28311
16 changed files with 575 additions and 472 deletions

View File

@ -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 8948986e9c8d1e1988e67d2819492a52b719b13a.
The git commit ID used was 14d97931da6435d10aa4dcb444896af0314372f4.

View File

@ -122,8 +122,8 @@ typedef enum {
typedef struct {
cubeb_sample_format format; /**< Requested sample format. One of
#cubeb_sample_format. */
unsigned int rate; /**< Requested sample rate. Valid range is [1, 192000]. */
unsigned int channels; /**< Requested channel count. Valid range is [1, 32]. */
unsigned int rate; /**< Requested sample rate. Valid range is [1000, 192000]. */
unsigned int channels; /**< Requested channel count. Valid range is [1, 8]. */
#if defined(__ANDROID__)
cubeb_stream_type stream_type; /**< Used to map Android audio stream types */
#endif
@ -148,7 +148,8 @@ enum {
CUBEB_OK = 0, /**< Success. */
CUBEB_ERROR = -1, /**< Unclassified error. */
CUBEB_ERROR_INVALID_FORMAT = -2, /**< Unsupported #cubeb_stream_params requested. */
CUBEB_ERROR_INVALID_PARAMETER = -3 /**< Invalid parameter specified. */
CUBEB_ERROR_INVALID_PARAMETER = -3, /**< Invalid parameter specified. */
CUBEB_ERROR_NOT_SUPPORTED = -4 /**< Optional function not implemented in current backend. */
};
/** User supplied data callback.
@ -156,7 +157,8 @@ enum {
@param user_ptr
@param buffer
@param nframes
@retval Number of frames written to buffer, which must equal nframes except at end of stream.
@retval Number of frames written to buffer, which must equal nframes except
at end of stream.
@retval CUBEB_ERROR on error, in which case the data callback will stop
and the stream will enter a shutdown state. */
typedef long (* cubeb_data_callback)(cubeb_stream * stream,
@ -195,6 +197,7 @@ char const * cubeb_get_backend_id(cubeb * context);
@param max_channels The maximum number of channels.
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_ERROR_NOT_SUPPORTED
@retval CUBEB_ERROR */
int cubeb_get_max_channel_count(cubeb * context, uint32_t * max_channels);
@ -205,16 +208,20 @@ int cubeb_get_max_channel_count(cubeb * context, uint32_t * max_channels);
@param params On some backends, the minimum achievable latency depends on
the characteristics of the stream.
@param latency_ms The latency value, in ms, to pass to cubeb_stream_init.
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_OK */
int cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * latency_ms);
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_get_min_latency(cubeb * context,
cubeb_stream_params params,
uint32_t * latency_ms);
/** Get the preferred sample rate for this backend: this is hardware and platform
dependant, and can avoid resampling, and/or trigger fastpaths.
@param context
@param rate The samplerate (in Hz) the current configuration prefers.
@return CUBEB_ERROR_INVALID_PARAMETER
@return CUBEB_OK */
/** Get the preferred sample rate for this backend: this is hardware and
platform dependant, and can avoid resampling, and/or trigger fastpaths.
@param context
@param rate The samplerate (in Hz) the current configuration prefers.
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_get_preferred_sample_rate(cubeb * context, uint32_t * rate);
/** Destroy an application context.
@ -226,16 +233,20 @@ void cubeb_destroy(cubeb * context);
@param stream
@param stream_name
@param stream_params
@param latency Approximate stream latency in milliseconds. Valid range is [1, 2000].
@param latency Approximate stream latency in milliseconds. Valid range
is [1, 2000].
@param data_callback Will be called to preroll data before playback is
started by cubeb_stream_start.
started by cubeb_stream_start.
@param state_callback
@param user_ptr
@retval CUBEB_OK
@retval CUBEB_ERROR
@retval CUBEB_ERROR_INVALID_FORMAT */
int cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
cubeb_stream_params stream_params, unsigned int latency,
int cubeb_stream_init(cubeb * context,
cubeb_stream ** stream,
char const * stream_name,
cubeb_stream_params stream_params,
unsigned int latency,
cubeb_data_callback data_callback,
cubeb_state_callback state_callback,
void * user_ptr);
@ -269,63 +280,60 @@ int cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position);
@param stream
@param latency Current approximate stream latency in frames.
@retval CUBEB_OK
@retval CUBEB_ERROR_NOT_SUPPORTED
@retval CUBEB_ERROR */
int cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency);
/**
* Set the volume for a stream.
* @param stream the stream for which to adjust the volume.
* @param volume a float between 0.0 (muted) and 1.0 (maximum volume)
* @return CUBEB_ERROR_INVALID_PARAMETER if volume is outside [0.0; 1.0]
* @return CUBEB_ERROR_INVALID_PARAMETER if stream is an invalid pointer
* @return CUBEB_OK otherwise
*/
/** Set the volume for a stream.
@param stream the stream for which to adjust the volume.
@param volume a float between 0.0 (muted) and 1.0 (maximum volume)
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER volume is outside [0.0, 1.0] or
stream is an invalid pointer
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_stream_set_volume(cubeb_stream * stream, float volume);
/**
* If the stream is stereo, set the left/right panning. If the stream is mono,
* this has no effect.
* @param stream the stream for which to change the panning
* @param panning a number from -1.0 to 1.0. -1.0 means that the stream is fully
* mixed in the left channel, 1.0 means the stream is fully mixed in the right
* channel. 0.0 is equal power in the right and left channel (default).
* @return CUBEB_ERROR_INVALID_PARAMETER if stream is null or if panning is outside
* the [-1.0; 1.0] range.
* @return CUBEB_ERROR if this stream is not mono nor stereo.
* @return CUBEB_OK otherwise.
*/
/** If the stream is stereo, set the left/right panning. If the stream is mono,
this has no effect.
@param stream the stream for which to change the panning
@param panning a number from -1.0 to 1.0. -1.0 means that the stream is
fully mixed in the left channel, 1.0 means the stream is fully
mixed in the right channel. 0.0 is equal power in the right and
left channel (default).
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER if stream is null or if panning is
outside the [-1.0, 1.0] range.
@retval CUBEB_ERROR_NOT_SUPPORTED
@retval CUBEB_ERROR stream is not mono nor stereo */
int cubeb_stream_set_panning(cubeb_stream * stream, float panning);
/**
* Get the current output device for this stream.
* @param stm the stream for which to query the current output device
* @param device a pointer in which the current output device will be stored.
* @return CUBEB_OK in case of success
* @return CUBEB_ERROR_INVALID_PARAMETER if either stm, device or count are
* invalid pointers
*/
/** Get the current output device for this stream.
@param stm the stream for which to query the current output device
@param device a pointer in which the current output device will be stored.
@retval CUBEB_OK in case of success
@retval CUBEB_ERROR_INVALID_PARAMETER if either stm, device or count are
invalid pointers
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_stream_get_current_device(cubeb_stream * stm,
cubeb_device ** const device);
/**
* Destroy a cubeb_device structure.
* @param stream the stream passed in cubeb_stream_get_current_device
* @param devices the devices to destroy
* @return CUBEB_OK in case of success
* @return CUBEB_ERROR_INVALID_PARAMETER if devices is an invalid pointer
*/
/** Destroy a cubeb_device structure.
@param stream the stream passed in cubeb_stream_get_current_device
@param devices the devices to destroy
@retval CUBEB_OK in case of success
@retval CUBEB_ERROR_INVALID_PARAMETER if devices is an invalid pointer
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_stream_device_destroy(cubeb_stream * stream,
cubeb_device * devices);
/**
* Set a callback to be notified when the output device changes.
* @param stream the stream for which to set the callback.
* @param device_changed_callback a function called whenever the device has
* changed. Passing NULL allow to unregister a function
* @return CUBEB_ERROR_INVALID_PARAMETER if either stream or
* device_changed_callback are invalid pointers.
* @return CUBEB_OK
*/
/** Set a callback to be notified when the output device changes.
@param stream the stream for which to set the callback.
@param device_changed_callback a function called whenever the device has
changed. Passing NULL allow to unregister a function
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER if either stream or
device_changed_callback are invalid pointers.
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback);

View File

@ -34,8 +34,8 @@ struct cubeb_ops {
cubeb_device ** const device);
int (* stream_device_destroy)(cubeb_stream * stream,
cubeb_device * device);
int (*stream_register_device_changed_callback)(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback);
int (* stream_register_device_changed_callback)(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback);
};

View File

@ -4,6 +4,8 @@
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
#undef NDEBUG
#include <assert.h>
#include <stddef.h>
#if defined(HAVE_CONFIG_H)
#include "config.h"
@ -129,6 +131,15 @@ cubeb_init(cubeb ** context, char const * context_name)
for (i = 0; i < NELEMS(init); ++i) {
if (init[i](context, context_name) == CUBEB_OK) {
/* Assert that the minimal API is implemented. */
#define OK(fn) assert((* context)->ops->fn)
OK(get_backend_id);
OK(destroy);
OK(stream_init);
OK(stream_destroy);
OK(stream_start);
OK(stream_stop);
OK(stream_get_position);
return CUBEB_OK;
}
}
@ -153,6 +164,10 @@ cubeb_get_max_channel_count(cubeb * context, uint32_t * max_channels)
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!context->ops->get_max_channel_count) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->get_max_channel_count(context, max_channels);
}
@ -162,6 +177,11 @@ cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * la
if (!context || !latency_ms) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!context->ops->get_min_latency) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->get_min_latency(context, params, latency_ms);
}
@ -171,6 +191,11 @@ cubeb_get_preferred_sample_rate(cubeb * context, uint32_t * rate)
if (!context || !rate) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!context->ops->get_preferred_sample_rate) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->get_preferred_sample_rate(context, rate);
}
@ -256,6 +281,10 @@ cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_get_latency) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_get_latency(stream, latency);
}
@ -266,6 +295,10 @@ cubeb_stream_set_volume(cubeb_stream * stream, float volume)
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_set_volume) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_set_volume(stream, volume);
}
@ -275,6 +308,10 @@ int cubeb_stream_set_panning(cubeb_stream * stream, float panning)
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_set_panning) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_set_panning(stream, panning);
}
@ -285,14 +322,11 @@ int cubeb_stream_get_current_device(cubeb_stream * stream,
return CUBEB_ERROR_INVALID_PARAMETER;
}
// If we find an implementation, call the function, it might not be available
// on some platforms.
if (stream->context->ops->stream_get_current_device) {
return stream->context->ops->stream_get_current_device(stream,
device);
if (!stream->context->ops->stream_get_current_device) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return CUBEB_ERROR;
return stream->context->ops->stream_get_current_device(stream, device);
}
int cubeb_stream_device_destroy(cubeb_stream * stream,
@ -302,13 +336,11 @@ int cubeb_stream_device_destroy(cubeb_stream * stream,
return CUBEB_ERROR_INVALID_PARAMETER;
}
// If we find an implementation, call the function, it might not be available
// on some platforms.
if (stream->context->ops->stream_device_destroy) {
return stream->context->ops->stream_device_destroy(stream, device);
if (!stream->context->ops->stream_device_destroy) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return CUBEB_ERROR;
return stream->context->ops->stream_device_destroy(stream, device);
}
int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
@ -318,11 +350,9 @@ int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (stream->context->ops->stream_register_device_changed_callback) {
return stream->context->ops->
stream_register_device_changed_callback(stream,
device_changed_callback);
if (!stream->context->ops->stream_register_device_changed_callback) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return CUBEB_ERROR;
return stream->context->ops->stream_register_device_changed_callback(stream, device_changed_callback);
}

View File

@ -5,6 +5,7 @@
* accompanying file LICENSE for details.
*/
#undef NDEBUG
#define _DEFAULT_SOURCE
#define _BSD_SOURCE
#define _XOPEN_SOURCE 500
#include <pthread.h>
@ -920,7 +921,7 @@ alsa_stream_destroy(cubeb_stream * stm)
static int
alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
{
int rv;
int r;
cubeb_stream * stm;
snd_pcm_hw_params_t* hw_params;
cubeb_stream_params params;
@ -932,18 +933,18 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
assert(ctx);
rv = alsa_stream_init(ctx, &stm, "", params, 100, NULL, NULL, NULL);
if (rv != CUBEB_OK) {
r = alsa_stream_init(ctx, &stm, "", params, 100, NULL, NULL, NULL);
if (r != CUBEB_OK) {
return CUBEB_ERROR;
}
rv = snd_pcm_hw_params_any(stm->pcm, hw_params);
if (rv < 0) {
r = snd_pcm_hw_params_any(stm->pcm, hw_params);
if (r < 0) {
return CUBEB_ERROR;
}
rv = snd_pcm_hw_params_get_channels_max(hw_params, max_channels);
if (rv < 0) {
r = snd_pcm_hw_params_get_channels_max(hw_params, max_channels);
if (r < 0) {
return CUBEB_ERROR;
}
@ -954,7 +955,7 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
static int
alsa_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) {
int rv, dir;
int r, dir;
snd_pcm_t * pcm;
snd_pcm_hw_params_t * hw_params;
@ -962,19 +963,19 @@ alsa_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) {
/* get a pcm, disabling resampling, so we get a rate the
* hardware/dmix/pulse/etc. supports. */
rv = snd_pcm_open(&pcm, "", SND_PCM_STREAM_PLAYBACK | SND_PCM_NO_AUTO_RESAMPLE, 0);
if (rv < 0) {
r = snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK | SND_PCM_NO_AUTO_RESAMPLE, 0);
if (r < 0) {
return CUBEB_ERROR;
}
rv = snd_pcm_hw_params_any(pcm, hw_params);
if (rv < 0) {
r = snd_pcm_hw_params_any(pcm, hw_params);
if (r < 0) {
snd_pcm_close(pcm);
return CUBEB_ERROR;
}
rv = snd_pcm_hw_params_get_rate(hw_params, rate, &dir);
if (rv >= 0) {
r = snd_pcm_hw_params_get_rate(hw_params, rate, &dir);
if (r >= 0) {
/* There is a default rate: use it. */
snd_pcm_close(pcm);
return CUBEB_OK;
@ -983,8 +984,8 @@ alsa_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) {
/* Use a common rate, alsa may adjust it based on hw/etc. capabilities. */
*rate = 44100;
rv = snd_pcm_hw_params_set_rate_near(pcm, hw_params, rate, NULL);
if (rv < 0) {
r = snd_pcm_hw_params_set_rate_near(pcm, hw_params, rate, NULL);
if (r < 0) {
snd_pcm_close(pcm);
return CUBEB_ERROR;
}
@ -998,7 +999,7 @@ static int
alsa_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_ms)
{
/* This is found to be an acceptable minimum, even on a super low-end
* machine. */
* machine. */
*latency_ms = 40;
return CUBEB_OK;
@ -1109,13 +1110,6 @@ alsa_stream_set_volume(cubeb_stream * stm, float volume)
return CUBEB_OK;
}
int
alsa_stream_set_panning(cubeb_stream * stream, float panning)
{
assert(0 && "not implemented");
return CUBEB_OK;
}
static struct cubeb_ops const alsa_ops = {
.init = alsa_init,
.get_backend_id = alsa_get_backend_id,
@ -1130,7 +1124,7 @@ static struct cubeb_ops const alsa_ops = {
.stream_get_position = alsa_stream_get_position,
.stream_get_latency = alsa_stream_get_latency,
.stream_set_volume = alsa_stream_set_volume,
.stream_set_panning = alsa_stream_set_panning,
.stream_set_panning = NULL,
.stream_get_current_device = NULL,
.stream_device_destroy = NULL,
.stream_register_device_changed_callback = NULL

View File

@ -35,14 +35,14 @@
* call dlsym to get the symbol |mangled_name|, handle the error and store the
* pointer in |pointer|. Because depending on Android version, we want different
* symbols, not finding a symbol is not an error. */
#define DLSYM_DLERROR(mangled_name, pointer, lib) \
do { \
pointer = dlsym(lib, mangled_name); \
if (!pointer) { \
#define DLSYM_DLERROR(mangled_name, pointer, lib) \
do { \
pointer = dlsym(lib, mangled_name); \
if (!pointer) { \
ALOG("error while loading %stm: %stm\n", mangled_name, dlerror()); \
} else { \
ALOG("%stm: OK", mangled_name); \
} \
} else { \
ALOG("%stm: OK", mangled_name); \
} \
} while(0);
static struct cubeb_ops const audiotrack_ops;
@ -50,28 +50,28 @@ void audiotrack_destroy(cubeb * context);
void audiotrack_stream_destroy(cubeb_stream * stream);
struct AudioTrack {
/* only available on ICS and later. The second int paramter is in fact of type audio_stream_type_t. */
/* only available on ICS and later. The second int paramter is in fact of type audio_stream_type_t. */
/* static */ status_t (*get_min_frame_count)(int* frame_count, int stream_type, uint32_t rate);
/* if we have a recent ctor, but can't find the above symbol, we
* can get the minimum frame count with this signature, and we are
* running gingerbread. */
/* if we have a recent ctor, but can't find the above symbol, we
* can get the minimum frame count with this signature, and we are
* running gingerbread. */
/* static */ status_t (*get_min_frame_count_gingerbread)(int* frame_count, int stream_type, uint32_t rate);
/* if this symbol is not availble, and the next one is, we know
* we are on a Froyo (Android 2.2) device. */
void* (*ctor)(void* instance, int, unsigned int, int, int, int, unsigned int, void (*)(int, void*, void*), void*, int, int);
void* (*ctor_froyo)(void* instance, int, unsigned int, int, int, int, unsigned int, void (*)(int, void*, void*), void*, int);
void* (*dtor)(void* instance);
void (*start)(void* instance);
void (*pause)(void* instance);
uint32_t (*latency)(void* instance);
status_t (*check)(void* instance);
status_t (*get_position)(void* instance, uint32_t* position);
/* only used on froyo. */
/* if this symbol is not availble, and the next one is, we know
* we are on a Froyo (Android 2.2) device. */
void* (*ctor)(void* instance, int, unsigned int, int, int, int, unsigned int, void (*)(int, void*, void*), void*, int, int);
void* (*ctor_froyo)(void* instance, int, unsigned int, int, int, int, unsigned int, void (*)(int, void*, void*), void*, int);
void* (*dtor)(void* instance);
void (*start)(void* instance);
void (*pause)(void* instance);
uint32_t (*latency)(void* instance);
status_t (*check)(void* instance);
status_t (*get_position)(void* instance, uint32_t* position);
/* only used on froyo. */
/* static */ int (*get_output_frame_count)(int* frame_count, int stream);
/* static */ int (*get_output_latency)(uint32_t* latency, int stream);
/* static */ int (*get_output_samplingrate)(int* samplerate, int stream);
status_t (*set_marker_position)(void* instance, unsigned int);
status_t (*set_volume)(void* instance, float left, float right);
status_t (*set_marker_position)(void* instance, unsigned int);
status_t (*set_volume)(void* instance, float left, float right);
};
struct cubeb {
@ -97,44 +97,44 @@ audiotrack_refill(int event, void* user, void* info)
{
cubeb_stream * stream = user;
switch (event) {
case EVENT_MORE_DATA: {
long got = 0;
struct Buffer * b = (struct Buffer*)info;
case EVENT_MORE_DATA: {
long got = 0;
struct Buffer * b = (struct Buffer*)info;
if (stream->draining) {
return;
}
got = stream->data_callback(stream, stream->user_ptr, b->raw, b->frameCount);
stream->written += got;
if (got != (long)b->frameCount) {
uint32_t p;
stream->draining = 1;
/* set a marker so we are notified when the are done draining, that is,
* when every frame has been played by android. */
stream->context->klass.set_marker_position(stream->instance, stream->written);
}
break;
if (stream->draining) {
return;
}
case EVENT_UNDERRUN:
ALOG("underrun in cubeb backend.");
break;
case EVENT_LOOP_END:
assert(0 && "We don't support the loop feature of audiotrack.");
break;
case EVENT_MARKER:
assert(stream->draining);
stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_DRAINED);
break;
case EVENT_NEW_POS:
assert(0 && "We don't support the setPositionUpdatePeriod feature of audiotrack.");
break;
case EVENT_BUFFER_END:
assert(0 && "Should not happen.");
break;
got = stream->data_callback(stream, stream->user_ptr, b->raw, b->frameCount);
stream->written += got;
if (got != (long)b->frameCount) {
uint32_t p;
stream->draining = 1;
/* set a marker so we are notified when the are done draining, that is,
* when every frame has been played by android. */
stream->context->klass.set_marker_position(stream->instance, stream->written);
}
break;
}
case EVENT_UNDERRUN:
ALOG("underrun in cubeb backend.");
break;
case EVENT_LOOP_END:
assert(0 && "We don't support the loop feature of audiotrack.");
break;
case EVENT_MARKER:
assert(stream->draining);
stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_DRAINED);
break;
case EVENT_NEW_POS:
assert(0 && "We don't support the setPositionUpdatePeriod feature of audiotrack.");
break;
case EVENT_BUFFER_END:
assert(0 && "Should not happen.");
break;
}
}
@ -256,12 +256,12 @@ audiotrack_init(cubeb ** context, char const * context_name)
/* check that we have a combination of symbol that makes sense */
c = &ctx->klass;
if(!((c->ctor || c->ctor_froyo) && /* at least on ctor. */
c->dtor && c->latency && c->check &&
/* at least one way to get the minimum frame count to request. */
((c->get_output_frame_count && c->get_output_latency && c->get_output_samplingrate) ||
c->get_min_frame_count ||
c->get_min_frame_count_gingerbread) &&
c->start && c->pause && c->get_position && c->set_marker_position)) {
c->dtor && c->latency && c->check &&
/* at least one way to get the minimum frame count to request. */
((c->get_output_frame_count && c->get_output_latency && c->get_output_samplingrate) ||
c->get_min_frame_count ||
c->get_min_frame_count_gingerbread) &&
c->start && c->pause && c->get_position && c->set_marker_position)) {
ALOG("Could not find all the symbols we need.");
audiotrack_destroy(ctx);
return CUBEB_ERROR;
@ -286,7 +286,7 @@ audiotrack_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
assert(ctx && max_channels);
/* The android mixer handles up to two channels, see
http://androidxref.com/4.2.2_r1/xref/frameworks/av/services/audioflinger/AudioFlinger.h#67 */
http://androidxref.com/4.2.2_r1/xref/frameworks/av/services/audioflinger/AudioFlinger.h#67 */
*max_channels = 2;
return CUBEB_OK;
@ -297,10 +297,10 @@ audiotrack_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * l
{
/* We always use the lowest latency possible when using this backend (see
* audiotrack_stream_init), so this value is not going to be used. */
int rv;
int r;
rv = audiotrack_get_min_frame_count(ctx, &params, (int *)latency_ms);
if (rv != CUBEB_OK) {
r = audiotrack_get_min_frame_count(ctx, &params, (int *)latency_ms);
if (r != CUBEB_OK) {
return CUBEB_ERROR;
}
@ -313,11 +313,11 @@ audiotrack_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * l
static int
audiotrack_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
{
status_t rv;
status_t r;
rv = ctx->klass.get_output_samplingrate((int32_t *)rate, 3 /* MUSIC */);
r = ctx->klass.get_output_samplingrate((int32_t *)rate, 3 /* MUSIC */);
return rv == 0 ? CUBEB_OK : CUBEB_ERROR;
return r == 0 ? CUBEB_OK : CUBEB_ERROR;
}
void
@ -483,13 +483,6 @@ audiotrack_stream_set_volume(cubeb_stream * stream, float volume)
return CUBEB_OK;
}
int
audiotrack_stream_set_panning(cubeb_stream * stream, float panning)
{
assert(false && "not implemented.");
return CUBEB_OK;
}
static struct cubeb_ops const audiotrack_ops = {
.init = audiotrack_init,
.get_backend_id = audiotrack_get_backend_id,
@ -504,7 +497,7 @@ static struct cubeb_ops const audiotrack_ops = {
.stream_get_position = audiotrack_stream_get_position,
.stream_get_latency = audiotrack_stream_get_latency,
.stream_set_volume = audiotrack_stream_set_volume,
.stream_set_panning = audiotrack_stream_set_panning,
.stream_set_panning = NULL,
.stream_get_current_device = NULL,
.stream_device_destroy = NULL,
.stream_register_device_changed_callback = NULL

View File

@ -223,15 +223,15 @@ audiounit_property_listener_callback(AudioObjectID id, UInt32 address_count,
for (UInt32 i = 0; i < address_count; i++) {
switch(addresses[i].mSelector) {
case kAudioHardwarePropertyDefaultOutputDevice:
/* fall through */
case kAudioDevicePropertyDataSource:
pthread_mutex_lock(&stm->mutex);
if (stm->device_changed_callback) {
stm->device_changed_callback(stm->user_ptr);
}
pthread_mutex_unlock(&stm->mutex);
break;
case kAudioHardwarePropertyDefaultOutputDevice:
/* fall through */
case kAudioDevicePropertyDataSource:
pthread_mutex_lock(&stm->mutex);
if (stm->device_changed_callback) {
stm->device_changed_callback(stm->user_ptr);
}
pthread_mutex_unlock(&stm->mutex);
break;
}
}
@ -494,7 +494,7 @@ audiounit_stream_init(cubeb * context, cubeb_stream ** stream, char const * stre
case CUBEB_SAMPLE_S16BE:
ss.mBitsPerChannel = 16;
ss.mFormatFlags |= kAudioFormatFlagIsSignedInteger |
kAudioFormatFlagIsBigEndian;
kAudioFormatFlagIsBigEndian;
break;
case CUBEB_SAMPLE_FLOAT32LE:
ss.mBitsPerChannel = 32;
@ -503,7 +503,7 @@ audiounit_stream_init(cubeb * context, cubeb_stream ** stream, char const * stre
case CUBEB_SAMPLE_FLOAT32BE:
ss.mBitsPerChannel = 32;
ss.mFormatFlags |= kAudioFormatFlagIsFloat |
kAudioFormatFlagIsBigEndian;
kAudioFormatFlagIsBigEndian;
break;
default:
return CUBEB_ERROR_INVALID_FORMAT;
@ -911,7 +911,7 @@ int audiounit_stream_device_destroy(cubeb_stream * stream,
}
int audiounit_stream_register_device_changed_callback(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback)
cubeb_device_changed_callback device_changed_callback)
{
pthread_mutex_lock(&stream->mutex);
stream->device_changed_callback = device_changed_callback;

View File

@ -78,15 +78,15 @@ play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event)
cubeb_stream * stm = user_ptr;
assert(stm);
switch (event) {
case SL_PLAYEVENT_HEADATMARKER:
pthread_mutex_lock(&stm->mutex);
assert(stm->draining);
pthread_mutex_unlock(&stm->mutex);
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
(*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PAUSED);
break;
default:
break;
case SL_PLAYEVENT_HEADATMARKER:
pthread_mutex_lock(&stm->mutex);
assert(stm->draining);
pthread_mutex_unlock(&stm->mutex);
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
(*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PAUSED);
break;
default:
break;
}
}
@ -114,7 +114,7 @@ bufferqueue_callback(SLBufferQueueItf caller, void * user_ptr)
if (!draining) {
written = cubeb_resampler_fill(stm->resampler, buf,
stm->queuebuf_len / stm->framesize);
stm->queuebuf_len / stm->framesize);
if (written < 0 || written * stm->framesize > stm->queuebuf_len) {
(*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PAUSED);
return;
@ -151,22 +151,22 @@ static SLuint32
convert_stream_type_to_sl_stream(cubeb_stream_type stream_type)
{
switch(stream_type) {
case CUBEB_STREAM_TYPE_SYSTEM:
return SL_ANDROID_STREAM_SYSTEM;
case CUBEB_STREAM_TYPE_MUSIC:
return SL_ANDROID_STREAM_MEDIA;
case CUBEB_STREAM_TYPE_NOTIFICATION:
return SL_ANDROID_STREAM_NOTIFICATION;
case CUBEB_STREAM_TYPE_ALARM:
return SL_ANDROID_STREAM_ALARM;
case CUBEB_STREAM_TYPE_VOICE_CALL:
return SL_ANDROID_STREAM_VOICE;
case CUBEB_STREAM_TYPE_RING:
return SL_ANDROID_STREAM_RING;
case CUBEB_STREAM_TYPE_SYSTEM_ENFORCED:
return SL_ANDROID_STREAM_SYSTEM_ENFORCED;
default:
return 0xFFFFFFFF;
case CUBEB_STREAM_TYPE_SYSTEM:
return SL_ANDROID_STREAM_SYSTEM;
case CUBEB_STREAM_TYPE_MUSIC:
return SL_ANDROID_STREAM_MEDIA;
case CUBEB_STREAM_TYPE_NOTIFICATION:
return SL_ANDROID_STREAM_NOTIFICATION;
case CUBEB_STREAM_TYPE_ALARM:
return SL_ANDROID_STREAM_ALARM;
case CUBEB_STREAM_TYPE_VOICE_CALL:
return SL_ANDROID_STREAM_VOICE;
case CUBEB_STREAM_TYPE_RING:
return SL_ANDROID_STREAM_RING;
case CUBEB_STREAM_TYPE_SYSTEM_ENFORCED:
return SL_ANDROID_STREAM_SYSTEM_ENFORCED;
default:
return 0xFFFFFFFF;
}
}
#endif
@ -317,7 +317,7 @@ opensl_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
{
assert(ctx && max_channels);
/* The android mixer handles up to two channels, see
http://androidxref.com/4.2.2_r1/xref/frameworks/av/services/audioflinger/AudioFlinger.h#67 */
http://androidxref.com/4.2.2_r1/xref/frameworks/av/services/audioflinger/AudioFlinger.h#67 */
*max_channels = 2;
return CUBEB_OK;
@ -329,7 +329,7 @@ opensl_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
/* https://android.googlesource.com/platform/ndk.git/+/master/docs/opensles/index.html
* We don't want to deal with JNI here (and we don't have Java on b2g anyways),
* so we just dlopen the library and get the two symbols we need. */
int rv;
int r;
void * libmedia;
uint32_t (*get_primary_output_samplingrate)();
uint32_t (*get_output_samplingrate)(int * samplingRate, int streamType);
@ -364,8 +364,8 @@ opensl_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
*rate = get_primary_output_samplingrate();
} else {
/* We don't really know about the type, here, so we just pass music. */
rv = get_output_samplingrate((int *) rate, AUDIO_STREAM_TYPE_MUSIC);
if (rv) {
r = get_output_samplingrate((int *) rate, AUDIO_STREAM_TYPE_MUSIC);
if (r) {
dlclose(libmedia);
return CUBEB_ERROR;
}
@ -391,16 +391,16 @@ opensl_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
* We don't want to deal with JNI here (and we don't have Java on b2g anyways),
* so we just dlopen the library and get the two symbols we need. */
int rv;
int r;
void * libmedia;
size_t (*get_primary_output_frame_count)(void);
int (*get_output_frame_count)(size_t * frameCount, int streamType);
uint32_t primary_sampling_rate;
size_t primary_buffer_size;
rv = opensl_get_preferred_sample_rate(ctx, &primary_sampling_rate);
r = opensl_get_preferred_sample_rate(ctx, &primary_sampling_rate);
if (rv) {
if (r) {
return CUBEB_ERROR;
}
@ -458,9 +458,9 @@ static void opensl_stream_destroy(cubeb_stream * stm);
static int
opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
cubeb_stream_params stream_params, unsigned int latency,
cubeb_data_callback data_callback, cubeb_state_callback state_callback,
void * user_ptr)
cubeb_stream_params stream_params, unsigned int latency,
cubeb_data_callback data_callback, cubeb_state_callback state_callback,
void * user_ptr)
{
cubeb_stream * stm;
@ -482,8 +482,8 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name
format.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
format.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
format.channelMask = stream_params.channels == 1 ?
SL_SPEAKER_FRONT_CENTER :
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
SL_SPEAKER_FRONT_CENTER :
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
switch (stream_params.format) {
case CUBEB_SAMPLE_S16LE:
@ -588,9 +588,9 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name
if (stream_type != 0xFFFFFFFF) {
SLAndroidConfigurationItf playerConfig;
res = (*stm->playerObj)->GetInterface(stm->playerObj,
ctx->SL_IID_ANDROIDCONFIGURATION, &playerConfig);
ctx->SL_IID_ANDROIDCONFIGURATION, &playerConfig);
res = (*playerConfig)->SetConfiguration(playerConfig,
SL_ANDROID_KEY_STREAM_TYPE, &stream_type, sizeof(SLint32));
SL_ANDROID_KEY_STREAM_TYPE, &stream_type, sizeof(SLint32));
if (res != SL_RESULT_SUCCESS) {
opensl_stream_destroy(stm);
return CUBEB_ERROR;
@ -611,7 +611,7 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name
}
res = (*stm->playerObj)->GetInterface(stm->playerObj, ctx->SL_IID_BUFFERQUEUE,
&stm->bufq);
&stm->bufq);
if (res != SL_RESULT_SUCCESS) {
opensl_stream_destroy(stm);
return CUBEB_ERROR;
@ -667,7 +667,7 @@ static int
opensl_stream_start(cubeb_stream * stm)
{
/* To refill the queues before starting playback in order to avoid racing
* with refills started by SetPlayState on OpenSLES ndk threads. */
* with refills started by SetPlayState on OpenSLES ndk threads. */
bufferqueue_callback(NULL, stm);
SLresult res = (*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PLAYING);
if (res != SL_RESULT_SUCCESS)
@ -692,7 +692,7 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
SLmillisecond msec;
uint64_t samplerate;
SLresult res;
int rv;
int r;
uint32_t mixer_latency;
res = (*stm->play)->GetPosition(stm->play, &msec);
@ -701,8 +701,8 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
samplerate = stm->inputrate;
rv = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
if (rv) {
r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
if (r) {
return CUBEB_ERROR;
}
@ -714,7 +714,7 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
if (msec > mixer_latency) {
int64_t unadjusted_position = samplerate * (msec - mixer_latency) / 1000;
*position = unadjusted_position < maximum_position ?
unadjusted_position : maximum_position;
unadjusted_position : maximum_position;
} else {
*position = 0;
}
@ -724,17 +724,17 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
int
opensl_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
{
int rv;
int r;
uint32_t mixer_latency; // The latency returned by AudioFlinger is in ms.
/* audio_stream_type_t is an int, so this is okay. */
rv = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
if (rv) {
r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
if (r) {
return CUBEB_ERROR;
}
*latency = stm->latency * stm->inputrate / 1000 + // OpenSL latency
mixer_latency * stm->inputrate / 1000; // AudioFlinger latency
mixer_latency * stm->inputrate / 1000; // AudioFlinger latency
return CUBEB_OK;
}
@ -770,14 +770,6 @@ opensl_stream_set_volume(cubeb_stream * stm, float volume)
return CUBEB_OK;
}
int
opensl_stream_set_panning(cubeb_stream * stream, float panning)
{
assert(0 && "not implemented.");
return CUBEB_OK;
}
static struct cubeb_ops const opensl_ops = {
.init = opensl_init,
.get_backend_id = opensl_get_backend_id,
@ -792,7 +784,7 @@ static struct cubeb_ops const opensl_ops = {
.stream_get_position = opensl_stream_get_position,
.stream_get_latency = opensl_stream_get_latency,
.stream_set_volume = opensl_stream_set_volume,
.stream_set_panning = opensl_stream_set_panning,
.stream_set_panning = NULL,
.stream_get_current_device = NULL,
.stream_device_destroy = NULL,
.stream_register_device_changed_callback = NULL

View File

@ -18,55 +18,58 @@
#define WRAP(x) x
#else
#define WRAP(x) cubeb_##x
#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x
MAKE_TYPEDEF(pa_channel_map_can_balance);
MAKE_TYPEDEF(pa_channel_map_init_auto);
MAKE_TYPEDEF(pa_context_connect);
MAKE_TYPEDEF(pa_context_disconnect);
MAKE_TYPEDEF(pa_context_drain);
MAKE_TYPEDEF(pa_context_get_server_info);
MAKE_TYPEDEF(pa_context_get_sink_info_by_name);
MAKE_TYPEDEF(pa_context_get_state);
MAKE_TYPEDEF(pa_context_new);
MAKE_TYPEDEF(pa_context_rttime_new);
MAKE_TYPEDEF(pa_context_set_sink_input_volume);
MAKE_TYPEDEF(pa_context_set_state_callback);
MAKE_TYPEDEF(pa_context_unref);
MAKE_TYPEDEF(pa_cvolume_set);
MAKE_TYPEDEF(pa_cvolume_set_balance);
MAKE_TYPEDEF(pa_frame_size);
MAKE_TYPEDEF(pa_operation_get_state);
MAKE_TYPEDEF(pa_operation_unref);
MAKE_TYPEDEF(pa_rtclock_now);
MAKE_TYPEDEF(pa_stream_begin_write);
MAKE_TYPEDEF(pa_stream_cancel_write);
MAKE_TYPEDEF(pa_stream_connect_playback);
MAKE_TYPEDEF(pa_stream_cork);
MAKE_TYPEDEF(pa_stream_disconnect);
MAKE_TYPEDEF(pa_stream_get_channel_map);
MAKE_TYPEDEF(pa_stream_get_index);
MAKE_TYPEDEF(pa_stream_get_latency);
MAKE_TYPEDEF(pa_stream_get_sample_spec);
MAKE_TYPEDEF(pa_stream_get_state);
MAKE_TYPEDEF(pa_stream_get_time);
MAKE_TYPEDEF(pa_stream_new);
MAKE_TYPEDEF(pa_stream_set_state_callback);
MAKE_TYPEDEF(pa_stream_set_write_callback);
MAKE_TYPEDEF(pa_stream_unref);
MAKE_TYPEDEF(pa_stream_update_timing_info);
MAKE_TYPEDEF(pa_stream_write);
MAKE_TYPEDEF(pa_sw_volume_from_linear);
MAKE_TYPEDEF(pa_threaded_mainloop_free);
MAKE_TYPEDEF(pa_threaded_mainloop_get_api);
MAKE_TYPEDEF(pa_threaded_mainloop_in_thread);
MAKE_TYPEDEF(pa_threaded_mainloop_lock);
MAKE_TYPEDEF(pa_threaded_mainloop_new);
MAKE_TYPEDEF(pa_threaded_mainloop_signal);
MAKE_TYPEDEF(pa_threaded_mainloop_start);
MAKE_TYPEDEF(pa_threaded_mainloop_stop);
MAKE_TYPEDEF(pa_threaded_mainloop_unlock);
MAKE_TYPEDEF(pa_threaded_mainloop_wait);
MAKE_TYPEDEF(pa_usec_to_bytes);
#define LIBPULSE_API_VISIT(X) \
X(pa_channel_map_can_balance) \
X(pa_channel_map_init_auto) \
X(pa_context_connect) \
X(pa_context_disconnect) \
X(pa_context_drain) \
X(pa_context_get_server_info) \
X(pa_context_get_sink_info_by_name) \
X(pa_context_get_state) \
X(pa_context_new) \
X(pa_context_rttime_new) \
X(pa_context_set_sink_input_volume) \
X(pa_context_set_state_callback) \
X(pa_context_unref) \
X(pa_cvolume_set) \
X(pa_cvolume_set_balance) \
X(pa_frame_size) \
X(pa_operation_get_state) \
X(pa_operation_unref) \
X(pa_rtclock_now) \
X(pa_stream_begin_write) \
X(pa_stream_cancel_write) \
X(pa_stream_connect_playback) \
X(pa_stream_cork) \
X(pa_stream_disconnect) \
X(pa_stream_get_channel_map) \
X(pa_stream_get_index) \
X(pa_stream_get_latency) \
X(pa_stream_get_sample_spec) \
X(pa_stream_get_state) \
X(pa_stream_get_time) \
X(pa_stream_new) \
X(pa_stream_set_state_callback) \
X(pa_stream_set_write_callback) \
X(pa_stream_unref) \
X(pa_stream_update_timing_info) \
X(pa_stream_write) \
X(pa_sw_volume_from_linear) \
X(pa_threaded_mainloop_free) \
X(pa_threaded_mainloop_get_api) \
X(pa_threaded_mainloop_in_thread) \
X(pa_threaded_mainloop_lock) \
X(pa_threaded_mainloop_new) \
X(pa_threaded_mainloop_signal) \
X(pa_threaded_mainloop_start) \
X(pa_threaded_mainloop_stop) \
X(pa_threaded_mainloop_unlock) \
X(pa_threaded_mainloop_wait) \
X(pa_usec_to_bytes) \
#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x;
LIBPULSE_API_VISIT(MAKE_TYPEDEF);
#undef MAKE_TYPEDEF
#endif
@ -314,7 +317,7 @@ pulse_context_init(cubeb * ctx)
}
ctx->context = WRAP(pa_context_new)(WRAP(pa_threaded_mainloop_get_api)(ctx->mainloop),
ctx->context_name);
ctx->context_name);
WRAP(pa_context_set_state_callback)(ctx->context, context_state_callback, ctx);
WRAP(pa_threaded_mainloop_lock)(ctx->mainloop);
@ -348,61 +351,15 @@ pulse_init(cubeb ** context, char const * context_name)
return CUBEB_ERROR;
}
#define LOAD(x) do { \
cubeb_##x = dlsym(libpulse, #x); \
if (!cubeb_##x) { \
dlclose(libpulse); \
return CUBEB_ERROR; \
} \
} while(0)
LOAD(pa_channel_map_can_balance);
LOAD(pa_channel_map_init_auto);
LOAD(pa_context_connect);
LOAD(pa_context_disconnect);
LOAD(pa_context_drain);
LOAD(pa_context_get_server_info);
LOAD(pa_context_get_sink_info_by_name);
LOAD(pa_context_get_state);
LOAD(pa_context_new);
LOAD(pa_context_rttime_new);
LOAD(pa_context_set_sink_input_volume);
LOAD(pa_context_set_state_callback);
LOAD(pa_context_unref);
LOAD(pa_cvolume_set);
LOAD(pa_cvolume_set_balance);
LOAD(pa_frame_size);
LOAD(pa_operation_get_state);
LOAD(pa_operation_unref);
LOAD(pa_rtclock_now);
LOAD(pa_stream_begin_write);
LOAD(pa_stream_cancel_write);
LOAD(pa_stream_connect_playback);
LOAD(pa_stream_cork);
LOAD(pa_stream_disconnect);
LOAD(pa_stream_get_channel_map);
LOAD(pa_stream_get_index);
LOAD(pa_stream_get_latency);
LOAD(pa_stream_get_sample_spec);
LOAD(pa_stream_get_state);
LOAD(pa_stream_get_time);
LOAD(pa_stream_new);
LOAD(pa_stream_set_state_callback);
LOAD(pa_stream_set_write_callback);
LOAD(pa_stream_unref);
LOAD(pa_stream_update_timing_info);
LOAD(pa_stream_write);
LOAD(pa_sw_volume_from_linear);
LOAD(pa_threaded_mainloop_free);
LOAD(pa_threaded_mainloop_get_api);
LOAD(pa_threaded_mainloop_in_thread);
LOAD(pa_threaded_mainloop_lock);
LOAD(pa_threaded_mainloop_new);
LOAD(pa_threaded_mainloop_signal);
LOAD(pa_threaded_mainloop_start);
LOAD(pa_threaded_mainloop_stop);
LOAD(pa_threaded_mainloop_unlock);
LOAD(pa_threaded_mainloop_wait);
LOAD(pa_usec_to_bytes);
#define LOAD(x) { \
cubeb_##x = dlsym(libpulse, #x); \
if (!cubeb_##x) { \
dlclose(libpulse); \
return CUBEB_ERROR; \
} \
}
LIBPULSE_API_VISIT(LOAD);
#undef LOAD
#endif
@ -590,9 +547,9 @@ pulse_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n
WRAP(pa_stream_set_state_callback)(stm->stream, stream_state_callback, stm);
WRAP(pa_stream_set_write_callback)(stm->stream, stream_request_callback, stm);
WRAP(pa_stream_connect_playback)(stm->stream, NULL, &battr,
PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
PA_STREAM_START_CORKED,
NULL, NULL);
PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
PA_STREAM_START_CORKED,
NULL, NULL);
r = wait_until_stream_ready(stm);
if (r == 0) {

View File

@ -342,13 +342,6 @@ sndio_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
return CUBEB_OK;
}
int
sndio_stream_set_panning(cubeb_stream * stm, float panning)
{
assert(false && "not implemented");
return CUBEB_OK;
}
static struct cubeb_ops const sndio_ops = {
.init = sndio_init,
.get_backend_id = sndio_get_backend_id,
@ -363,7 +356,7 @@ static struct cubeb_ops const sndio_ops = {
.stream_get_position = sndio_stream_get_position,
.stream_get_latency = sndio_stream_get_latency,
.stream_set_volume = sndio_stream_set_volume,
.stream_set_panning = sndio_stream_set_panning,
.stream_set_panning = NULL,
.stream_get_current_device = NULL,
.stream_device_destroy = NULL,
.stream_register_device_changed_callback = NULL

View File

@ -946,12 +946,6 @@ int wasapi_stream_set_volume(cubeb_stream * stm, float volume)
return CUBEB_OK;
}
int wasapi_stream_set_panning(cubeb_stream * stream, float panning)
{
assert(false && "not implemented");
return CUBEB_OK;
}
cubeb_ops const wasapi_ops = {
/*.init =*/ wasapi_init,
/*.get_backend_id =*/ wasapi_get_backend_id,
@ -966,7 +960,7 @@ cubeb_ops const wasapi_ops = {
/*.stream_get_position =*/ wasapi_stream_get_position,
/*.stream_get_latency =*/ wasapi_stream_get_latency,
/*.stream_set_volume =*/ wasapi_stream_set_volume,
/*.stream_set_panning =*/ wasapi_stream_set_panning,
/*.stream_set_panning =*/ NULL,
/*.stream_get_current_device =*/ NULL,
/*.stream_device_destroy =*/ NULL,
/*.stream_register_device_changed_callback =*/ NULL

View File

@ -200,11 +200,11 @@ winmm_buffer_thread(void * user_ptr)
assert(ctx);
for (;;) {
DWORD rv;
DWORD r;
PSLIST_ENTRY item;
rv = WaitForSingleObject(ctx->event, INFINITE);
assert(rv == WAIT_OBJECT_0);
r = WaitForSingleObject(ctx->event, INFINITE);
assert(r == WAIT_OBJECT_0);
/* Process work items in batches so that a single stream can't
starve the others by continuously adding new work to the top of
@ -323,7 +323,7 @@ winmm_get_backend_id(cubeb * ctx)
static void
winmm_destroy(cubeb * ctx)
{
DWORD rv;
DWORD r;
assert(ctx->active_streams == 0);
assert(!InterlockedPopEntrySList(ctx->work));
@ -333,8 +333,8 @@ winmm_destroy(cubeb * ctx)
if (ctx->thread) {
ctx->shutdown = 1;
SetEvent(ctx->event);
rv = WaitForSingleObject(ctx->thread, INFINITE);
assert(rv == WAIT_OBJECT_0);
r = WaitForSingleObject(ctx->thread, INFINITE);
assert(r == WAIT_OBJECT_0);
CloseHandle(ctx->thread);
}
@ -488,7 +488,7 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n
static void
winmm_stream_destroy(cubeb_stream * stm)
{
DWORD rv;
DWORD r;
int i;
int enqueued;
@ -503,8 +503,8 @@ winmm_stream_destroy(cubeb_stream * stm)
/* Wait for all blocks to complete. */
while (enqueued > 0) {
rv = WaitForSingleObject(stm->event, INFINITE);
assert(rv == WAIT_OBJECT_0);
r = WaitForSingleObject(stm->event, INFINITE);
assert(r == WAIT_OBJECT_0);
EnterCriticalSection(&stm->lock);
enqueued = NBUFS - stm->free_buffers;
@ -668,13 +668,6 @@ winmm_stream_set_volume(cubeb_stream * stm, float volume)
return CUBEB_OK;
}
static int
winmm_stream_set_panning(cubeb_stream * stream, float panning)
{
assert(0 && "not implemented");
return CUBEB_OK;
}
static struct cubeb_ops const winmm_ops = {
/*.init =*/ winmm_init,
/*.get_backend_id =*/ winmm_get_backend_id,
@ -689,7 +682,7 @@ static struct cubeb_ops const winmm_ops = {
/*.stream_get_position =*/ winmm_stream_get_position,
/*.stream_get_latency = */ winmm_stream_get_latency,
/*.stream_set_volume =*/ winmm_stream_set_volume,
/*.stream_set_panning =*/ winmm_stream_set_panning,
/*.stream_set_panning =*/ NULL,
/*.stream_get_current_device =*/ NULL,
/*.stream_device_destroy =*/ NULL,
/*.stream_register_device_changed_callback=*/ NULL

View File

@ -114,15 +114,15 @@ int supports_channel_count(const char* backend_id, int nchannels)
int run_test(int num_channels, int sampling_rate, int is_float)
{
int ret = CUBEB_OK;
int r = CUBEB_OK;
cubeb *ctx = NULL;
synth_state* synth = NULL;
cubeb_stream *stream = NULL;
const char * backend_id = NULL;
ret = cubeb_init(&ctx, "Cubeb audio test");
if (ret != CUBEB_OK) {
r = cubeb_init(&ctx, "Cubeb audio test: channels");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
goto cleanup;
}
@ -148,10 +148,10 @@ int run_test(int num_channels, int sampling_rate, int is_float)
goto cleanup;
}
ret = cubeb_stream_init(ctx, &stream, "test tone", params,
100, is_float ? data_cb_float : data_cb_short, state_cb, synth);
if (ret != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream: %d\n", ret);
r = cubeb_stream_init(ctx, &stream, "test tone", params,
100, is_float ? data_cb_float : data_cb_short, state_cb, synth);
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream: %d\n", r);
goto cleanup;
}
@ -164,10 +164,74 @@ cleanup:
cubeb_destroy(ctx);
synth_destroy(synth);
return ret;
return r;
}
int main(int argc, char *argv[])
int run_panning_volume_test()
{
int r = CUBEB_OK;
cubeb *ctx = NULL;
synth_state* synth = NULL;
cubeb_stream *stream = NULL;
r = cubeb_init(&ctx, "Cubeb audio test");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
goto cleanup;
}
cubeb_stream_params params;
params.format = CUBEB_SAMPLE_S16NE;
params.rate = 44100;
params.channels = 2;
synth = synth_create(params.channels, params.rate);
if (synth == NULL) {
fprintf(stderr, "Out of memory\n");
goto cleanup;
}
r = cubeb_stream_init(ctx, &stream, "test tone", params,
100, data_cb_short, state_cb, synth);
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream: %d\n", r);
goto cleanup;
}
fprintf(stderr, "Testing: volume\n");
for(int i=0;i <= 4; ++i)
{
fprintf(stderr, "Volume: %d%%\n", i*25);
cubeb_stream_set_volume(stream, i/4.0f);
cubeb_stream_start(stream);
delay(400);
cubeb_stream_stop(stream);
delay(100);
}
fprintf(stderr, "Testing: panning\n");
for(int i=-4;i <= 4; ++i)
{
fprintf(stderr, "Panning: %.2f%%\n", i/4.0f);
cubeb_stream_set_panning(stream, i/4.0f);
cubeb_stream_start(stream);
delay(400);
cubeb_stream_stop(stream);
delay(100);
}
cleanup:
cubeb_stream_destroy(stream);
cubeb_destroy(ctx);
synth_destroy(synth);
return r;
}
void run_channel_rate_test()
{
int channel_values[] = {
1,
@ -192,8 +256,13 @@ int main(int argc, char *argv[])
assert(run_test(channel_values[j], freq_values[i], 1) == CUBEB_OK);
}
}
return CUBEB_OK;
}
int main(int argc, char *argv[])
{
assert(run_panning_volume_test() == CUBEB_OK);
run_channel_rate_test();
return CUBEB_OK;
}

View File

@ -11,35 +11,41 @@
int main(int argc, char * argv[])
{
cubeb * ctx = NULL;
int rv;
int r;
uint32_t max_channels;
uint32_t preferred_rate;
uint32_t latency_ms;
LOG("latency_test start");
rv = cubeb_init(&ctx, "Cubeb audio test");
assert(rv == CUBEB_OK && "Cubeb init failed.");
r = cubeb_init(&ctx, "Cubeb audio test");
assert(r == CUBEB_OK && "Cubeb init failed.");
LOG("cubeb_init ok");
rv = cubeb_get_max_channel_count(ctx, &max_channels);
assert(rv == CUBEB_OK && "Could not query the max channe count.");
assert(max_channels > 0 && "Invalid max channel count.");
LOG("cubeb_get_max_channel_count ok");
r = cubeb_get_max_channel_count(ctx, &max_channels);
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
assert(max_channels > 0 && "Invalid max channel count.");
LOG("cubeb_get_max_channel_count ok");
}
rv = cubeb_get_preferred_sample_rate(ctx, &preferred_rate);
assert(rv == CUBEB_OK && "Could not query the preferred sample rate.");
assert(preferred_rate && "Invalid preferred sample rate.");
LOG("cubeb_get_preferred_sample_rate ok");
r = cubeb_get_preferred_sample_rate(ctx, &preferred_rate);
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
assert(preferred_rate > 0 && "Invalid preferred sample rate.");
LOG("cubeb_get_preferred_sample_rate ok");
}
cubeb_stream_params params = {
CUBEB_SAMPLE_FLOAT32NE,
preferred_rate,
max_channels
};
rv = cubeb_get_min_latency(ctx, params, &latency_ms);
assert(rv == CUBEB_OK && "Could not query the minimal latency.");
assert(latency_ms && "Invalid minimal latency.");
LOG("cubeb_get_min_latency ok");
r = cubeb_get_min_latency(ctx, params, &latency_ms);
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
assert(latency_ms > 0 && "Invalid minimal latency.");
LOG("cubeb_get_min_latency ok");
}
cubeb_destroy(ctx);
LOG("cubeb_destroy ok");

View File

@ -54,16 +54,23 @@ test_init_destroy_context(void)
{
int r;
cubeb * ctx;
char const* backend_id;
BEGIN_TEST
r = cubeb_init(&ctx, "test_sanity");
r = cubeb_init(&ctx, "test_sanity");
assert(r == 0 && ctx);
backend_id = cubeb_get_backend_id(ctx);
assert(backend_id);
fprintf(stderr, "Backend: %s\n", backend_id);
cubeb_destroy(ctx);
END_TEST
}
}
static void
test_init_destroy_multiple_contexts(void)
@ -76,10 +83,10 @@ test_init_destroy_multiple_contexts(void)
BEGIN_TEST
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
r = cubeb_init(&ctx[i], NULL);
assert(r == 0 && ctx[i]);
}
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
r = cubeb_init(&ctx[i], NULL);
assert(r == 0 && ctx[i]);
}
/* destroy in a different order */
for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
@ -87,7 +94,40 @@ test_init_destroy_multiple_contexts(void)
}
END_TEST
}
}
static void
test_context_variables(void)
{
int r;
cubeb * ctx;
uint32_t value;
cubeb_stream_params params;
BEGIN_TEST
r = cubeb_init(&ctx, "test_context_variables");
assert(r == 0 && ctx);
params.channels = 2;
params.format = CUBEB_SAMPLE_S16LE;
params.rate = 44100;
r = cubeb_get_min_latency(ctx, params, &value);
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
assert(value > 0);
}
r = cubeb_get_preferred_sample_rate(ctx, &value);
assert(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
if (r == CUBEB_OK) {
assert(value > 0);
}
cubeb_destroy(ctx);
END_TEST
}
static void
test_init_destroy_stream(void)
@ -99,7 +139,7 @@ test_init_destroy_stream(void)
BEGIN_TEST
r = cubeb_init(&ctx, "test_sanity");
r = cubeb_init(&ctx, "test_sanity");
assert(r == 0 && ctx);
params.format = STREAM_FORMAT;
@ -114,7 +154,7 @@ test_init_destroy_stream(void)
cubeb_destroy(ctx);
END_TEST
}
}
static void
test_init_destroy_multiple_streams(void)
@ -127,7 +167,7 @@ test_init_destroy_multiple_streams(void)
BEGIN_TEST
r = cubeb_init(&ctx, "test_sanity");
r = cubeb_init(&ctx, "test_sanity");
assert(r == 0 && ctx);
params.format = STREAM_FORMAT;
@ -148,7 +188,39 @@ test_init_destroy_multiple_streams(void)
cubeb_destroy(ctx);
END_TEST
}
}
static void
test_configure_stream(void)
{
int r;
cubeb * ctx;
cubeb_stream * stream;
cubeb_stream_params params;
BEGIN_TEST
r = cubeb_init(&ctx, "test_sanity");
assert(r == 0 && ctx);
params.format = STREAM_FORMAT;
params.rate = STREAM_RATE;
params.channels = 2; // panning
r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY,
test_data_callback, test_state_callback, &dummy);
assert(r == 0 && stream);
r = cubeb_stream_set_volume(stream, 1.0f);
assert(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
r = cubeb_stream_set_panning(stream, 0.0f);
assert(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
cubeb_stream_destroy(stream);
cubeb_destroy(ctx);
END_TEST
}
static void
test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
@ -161,7 +233,7 @@ test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
BEGIN_TEST
r = cubeb_init(&ctx, "test_sanity");
r = cubeb_init(&ctx, "test_sanity");
assert(r == 0 && ctx);
params.format = STREAM_FORMAT;
@ -209,7 +281,7 @@ test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
cubeb_destroy(ctx);
END_TEST
}
}
static void
test_init_destroy_multiple_contexts_and_streams(void)
@ -224,7 +296,7 @@ test_init_destroy_multiple_contexts_and_streams(void)
BEGIN_TEST
params.format = STREAM_FORMAT;
params.format = STREAM_FORMAT;
params.rate = STREAM_RATE;
params.channels = STREAM_CHANNELS;
@ -248,7 +320,7 @@ test_init_destroy_multiple_contexts_and_streams(void)
}
END_TEST
}
}
static void
test_basic_stream_operations(void)
@ -261,7 +333,7 @@ test_basic_stream_operations(void)
BEGIN_TEST
r = cubeb_init(&ctx, "test_sanity");
r = cubeb_init(&ctx, "test_sanity");
assert(r == 0 && ctx);
params.format = STREAM_FORMAT;
@ -294,7 +366,7 @@ test_basic_stream_operations(void)
cubeb_destroy(ctx);
END_TEST
}
}
static void
test_stream_position(void)
@ -308,7 +380,7 @@ test_stream_position(void)
BEGIN_TEST
total_frames_written = 0;
total_frames_written = 0;
r = cubeb_init(&ctx, "test_sanity");
assert(r == 0 && ctx);
@ -384,7 +456,7 @@ test_stream_position(void)
cubeb_destroy(ctx);
END_TEST
}
}
static int do_drain;
static int got_drain;
@ -424,7 +496,7 @@ test_drain(void)
BEGIN_TEST
total_frames_written = 0;
total_frames_written = 0;
r = cubeb_init(&ctx, "test_sanity");
assert(r == 0 && ctx);
@ -467,30 +539,30 @@ test_drain(void)
cubeb_destroy(ctx);
END_TEST
}
}
int is_windows_7()
{
#ifdef __MINGW32__
printf("Warning: this test was built with MinGW.\n"
"MinGW does not contain necessary version checking infrastructure. Claiming to be Windows 7, even if we're not.\n");
return 1;
printf("Warning: this test was built with MinGW.\n"
"MinGW does not contain necessary version checking infrastructure. Claiming to be Windows 7, even if we're not.\n");
return 1;
#endif
#if (defined(_WIN32) || defined(__WIN32__)) && ( !defined(__MINGW32__))
OSVERSIONINFOEX osvi;
DWORDLONG condition_mask = 0;
OSVERSIONINFOEX osvi;
DWORDLONG condition_mask = 0;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
// NT 6.1 is Windows 7
osvi.dwMajorVersion = 6;
osvi.dwMinorVersion = 1;
// NT 6.1 is Windows 7
osvi.dwMajorVersion = 6;
osvi.dwMinorVersion = 1;
VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, VER_EQUAL);
VER_SET_CONDITION(condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, VER_EQUAL);
VER_SET_CONDITION(condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL);
return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, condition_mask);
return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, condition_mask);
#else
return 0;
#endif
@ -501,8 +573,10 @@ main(int argc, char * argv[])
{
test_init_destroy_context();
test_init_destroy_multiple_contexts();
test_context_variables();
test_init_destroy_stream();
test_init_destroy_multiple_streams();
test_configure_stream();
test_basic_stream_operations();
test_stream_position();

View File

@ -57,14 +57,14 @@ void state_cb(cubeb_stream *stream, void *user, cubeb_state state)
return;
switch (state) {
case CUBEB_STATE_STARTED:
printf("stream started\n"); break;
case CUBEB_STATE_STOPPED:
printf("stream stopped\n"); break;
case CUBEB_STATE_DRAINED:
printf("stream drained\n"); break;
default:
printf("unknown stream state %d\n", state);
case CUBEB_STATE_STARTED:
printf("stream started\n"); break;
case CUBEB_STATE_STOPPED:
printf("stream stopped\n"); break;
case CUBEB_STATE_DRAINED:
printf("stream drained\n"); break;
default:
printf("unknown stream state %d\n", state);
}
return;
@ -76,12 +76,12 @@ int main(int argc, char *argv[])
cubeb_stream *stream;
cubeb_stream_params params;
struct cb_user_data *user_data;
int ret;
int r;
ret = cubeb_init(&ctx, "Cubeb tone example");
if (ret != CUBEB_OK) {
r = cubeb_init(&ctx, "Cubeb tone example");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
return ret;
return r;
}
params.format = CUBEB_SAMPLE_S16NE;
@ -95,11 +95,11 @@ int main(int argc, char *argv[])
}
user_data->position = 0;
ret = cubeb_stream_init(ctx, &stream, "Cubeb tone (mono)", params,
250, data_cb, state_cb, user_data);
if (ret != CUBEB_OK) {
r = cubeb_stream_init(ctx, &stream, "Cubeb tone (mono)", params,
250, data_cb, state_cb, user_data);
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb stream\n");
return ret;
return r;
}
cubeb_stream_start(stream);