diff options
Diffstat (limited to 'media/libcubeb/src/cubeb.c')
-rw-r--r-- | media/libcubeb/src/cubeb.c | 477 |
1 files changed, 165 insertions, 312 deletions
diff --git a/media/libcubeb/src/cubeb.c b/media/libcubeb/src/cubeb.c index b3d32eea3d..a239319a46 100644 --- a/media/libcubeb/src/cubeb.c +++ b/media/libcubeb/src/cubeb.c @@ -5,121 +5,88 @@ * accompanying file LICENSE for details. */ #undef NDEBUG -#include "cubeb/cubeb.h" -#include "cubeb-internal.h" #include <assert.h> #include <stddef.h> #include <stdlib.h> -#include <string.h> +#include "cubeb/cubeb.h" +#include "cubeb-internal.h" -#define NELEMS(x) ((int)(sizeof(x) / sizeof(x[0]))) +#define NELEMS(x) ((int) (sizeof(x) / sizeof(x[0]))) + +cubeb_log_level g_log_level; +cubeb_log_callback g_log_callback; struct cubeb { struct cubeb_ops * ops; }; struct cubeb_stream { - /* - * Note: All implementations of cubeb_stream must keep the following - * layout. - */ struct cubeb * context; - void * user_ptr; }; #if defined(USE_PULSE) -int -pulse_init(cubeb ** context, char const * context_name); -#endif -#if defined(USE_PULSE_RUST) -int -pulse_rust_init(cubeb ** contet, char const * context_name); +int pulse_init(cubeb ** context, char const * context_name); #endif #if defined(USE_JACK) -int -jack_init(cubeb ** context, char const * context_name); +int jack_init (cubeb ** context, char const * context_name); #endif #if defined(USE_ALSA) -int -alsa_init(cubeb ** context, char const * context_name); +int alsa_init(cubeb ** context, char const * context_name); #endif #if defined(USE_AUDIOUNIT) -int -audiounit_init(cubeb ** context, char const * context_name); -#endif -#if defined(USE_AUDIOUNIT_RUST) -int -audiounit_rust_init(cubeb ** contet, char const * context_name); +int audiounit_init(cubeb ** context, char const * context_name); #endif #if defined(USE_WINMM) -int -winmm_init(cubeb ** context, char const * context_name); +int winmm_init(cubeb ** context, char const * context_name); #endif #if defined(USE_WASAPI) -int -wasapi_init(cubeb ** context, char const * context_name); +int wasapi_init(cubeb ** context, char const * context_name); #endif #if defined(USE_SNDIO) -int -sndio_init(cubeb ** context, char const * context_name); -#endif -#if defined(USE_SUN) -int -sun_init(cubeb ** context, char const * context_name); +int sndio_init(cubeb ** context, char const * context_name); #endif #if defined(USE_OPENSL) -int -opensl_init(cubeb ** context, char const * context_name); -#endif -#if defined(USE_OSS) -int -oss_init(cubeb ** context, char const * context_name); -#endif -#if defined(USE_AAUDIO) -int -aaudio_init(cubeb ** context, char const * context_name); +int opensl_init(cubeb ** context, char const * context_name); #endif #if defined(USE_AUDIOTRACK) -int -audiotrack_init(cubeb ** context, char const * context_name); +int audiotrack_init(cubeb ** context, char const * context_name); #endif #if defined(USE_KAI) -int -kai_init(cubeb ** context, char const * context_name); +int kai_init(cubeb ** context, char const * context_name); +#endif +#if defined(USE_SUN) +int sunaudio_init(cubeb ** context, char const * context_name); #endif + static int validate_stream_params(cubeb_stream_params * input_stream_params, cubeb_stream_params * output_stream_params) { XASSERT(input_stream_params || output_stream_params); if (output_stream_params) { - if (output_stream_params->rate < 1000 || - output_stream_params->rate > 192000 || - output_stream_params->channels < 1 || - output_stream_params->channels > UINT8_MAX) { + if (output_stream_params->rate < 1000 || output_stream_params->rate > 192000 || + output_stream_params->channels < 1 || output_stream_params->channels > 8) { return CUBEB_ERROR_INVALID_FORMAT; } } if (input_stream_params) { - if (input_stream_params->rate < 1000 || - input_stream_params->rate > 192000 || - input_stream_params->channels < 1 || - input_stream_params->channels > UINT8_MAX) { + if (input_stream_params->rate < 1000 || input_stream_params->rate > 192000 || + input_stream_params->channels < 1 || input_stream_params->channels > 8) { return CUBEB_ERROR_INVALID_FORMAT; } } // Rate and sample format must be the same for input and output, if using a // duplex stream if (input_stream_params && output_stream_params) { - if (input_stream_params->rate != output_stream_params->rate || + if (input_stream_params->rate != output_stream_params->rate || input_stream_params->format != output_stream_params->format) { return CUBEB_ERROR_INVALID_FORMAT; } } - cubeb_stream_params * params = - input_stream_params ? input_stream_params : output_stream_params; + cubeb_stream_params * params = input_stream_params ? + input_stream_params : output_stream_params; switch (params->format) { case CUBEB_SAMPLE_S16LE: @@ -132,6 +99,8 @@ validate_stream_params(cubeb_stream_params * input_stream_params, return CUBEB_ERROR_INVALID_FORMAT; } + + static int validate_latency(int latency) { @@ -142,104 +111,18 @@ validate_latency(int latency) } int -cubeb_init(cubeb ** context, char const * context_name, - char const * backend_name) +cubeb_init(cubeb ** context, char const * context_name) { - int (*init_oneshot)(cubeb **, char const *) = NULL; - - if (backend_name != NULL) { - if (!strcmp(backend_name, "pulse")) { -#if defined(USE_PULSE) - init_oneshot = pulse_init; -#endif - } else if (!strcmp(backend_name, "pulse-rust")) { -#if defined(USE_PULSE_RUST) - init_oneshot = pulse_rust_init; -#endif - } else if (!strcmp(backend_name, "jack")) { + int (* init[])(cubeb **, char const *) = { #if defined(USE_JACK) - init_oneshot = jack_init; -#endif - } else if (!strcmp(backend_name, "alsa")) { -#if defined(USE_ALSA) - init_oneshot = alsa_init; -#endif - } else if (!strcmp(backend_name, "audiounit")) { -#if defined(USE_AUDIOUNIT) - init_oneshot = audiounit_init; -#endif - } else if (!strcmp(backend_name, "audiounit-rust")) { -#if defined(USE_AUDIOUNIT_RUST) - init_oneshot = audiounit_rust_init; -#endif - } else if (!strcmp(backend_name, "wasapi")) { -#if defined(USE_WASAPI) - init_oneshot = wasapi_init; -#endif - } else if (!strcmp(backend_name, "winmm")) { -#if defined(USE_WINMM) - init_oneshot = winmm_init; -#endif - } else if (!strcmp(backend_name, "sndio")) { -#if defined(USE_SNDIO) - init_oneshot = sndio_init; -#endif - } else if (!strcmp(backend_name, "sun")) { -#if defined(USE_SUN) - init_oneshot = sun_init; -#endif - } else if (!strcmp(backend_name, "opensl")) { -#if defined(USE_OPENSL) - init_oneshot = opensl_init; -#endif - } else if (!strcmp(backend_name, "oss")) { -#if defined(USE_OSS) - init_oneshot = oss_init; -#endif - } else if (!strcmp(backend_name, "aaudio")) { -#if defined(USE_AAUDIO) - init_oneshot = aaudio_init; -#endif - } else if (!strcmp(backend_name, "audiotrack")) { -#if defined(USE_AUDIOTRACK) - init_oneshot = audiotrack_init; -#endif - } else if (!strcmp(backend_name, "kai")) { -#if defined(USE_KAI) - init_oneshot = kai_init; -#endif - } else { - /* Already set */ - } - } - - int (*default_init[])(cubeb **, char const *) = { - /* - * init_oneshot must be at the top to allow user - * to override all other choices - */ - init_oneshot, -#if defined(USE_PULSE_RUST) - pulse_rust_init, + jack_init, #endif #if defined(USE_PULSE) pulse_init, #endif -#if defined(USE_JACK) - jack_init, -#endif -#if defined(USE_SNDIO) - sndio_init, -#endif #if defined(USE_ALSA) alsa_init, #endif -#if defined(USE_OSS) - oss_init, -#endif -#if defined(USE_AUDIOUNIT_RUST) - audiounit_rust_init, -#endif #if defined(USE_AUDIOUNIT) audiounit_init, #endif @@ -249,23 +132,21 @@ cubeb_init(cubeb ** context, char const * context_name, #if defined(USE_WINMM) winmm_init, #endif -#if defined(USE_SUN) - sun_init, +#if defined(USE_SNDIO) + sndio_init, #endif #if defined(USE_OPENSL) opensl_init, #endif - // TODO: should probably be preferred over OpenSLES when available. - // Initialization will fail on old android devices. -#if defined(USE_AAUDIO) - aaudio_init, -#endif #if defined(USE_AUDIOTRACK) audiotrack_init, #endif #if defined(USE_KAI) kai_init, #endif +#if defined(USE_SUN) + sunaudio_init, +#endif }; int i; @@ -273,10 +154,10 @@ cubeb_init(cubeb ** context, char const * context_name, return CUBEB_ERROR_INVALID_PARAMETER; } -#define OK(fn) assert((*context)->ops->fn) - for (i = 0; i < NELEMS(default_init); ++i) { - if (default_init[i] && default_init[i](context, context_name) == CUBEB_OK) { + 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); @@ -287,6 +168,7 @@ cubeb_init(cubeb ** context, char const * context_name, return CUBEB_OK; } } + return CUBEB_ERROR; } @@ -315,10 +197,9 @@ cubeb_get_max_channel_count(cubeb * context, uint32_t * max_channels) } int -cubeb_get_min_latency(cubeb * context, cubeb_stream_params * params, - uint32_t * latency_ms) +cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * latency_ms) { - if (!context || !params || !latency_ms) { + if (!context || !latency_ms) { return CUBEB_ERROR_INVALID_PARAMETER; } @@ -326,7 +207,7 @@ cubeb_get_min_latency(cubeb * context, cubeb_stream_params * params, return CUBEB_ERROR_NOT_SUPPORTED; } - return context->ops->get_min_latency(context, *params, latency_ms); + return context->ops->get_min_latency(context, params, latency_ms); } int @@ -354,39 +235,36 @@ cubeb_destroy(cubeb * context) } int -cubeb_stream_init(cubeb * context, cubeb_stream ** stream, - char const * stream_name, cubeb_devid input_device, +cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name, + cubeb_devid input_device, cubeb_stream_params * input_stream_params, cubeb_devid output_device, cubeb_stream_params * output_stream_params, - unsigned int latency, cubeb_data_callback data_callback, - cubeb_state_callback state_callback, void * user_ptr) + unsigned int latency, + cubeb_data_callback data_callback, + cubeb_state_callback state_callback, + void * user_ptr) { int r; - if (!context || !stream || !data_callback || !state_callback) { + if (!context || !stream) { return CUBEB_ERROR_INVALID_PARAMETER; } - if ((r = validate_stream_params(input_stream_params, output_stream_params)) != - CUBEB_OK || + if ((r = validate_stream_params(input_stream_params, output_stream_params)) != CUBEB_OK || (r = validate_latency(latency)) != CUBEB_OK) { return r; } - r = context->ops->stream_init(context, stream, stream_name, input_device, - input_stream_params, output_device, - output_stream_params, latency, data_callback, - state_callback, user_ptr); - - if (r == CUBEB_ERROR_INVALID_FORMAT) { - LOG("Invalid format, %p %p %d %d", output_stream_params, - input_stream_params, - output_stream_params && output_stream_params->format, - input_stream_params && input_stream_params->format); - } - - return r; + return context->ops->stream_init(context, stream, stream_name, + input_device, + input_stream_params, + output_device, + output_stream_params, + latency, + data_callback, + state_callback, + user_ptr); } void @@ -444,20 +322,6 @@ cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency) } int -cubeb_stream_get_input_latency(cubeb_stream * stream, uint32_t * latency) -{ - if (!stream || !latency) { - return CUBEB_ERROR_INVALID_PARAMETER; - } - - if (!stream->context->ops->stream_get_input_latency) { - return CUBEB_ERROR_NOT_SUPPORTED; - } - - return stream->context->ops->stream_get_input_latency(stream, latency); -} - -int cubeb_stream_set_volume(cubeb_stream * stream, float volume) { if (!stream || volume > 1.0 || volume < 0.0) { @@ -471,23 +335,21 @@ cubeb_stream_set_volume(cubeb_stream * stream, float volume) return stream->context->ops->stream_set_volume(stream, volume); } -int -cubeb_stream_set_name(cubeb_stream * stream, char const * stream_name) +int cubeb_stream_set_panning(cubeb_stream * stream, float panning) { - if (!stream || !stream_name) { + if (!stream || panning < -1.0 || panning > 1.0) { return CUBEB_ERROR_INVALID_PARAMETER; } - if (!stream->context->ops->stream_set_name) { + if (!stream->context->ops->stream_set_panning) { return CUBEB_ERROR_NOT_SUPPORTED; } - return stream->context->ops->stream_set_name(stream, stream_name); + return stream->context->ops->stream_set_panning(stream, panning); } -int -cubeb_stream_get_current_device(cubeb_stream * stream, - cubeb_device ** const device) +int cubeb_stream_get_current_device(cubeb_stream * stream, + cubeb_device ** const device) { if (!stream || !device) { return CUBEB_ERROR_INVALID_PARAMETER; @@ -500,8 +362,8 @@ cubeb_stream_get_current_device(cubeb_stream * stream, return stream->context->ops->stream_get_current_device(stream, device); } -int -cubeb_stream_device_destroy(cubeb_stream * stream, cubeb_device * device) +int cubeb_stream_device_destroy(cubeb_stream * stream, + cubeb_device * device) { if (!stream || !device) { return CUBEB_ERROR_INVALID_PARAMETER; @@ -514,10 +376,8 @@ cubeb_stream_device_destroy(cubeb_stream * stream, cubeb_device * device) return stream->context->ops->stream_device_destroy(stream, device); } -int -cubeb_stream_register_device_changed_callback( - cubeb_stream * stream, - cubeb_device_changed_callback device_changed_callback) +int cubeb_stream_register_device_changed_callback(cubeb_stream * stream, + cubeb_device_changed_callback device_changed_callback) { if (!stream) { return CUBEB_ERROR_INVALID_PARAMETER; @@ -527,70 +387,59 @@ cubeb_stream_register_device_changed_callback( return CUBEB_ERROR_NOT_SUPPORTED; } - return stream->context->ops->stream_register_device_changed_callback( - stream, device_changed_callback); + return stream->context->ops->stream_register_device_changed_callback(stream, device_changed_callback); } -void * -cubeb_stream_user_ptr(cubeb_stream * stream) -{ - if (!stream) { - return NULL; - } - - return stream->user_ptr; -} - -static void -log_device(cubeb_device_info * device_info) +static +void log_device(cubeb_device_info * device_info) { char devfmts[128] = ""; - const char *devtype, *devstate, *devdeffmt; + const char * devtype, * devstate, * devdeffmt; switch (device_info->type) { - case CUBEB_DEVICE_TYPE_INPUT: - devtype = "input"; - break; - case CUBEB_DEVICE_TYPE_OUTPUT: - devtype = "output"; - break; - case CUBEB_DEVICE_TYPE_UNKNOWN: - default: - devtype = "unknown?"; - break; + case CUBEB_DEVICE_TYPE_INPUT: + devtype = "input"; + break; + case CUBEB_DEVICE_TYPE_OUTPUT: + devtype = "output"; + break; + case CUBEB_DEVICE_TYPE_UNKNOWN: + default: + devtype = "unknown?"; + break; }; switch (device_info->state) { - case CUBEB_DEVICE_STATE_DISABLED: - devstate = "disabled"; - break; - case CUBEB_DEVICE_STATE_UNPLUGGED: - devstate = "unplugged"; - break; - case CUBEB_DEVICE_STATE_ENABLED: - devstate = "enabled"; - break; - default: - devstate = "unknown?"; - break; + case CUBEB_DEVICE_STATE_DISABLED: + devstate = "disabled"; + break; + case CUBEB_DEVICE_STATE_UNPLUGGED: + devstate = "unplugged"; + break; + case CUBEB_DEVICE_STATE_ENABLED: + devstate = "enabled"; + break; + default: + devstate = "unknown?"; + break; }; switch (device_info->default_format) { - case CUBEB_DEVICE_FMT_S16LE: - devdeffmt = "S16LE"; - break; - case CUBEB_DEVICE_FMT_S16BE: - devdeffmt = "S16BE"; - break; - case CUBEB_DEVICE_FMT_F32LE: - devdeffmt = "F32LE"; - break; - case CUBEB_DEVICE_FMT_F32BE: - devdeffmt = "F32BE"; - break; - default: - devdeffmt = "unknown?"; - break; + case CUBEB_DEVICE_FMT_S16LE: + devdeffmt = "S16LE"; + break; + case CUBEB_DEVICE_FMT_S16BE: + devdeffmt = "S16BE"; + break; + case CUBEB_DEVICE_FMT_F32LE: + devdeffmt = "F32LE"; + break; + case CUBEB_DEVICE_FMT_F32BE: + devdeffmt = "F32BE"; + break; + default: + devdeffmt = "unknown?"; + break; }; if (device_info->format & CUBEB_DEVICE_FMT_S16LE) { @@ -617,17 +466,20 @@ log_device(cubeb_device_info * device_info) "\tRate:\t[%u, %u] (default: %u)\n" "\tLatency: lo %u frames, hi %u frames", device_info->device_id, device_info->preferred ? " (PREFERRED)" : "", - device_info->friendly_name, device_info->group_id, - device_info->vendor_name, devtype, devstate, device_info->max_channels, - (devfmts[0] == '\0') ? devfmts : devfmts + 1, - (unsigned int)device_info->format, devdeffmt, device_info->min_rate, - device_info->max_rate, device_info->default_rate, device_info->latency_lo, - device_info->latency_hi); + device_info->friendly_name, + device_info->group_id, + device_info->vendor_name, + devtype, + devstate, + device_info->max_channels, + (devfmts[0] == '\0') ? devfmts : devfmts + 1, (unsigned int)device_info->format, devdeffmt, + device_info->min_rate, device_info->max_rate, device_info->default_rate, + device_info->latency_lo, device_info->latency_hi); } -int -cubeb_enumerate_devices(cubeb * context, cubeb_device_type devtype, - cubeb_device_collection * collection) +int cubeb_enumerate_devices(cubeb * context, + cubeb_device_type devtype, + cubeb_device_collection ** collection) { int rv; if ((devtype & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) == 0) @@ -639,59 +491,61 @@ cubeb_enumerate_devices(cubeb * context, cubeb_device_type devtype, rv = context->ops->enumerate_devices(context, devtype, collection); - if (g_cubeb_log_callback) { - for (size_t i = 0; i < collection->count; i++) { - log_device(&collection->device[i]); + if (g_log_callback) { + for (uint32_t i = 0; i < (*collection)->count; i++) { + log_device((*collection)->device[i]); } } return rv; } -int -cubeb_device_collection_destroy(cubeb * context, - cubeb_device_collection * collection) +int cubeb_device_collection_destroy(cubeb_device_collection * collection) { - int r; + uint32_t i; - if (context == NULL || collection == NULL) + if (collection == NULL) return CUBEB_ERROR_INVALID_PARAMETER; - if (!context->ops->device_collection_destroy) - return CUBEB_ERROR_NOT_SUPPORTED; + for (i = 0; i < collection->count; i++) + cubeb_device_info_destroy(collection->device[i]); - if (!collection->device) - return CUBEB_OK; + free(collection); + return CUBEB_OK; +} - r = context->ops->device_collection_destroy(context, collection); - if (r == CUBEB_OK) { - collection->device = NULL; - collection->count = 0; +int cubeb_device_info_destroy(cubeb_device_info * info) +{ + if (info == NULL) { + return CUBEB_ERROR_INVALID_PARAMETER; } - return r; + free(info->device_id); + free(info->friendly_name); + free(info->group_id); + free(info->vendor_name); + + free(info); + return CUBEB_OK; } -int -cubeb_register_device_collection_changed( - cubeb * context, cubeb_device_type devtype, - cubeb_device_collection_changed_callback callback, void * user_ptr) +int cubeb_register_device_collection_changed(cubeb * context, + cubeb_device_type devtype, + cubeb_device_collection_changed_callback callback, + void * user_ptr) { - if (context == NULL || - (devtype & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) == 0) + if (context == NULL || (devtype & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) == 0) return CUBEB_ERROR_INVALID_PARAMETER; if (!context->ops->register_device_collection_changed) { return CUBEB_ERROR_NOT_SUPPORTED; } - return context->ops->register_device_collection_changed(context, devtype, - callback, user_ptr); + return context->ops->register_device_collection_changed(context, devtype, callback, user_ptr); } -int -cubeb_set_log_callback(cubeb_log_level log_level, - cubeb_log_callback log_callback) +int cubeb_set_log_callback(cubeb_log_level log_level, + cubeb_log_callback log_callback) { if (log_level < CUBEB_LOG_DISABLED || log_level > CUBEB_LOG_VERBOSE) { return CUBEB_ERROR_INVALID_FORMAT; @@ -701,21 +555,20 @@ cubeb_set_log_callback(cubeb_log_level log_level, return CUBEB_ERROR_INVALID_PARAMETER; } - if (g_cubeb_log_callback && log_callback) { + if (g_log_callback && log_callback) { return CUBEB_ERROR_NOT_SUPPORTED; } - g_cubeb_log_callback = log_callback; - g_cubeb_log_level = log_level; - - // Logging a message here allows to initialize the asynchronous logger from a - // thread that is not the audio rendering thread, and especially to not - // initialize it the first time we find a verbose log, which is often in the - // audio rendering callback, that runs from the audio rendering thread, and - // that is high priority, and that we don't want to block. - if (log_level >= CUBEB_LOG_VERBOSE) { - ALOGV("Starting cubeb log"); - } + g_log_callback = log_callback; + g_log_level = log_level; return CUBEB_OK; } + +void +cubeb_crash() +{ + *((volatile int *) NULL) = 0; + abort(); +} + |