summaryrefslogtreecommitdiffstats
path: root/media/libcubeb/src/cubeb.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libcubeb/src/cubeb.c')
-rw-r--r--media/libcubeb/src/cubeb.c233
1 files changed, 152 insertions, 81 deletions
diff --git a/media/libcubeb/src/cubeb.c b/media/libcubeb/src/cubeb.c
index a239319a4..3ad39dee0 100644
--- a/media/libcubeb/src/cubeb.c
+++ b/media/libcubeb/src/cubeb.c
@@ -8,20 +8,23 @@
#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])))
-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)
@@ -45,6 +48,9 @@ int wasapi_init(cubeb ** context, char const * context_name);
#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);
+#endif
#if defined(USE_OPENSL)
int opensl_init(cubeb ** context, char const * context_name);
#endif
@@ -54,10 +60,6 @@ int audiotrack_init(cubeb ** context, char const * context_name);
#if defined(USE_KAI)
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,
@@ -66,7 +68,7 @@ validate_stream_params(cubeb_stream_params * input_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 > 8) {
+ output_stream_params->channels < 1 || output_stream_params->channels > UINT8_MAX) {
return CUBEB_ERROR_INVALID_FORMAT;
}
}
@@ -99,8 +101,6 @@ validate_stream_params(cubeb_stream_params * input_stream_params,
return CUBEB_ERROR_INVALID_FORMAT;
}
-
-
static int
validate_latency(int latency)
{
@@ -111,15 +111,75 @@ validate_latency(int latency)
}
int
-cubeb_init(cubeb ** context, char const * context_name)
+cubeb_init(cubeb ** context, char const * context_name, char const * backend_name)
{
- int (* init[])(cubeb **, char const *) = {
+ 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, "jack")) {
#if defined(USE_JACK)
- jack_init,
+ 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, "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, "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)
pulse_init,
#endif
+#if defined(USE_JACK)
+ jack_init,
+#endif
+#if defined(USE_SNDIO)
+ sndio_init,
+#endif
#if defined(USE_ALSA)
alsa_init,
#endif
@@ -132,8 +192,8 @@ cubeb_init(cubeb ** context, char const * context_name)
#if defined(USE_WINMM)
winmm_init,
#endif
-#if defined(USE_SNDIO)
- sndio_init,
+#if defined(USE_SUN)
+ sun_init,
#endif
#if defined(USE_OPENSL)
opensl_init,
@@ -144,9 +204,6 @@ cubeb_init(cubeb ** context, char const * context_name)
#if defined(USE_KAI)
kai_init,
#endif
-#if defined(USE_SUN)
- sunaudio_init,
-#endif
};
int i;
@@ -154,10 +211,10 @@ cubeb_init(cubeb ** context, char const * context_name)
return CUBEB_ERROR_INVALID_PARAMETER;
}
- 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)
+ for (i = 0; i < NELEMS(default_init); ++i) {
+ if (default_init[i] && default_init[i](context, context_name) == CUBEB_OK) {
+ /* Assert that the minimal API is implemented. */
OK(get_backend_id);
OK(destroy);
OK(stream_init);
@@ -168,7 +225,6 @@ cubeb_init(cubeb ** context, char const * context_name)
return CUBEB_OK;
}
}
-
return CUBEB_ERROR;
}
@@ -197,9 +253,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 || !latency_ms) {
+ if (!context || !params || !latency_ms) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
@@ -207,7 +263,7 @@ cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * la
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
@@ -247,7 +303,7 @@ cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n
{
int r;
- if (!context || !stream) {
+ if (!context || !stream || !data_callback || !state_callback) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
@@ -256,15 +312,24 @@ cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n
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);
+ 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;
}
void
@@ -298,6 +363,20 @@ cubeb_stream_stop(cubeb_stream * stream)
}
int
+cubeb_stream_reset_default_device(cubeb_stream * stream)
+{
+ if (!stream) {
+ return CUBEB_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!stream->context->ops->stream_reset_default_device) {
+ return CUBEB_ERROR_NOT_SUPPORTED;
+ }
+
+ return stream->context->ops->stream_reset_default_device(stream);
+}
+
+int
cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position)
{
if (!stream || !position) {
@@ -335,19 +414,6 @@ cubeb_stream_set_volume(cubeb_stream * stream, float volume)
return stream->context->ops->stream_set_volume(stream, volume);
}
-int cubeb_stream_set_panning(cubeb_stream * stream, float panning)
-{
- if (!stream || panning < -1.0 || panning > 1.0) {
- 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);
-}
-
int cubeb_stream_get_current_device(cubeb_stream * stream,
cubeb_device ** const device)
{
@@ -390,6 +456,15 @@ int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
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)
{
@@ -479,7 +554,7 @@ void log_device(cubeb_device_info * device_info)
int cubeb_enumerate_devices(cubeb * context,
cubeb_device_type devtype,
- cubeb_device_collection ** collection)
+ cubeb_device_collection * collection)
{
int rv;
if ((devtype & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) == 0)
@@ -491,42 +566,36 @@ int cubeb_enumerate_devices(cubeb * context,
rv = context->ops->enumerate_devices(context, devtype, collection);
- if (g_log_callback) {
- for (uint32_t i = 0; i < (*collection)->count; i++) {
- log_device((*collection)->device[i]);
+ if (g_cubeb_log_callback) {
+ for (size_t i = 0; i < collection->count; i++) {
+ log_device(&collection->device[i]);
}
}
return rv;
}
-int cubeb_device_collection_destroy(cubeb_device_collection * collection)
+int cubeb_device_collection_destroy(cubeb * context,
+ cubeb_device_collection * collection)
{
- uint32_t i;
+ int r;
- if (collection == NULL)
+ if (context == NULL || collection == NULL)
return CUBEB_ERROR_INVALID_PARAMETER;
- for (i = 0; i < collection->count; i++)
- cubeb_device_info_destroy(collection->device[i]);
+ if (!context->ops->device_collection_destroy)
+ return CUBEB_ERROR_NOT_SUPPORTED;
- free(collection);
- return CUBEB_OK;
-}
+ if (!collection->device)
+ return CUBEB_OK;
-int cubeb_device_info_destroy(cubeb_device_info * info)
-{
- if (info == NULL) {
- return CUBEB_ERROR_INVALID_PARAMETER;
+ r = context->ops->device_collection_destroy(context, collection);
+ if (r == CUBEB_OK) {
+ collection->device = NULL;
+ collection->count = 0;
}
- free(info->device_id);
- free(info->friendly_name);
- free(info->group_id);
- free(info->vendor_name);
-
- free(info);
- return CUBEB_OK;
+ return r;
}
int cubeb_register_device_collection_changed(cubeb * context,
@@ -555,20 +624,22 @@ int cubeb_set_log_callback(cubeb_log_level log_level,
return CUBEB_ERROR_INVALID_PARAMETER;
}
- if (g_log_callback && log_callback) {
+ if (g_cubeb_log_callback && log_callback) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
- g_log_callback = log_callback;
- g_log_level = log_level;
+ g_cubeb_log_callback = log_callback;
+ g_cubeb_log_level = log_level;
- return CUBEB_OK;
-}
+ // 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");
+ }
-void
-cubeb_crash()
-{
- *((volatile int *) NULL) = 0;
- abort();
+ return CUBEB_OK;
}