summaryrefslogtreecommitdiff
path: root/media
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2021-08-22 17:39:29 +0000
committerMoonchild <moonchild@palemoon.org>2021-08-22 17:39:29 +0000
commit90a8464e692e815531e31a96519ab830baa93f53 (patch)
tree3b6f8f12b986a4a119c511676861c879fd2d5a0b /media
parent569f071b435756783bfb15fa2881afbba08003c9 (diff)
downloadaura-central-90a8464e692e815531e31a96519ab830baa93f53.tar.gz
Revert "Issue mcp-graveyard/UXP%1806 - Follow-up: Restore PulseAudio support in libcubeb."
This reverts commit 0c2a0f45ec3c337d7fa9d028a8ab3196dcbca60e.
Diffstat (limited to 'media')
-rw-r--r--media/libcubeb/src/cubeb_pulse.c1700
-rw-r--r--media/libcubeb/src/moz.build6
-rwxr-xr-xmedia/libcubeb/update.sh1
3 files changed, 0 insertions, 1707 deletions
diff --git a/media/libcubeb/src/cubeb_pulse.c b/media/libcubeb/src/cubeb_pulse.c
deleted file mode 100644
index 31a2f93d2..000000000
--- a/media/libcubeb/src/cubeb_pulse.c
+++ /dev/null
@@ -1,1700 +0,0 @@
-/*
- * Copyright © 2011 Mozilla Foundation
- *
- * This program is made available under an ISC-style license. See the
- * accompanying file LICENSE for details.
- */
-#undef NDEBUG
-#include "cubeb-internal.h"
-#include "cubeb/cubeb.h"
-#include "cubeb_mixer.h"
-#include "cubeb_strings.h"
-#include <assert.h>
-#include <dlfcn.h>
-#include <pulse/pulseaudio.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef DISABLE_LIBPULSE_DLOPEN
-#define WRAP(x) x
-#else
-#define WRAP(x) cubeb_##x
-#define LIBPULSE_API_VISIT(X) \
- X(pa_channel_map_can_balance) \
- X(pa_channel_map_init) \
- 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_sink_info_list) \
- X(pa_context_get_sink_input_info) \
- X(pa_context_get_source_info_list) \
- 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_proplist_gets) \
- 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) \
- X(pa_stream_set_read_callback) \
- X(pa_stream_connect_record) \
- X(pa_stream_readable_size) \
- X(pa_stream_writable_size) \
- X(pa_stream_peek) \
- X(pa_stream_drop) \
- X(pa_stream_get_buffer_attr) \
- X(pa_stream_get_device_name) \
- X(pa_context_set_subscribe_callback) \
- X(pa_context_subscribe) \
- X(pa_mainloop_api_once) \
- X(pa_get_library_version) \
- X(pa_channel_map_init_auto) \
- X(pa_stream_set_name)
-
-#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x;
-LIBPULSE_API_VISIT(MAKE_TYPEDEF);
-#undef MAKE_TYPEDEF
-#endif
-
-#if PA_CHECK_VERSION(2, 0, 0)
-static int has_pulse_v2 = 0;
-#endif
-
-static struct cubeb_ops const pulse_ops;
-
-struct cubeb_default_sink_info {
- pa_channel_map channel_map;
- uint32_t sample_spec_rate;
- pa_sink_flags_t flags;
-};
-
-struct cubeb {
- struct cubeb_ops const * ops;
- void * libpulse;
- pa_threaded_mainloop * mainloop;
- pa_context * context;
- struct cubeb_default_sink_info * default_sink_info;
- char * context_name;
- int error;
- cubeb_device_collection_changed_callback output_collection_changed_callback;
- void * output_collection_changed_user_ptr;
- cubeb_device_collection_changed_callback input_collection_changed_callback;
- void * input_collection_changed_user_ptr;
- cubeb_strings * device_ids;
-};
-
-struct cubeb_stream {
- /* Note: Must match cubeb_stream layout in cubeb.c. */
- cubeb * context;
- void * user_ptr;
- /**/
- pa_stream * output_stream;
- pa_stream * input_stream;
- cubeb_data_callback data_callback;
- cubeb_state_callback state_callback;
- pa_time_event * drain_timer;
- pa_sample_spec output_sample_spec;
- pa_sample_spec input_sample_spec;
- int shutdown;
- float volume;
- cubeb_state state;
-};
-
-static const float PULSE_NO_GAIN = -1.0;
-
-enum cork_state { UNCORK = 0, CORK = 1 << 0, NOTIFY = 1 << 1 };
-
-static int
-intern_device_id(cubeb * ctx, char const ** id)
-{
- char const * interned;
-
- assert(ctx);
- assert(id);
-
- interned = cubeb_strings_intern(ctx->device_ids, *id);
- if (!interned) {
- return CUBEB_ERROR;
- }
-
- *id = interned;
-
- return CUBEB_OK;
-}
-
-static void
-sink_info_callback(pa_context * context, const pa_sink_info * info, int eol,
- void * u)
-{
- (void)context;
- cubeb * ctx = u;
- if (!eol) {
- free(ctx->default_sink_info);
- ctx->default_sink_info = malloc(sizeof(struct cubeb_default_sink_info));
- memcpy(&ctx->default_sink_info->channel_map, &info->channel_map,
- sizeof(pa_channel_map));
- ctx->default_sink_info->sample_spec_rate = info->sample_spec.rate;
- ctx->default_sink_info->flags = info->flags;
- }
- WRAP(pa_threaded_mainloop_signal)(ctx->mainloop, 0);
-}
-
-static void
-server_info_callback(pa_context * context, const pa_server_info * info,
- void * u)
-{
- pa_operation * o;
- o = WRAP(pa_context_get_sink_info_by_name)(context, info->default_sink_name,
- sink_info_callback, u);
- if (o) {
- WRAP(pa_operation_unref)(o);
- }
-}
-
-static void
-context_state_callback(pa_context * c, void * u)
-{
- cubeb * ctx = u;
- if (!PA_CONTEXT_IS_GOOD(WRAP(pa_context_get_state)(c))) {
- ctx->error = 1;
- }
- WRAP(pa_threaded_mainloop_signal)(ctx->mainloop, 0);
-}
-
-static void
-context_notify_callback(pa_context * c, void * u)
-{
- (void)c;
- cubeb * ctx = u;
- WRAP(pa_threaded_mainloop_signal)(ctx->mainloop, 0);
-}
-
-static void
-stream_success_callback(pa_stream * s, int success, void * u)
-{
- (void)s;
- (void)success;
- cubeb_stream * stm = u;
- WRAP(pa_threaded_mainloop_signal)(stm->context->mainloop, 0);
-}
-
-static void
-stream_state_change_callback(cubeb_stream * stm, cubeb_state s)
-{
- stm->state = s;
- stm->state_callback(stm, stm->user_ptr, s);
-}
-
-static void
-stream_drain_callback(pa_mainloop_api * a, pa_time_event * e,
- struct timeval const * tv, void * u)
-{
- (void)a;
- (void)tv;
- cubeb_stream * stm = u;
- assert(stm->drain_timer == e);
- stream_state_change_callback(stm, CUBEB_STATE_DRAINED);
- /* there's no pa_rttime_free, so use this instead. */
- a->time_free(stm->drain_timer);
- stm->drain_timer = NULL;
- WRAP(pa_threaded_mainloop_signal)(stm->context->mainloop, 0);
-}
-
-static void
-stream_state_callback(pa_stream * s, void * u)
-{
- cubeb_stream * stm = u;
- if (!PA_STREAM_IS_GOOD(WRAP(pa_stream_get_state)(s))) {
- stream_state_change_callback(stm, CUBEB_STATE_ERROR);
- }
- WRAP(pa_threaded_mainloop_signal)(stm->context->mainloop, 0);
-}
-
-static void
-trigger_user_callback(pa_stream * s, void const * input_data, size_t nbytes,
- cubeb_stream * stm)
-{
- void * buffer;
- size_t size;
- int r;
- long got;
- size_t towrite, read_offset;
- size_t frame_size;
-
- frame_size = WRAP(pa_frame_size)(&stm->output_sample_spec);
- assert(nbytes % frame_size == 0);
-
- towrite = nbytes;
- read_offset = 0;
- while (towrite) {
- size = towrite;
- r = WRAP(pa_stream_begin_write)(s, &buffer, &size);
- // Note: this has failed running under rr on occassion - needs
- // investigation.
- assert(r == 0);
- assert(size > 0);
- assert(size % frame_size == 0);
-
- LOGV("Trigger user callback with output buffer size=%zd, read_offset=%zd",
- size, read_offset);
- got = stm->data_callback(stm, stm->user_ptr,
- (uint8_t const *)input_data + read_offset, buffer,
- size / frame_size);
- if (got < 0) {
- WRAP(pa_stream_cancel_write)(s);
- stm->shutdown = 1;
- return;
- }
- // If more iterations move offset of read buffer
- if (input_data) {
- size_t in_frame_size = WRAP(pa_frame_size)(&stm->input_sample_spec);
- read_offset += (size / frame_size) * in_frame_size;
- }
-
- if (stm->volume != PULSE_NO_GAIN) {
- uint32_t samples = size * stm->output_sample_spec.channels / frame_size;
-
- if (stm->output_sample_spec.format == PA_SAMPLE_S16BE ||
- stm->output_sample_spec.format == PA_SAMPLE_S16LE) {
- short * b = buffer;
- for (uint32_t i = 0; i < samples; i++) {
- b[i] *= stm->volume;
- }
- } else {
- float * b = buffer;
- for (uint32_t i = 0; i < samples; i++) {
- b[i] *= stm->volume;
- }
- }
- }
-
- r = WRAP(pa_stream_write)(s, buffer, got * frame_size, NULL, 0,
- PA_SEEK_RELATIVE);
- assert(r == 0);
-
- if ((size_t)got < size / frame_size) {
- pa_usec_t latency = 0;
- r = WRAP(pa_stream_get_latency)(s, &latency, NULL);
- if (r == -PA_ERR_NODATA) {
- /* this needs a better guess. */
- latency = 100 * PA_USEC_PER_MSEC;
- }
- assert(r == 0 || r == -PA_ERR_NODATA);
- /* pa_stream_drain is useless, see PA bug# 866. this is a workaround. */
- /* arbitrary safety margin: double the current latency. */
- assert(!stm->drain_timer);
- stm->drain_timer = WRAP(pa_context_rttime_new)(
- stm->context->context, WRAP(pa_rtclock_now)() + 2 * latency,
- stream_drain_callback, stm);
- stm->shutdown = 1;
- return;
- }
-
- towrite -= size;
- }
-
- assert(towrite == 0);
-}
-
-static int
-read_from_input(pa_stream * s, void const ** buffer, size_t * size)
-{
- size_t readable_size = WRAP(pa_stream_readable_size)(s);
- if (readable_size > 0) {
- if (WRAP(pa_stream_peek)(s, buffer, size) < 0) {
- return -1;
- }
- }
- return readable_size;
-}
-
-static void
-stream_write_callback(pa_stream * s, size_t nbytes, void * u)
-{
- LOGV("Output callback to be written buffer size %zd", nbytes);
- cubeb_stream * stm = u;
- if (stm->shutdown || stm->state != CUBEB_STATE_STARTED) {
- return;
- }
-
- if (!stm->input_stream) {
- // Output/playback only operation.
- // Write directly to output
- assert(!stm->input_stream && stm->output_stream);
- trigger_user_callback(s, NULL, nbytes, stm);
- }
-}
-
-static void
-stream_read_callback(pa_stream * s, size_t nbytes, void * u)
-{
- LOGV("Input callback buffer size %zd", nbytes);
- cubeb_stream * stm = u;
- if (stm->shutdown) {
- return;
- }
-
- void const * read_data = NULL;
- size_t read_size;
- while (read_from_input(s, &read_data, &read_size) > 0) {
- /* read_data can be NULL in case of a hole. */
- if (read_data) {
- size_t in_frame_size = WRAP(pa_frame_size)(&stm->input_sample_spec);
- size_t read_frames = read_size / in_frame_size;
-
- if (stm->output_stream) {
- // input/capture + output/playback operation
- size_t out_frame_size = WRAP(pa_frame_size)(&stm->output_sample_spec);
- size_t write_size = read_frames * out_frame_size;
- // Offer full duplex data for writing
- trigger_user_callback(stm->output_stream, read_data, write_size, stm);
- } else {
- // input/capture only operation. Call callback directly
- long got = stm->data_callback(stm, stm->user_ptr, read_data, NULL,
- read_frames);
- if (got < 0 || (size_t)got != read_frames) {
- WRAP(pa_stream_cancel_write)(s);
- stm->shutdown = 1;
- break;
- }
- }
- }
- if (read_size > 0) {
- WRAP(pa_stream_drop)(s);
- }
-
- if (stm->shutdown) {
- return;
- }
- }
-}
-
-static int
-wait_until_context_ready(cubeb * ctx)
-{
- for (;;) {
- pa_context_state_t state = WRAP(pa_context_get_state)(ctx->context);
- if (!PA_CONTEXT_IS_GOOD(state))
- return -1;
- if (state == PA_CONTEXT_READY)
- break;
- WRAP(pa_threaded_mainloop_wait)(ctx->mainloop);
- }
- return 0;
-}
-
-static int
-wait_until_io_stream_ready(pa_stream * stream, pa_threaded_mainloop * mainloop)
-{
- if (!stream || !mainloop) {
- return -1;
- }
- for (;;) {
- pa_stream_state_t state = WRAP(pa_stream_get_state)(stream);
- if (!PA_STREAM_IS_GOOD(state))
- return -1;
- if (state == PA_STREAM_READY)
- break;
- WRAP(pa_threaded_mainloop_wait)(mainloop);
- }
- return 0;
-}
-
-static int
-wait_until_stream_ready(cubeb_stream * stm)
-{
- if (stm->output_stream &&
- wait_until_io_stream_ready(stm->output_stream, stm->context->mainloop) ==
- -1) {
- return -1;
- }
- if (stm->input_stream &&
- wait_until_io_stream_ready(stm->input_stream, stm->context->mainloop) ==
- -1) {
- return -1;
- }
- return 0;
-}
-
-static int
-operation_wait(cubeb * ctx, pa_stream * stream, pa_operation * o)
-{
- while (WRAP(pa_operation_get_state)(o) == PA_OPERATION_RUNNING) {
- WRAP(pa_threaded_mainloop_wait)(ctx->mainloop);
- if (!PA_CONTEXT_IS_GOOD(WRAP(pa_context_get_state)(ctx->context))) {
- return -1;
- }
- if (stream && !PA_STREAM_IS_GOOD(WRAP(pa_stream_get_state)(stream))) {
- return -1;
- }
- }
- return 0;
-}
-
-static void
-cork_io_stream(cubeb_stream * stm, pa_stream * io_stream, enum cork_state state)
-{
- pa_operation * o;
- if (!io_stream) {
- return;
- }
- o = WRAP(pa_stream_cork)(io_stream, state & CORK, stream_success_callback,
- stm);
- if (o) {
- operation_wait(stm->context, io_stream, o);
- WRAP(pa_operation_unref)(o);
- }
-}
-
-static void
-stream_cork(cubeb_stream * stm, enum cork_state state)
-{
- WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
- cork_io_stream(stm, stm->output_stream, state);
- cork_io_stream(stm, stm->input_stream, state);
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
-
- if (state & NOTIFY) {
- stream_state_change_callback(stm, state & CORK ? CUBEB_STATE_STOPPED
- : CUBEB_STATE_STARTED);
- }
-}
-
-static int
-stream_update_timing_info(cubeb_stream * stm)
-{
- int r = -1;
- pa_operation * o = NULL;
- if (stm->output_stream) {
- o = WRAP(pa_stream_update_timing_info)(stm->output_stream,
- stream_success_callback, stm);
- if (o) {
- r = operation_wait(stm->context, stm->output_stream, o);
- WRAP(pa_operation_unref)(o);
- }
- if (r != 0) {
- return r;
- }
- }
-
- if (stm->input_stream) {
- o = WRAP(pa_stream_update_timing_info)(stm->input_stream,
- stream_success_callback, stm);
- if (o) {
- r = operation_wait(stm->context, stm->input_stream, o);
- WRAP(pa_operation_unref)(o);
- }
- }
-
- return r;
-}
-
-static pa_channel_position_t
-cubeb_channel_to_pa_channel(cubeb_channel channel)
-{
- switch (channel) {
- case CHANNEL_FRONT_LEFT:
- return PA_CHANNEL_POSITION_FRONT_LEFT;
- case CHANNEL_FRONT_RIGHT:
- return PA_CHANNEL_POSITION_FRONT_RIGHT;
- case CHANNEL_FRONT_CENTER:
- return PA_CHANNEL_POSITION_FRONT_CENTER;
- case CHANNEL_LOW_FREQUENCY:
- return PA_CHANNEL_POSITION_LFE;
- case CHANNEL_BACK_LEFT:
- return PA_CHANNEL_POSITION_REAR_LEFT;
- case CHANNEL_BACK_RIGHT:
- return PA_CHANNEL_POSITION_REAR_RIGHT;
- case CHANNEL_FRONT_LEFT_OF_CENTER:
- return PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
- case CHANNEL_FRONT_RIGHT_OF_CENTER:
- return PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
- case CHANNEL_BACK_CENTER:
- return PA_CHANNEL_POSITION_REAR_CENTER;
- case CHANNEL_SIDE_LEFT:
- return PA_CHANNEL_POSITION_SIDE_LEFT;
- case CHANNEL_SIDE_RIGHT:
- return PA_CHANNEL_POSITION_SIDE_RIGHT;
- case CHANNEL_TOP_CENTER:
- return PA_CHANNEL_POSITION_TOP_CENTER;
- case CHANNEL_TOP_FRONT_LEFT:
- return PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
- case CHANNEL_TOP_FRONT_CENTER:
- return PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
- case CHANNEL_TOP_FRONT_RIGHT:
- return PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
- case CHANNEL_TOP_BACK_LEFT:
- return PA_CHANNEL_POSITION_TOP_REAR_LEFT;
- case CHANNEL_TOP_BACK_CENTER:
- return PA_CHANNEL_POSITION_TOP_REAR_CENTER;
- case CHANNEL_TOP_BACK_RIGHT:
- return PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
- default:
- return PA_CHANNEL_POSITION_INVALID;
- }
-}
-
-static void
-layout_to_channel_map(cubeb_channel_layout layout, pa_channel_map * cm)
-{
- assert(cm && layout != CUBEB_LAYOUT_UNDEFINED);
-
- WRAP(pa_channel_map_init)(cm);
-
- uint32_t channels = 0;
- cubeb_channel_layout channelMap = layout;
- for (uint32_t i = 0; channelMap != 0; ++i) {
- uint32_t channel = (channelMap & 1) << i;
- if (channel != 0) {
- cm->map[channels] = cubeb_channel_to_pa_channel(channel);
- channels++;
- }
- channelMap = channelMap >> 1;
- }
- unsigned int channels_from_layout = cubeb_channel_layout_nb_channels(layout);
- assert(channels_from_layout <= UINT8_MAX);
- cm->channels = (uint8_t)channels_from_layout;
-
- // Special case single channel center mapping as mono.
- if (cm->channels == 1 && cm->map[0] == PA_CHANNEL_POSITION_FRONT_CENTER) {
- cm->map[0] = PA_CHANNEL_POSITION_MONO;
- }
-}
-
-static void
-pulse_context_destroy(cubeb * ctx);
-static void
-pulse_destroy(cubeb * ctx);
-
-static int
-pulse_context_init(cubeb * ctx)
-{
- int r;
-
- if (ctx->context) {
- assert(ctx->error == 1);
- pulse_context_destroy(ctx);
- }
-
- ctx->context = WRAP(pa_context_new)(
- WRAP(pa_threaded_mainloop_get_api)(ctx->mainloop), ctx->context_name);
- if (!ctx->context) {
- return -1;
- }
- WRAP(pa_context_set_state_callback)
- (ctx->context, context_state_callback, ctx);
-
- WRAP(pa_threaded_mainloop_lock)(ctx->mainloop);
- r = WRAP(pa_context_connect)(ctx->context, NULL, 0, NULL);
-
- if (r < 0 || wait_until_context_ready(ctx) != 0) {
- WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
- pulse_context_destroy(ctx);
- ctx->context = NULL;
- return -1;
- }
-
- WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
-
- ctx->error = 0;
-
- return 0;
-}
-
-static int
-pulse_subscribe_notifications(cubeb * context, pa_subscription_mask_t mask);
-
-/*static*/ int
-pulse_init(cubeb ** context, char const * context_name)
-{
- void * libpulse = NULL;
- cubeb * ctx;
- pa_operation * o;
-
- *context = NULL;
-
-#ifndef DISABLE_LIBPULSE_DLOPEN
- libpulse = dlopen("libpulse.so.0", RTLD_LAZY);
- if (!libpulse) {
- libpulse = dlopen("libpulse.so", RTLD_LAZY);
- if (!libpulse) {
- return CUBEB_ERROR;
- }
- }
-
-#define LOAD(x) \
- { \
- cubeb_##x = dlsym(libpulse, #x); \
- if (!cubeb_##x) { \
- dlclose(libpulse); \
- return CUBEB_ERROR; \
- } \
- }
-
- LIBPULSE_API_VISIT(LOAD);
-#undef LOAD
-#endif
-
-#if PA_CHECK_VERSION(2, 0, 0)
- const char * version = WRAP(pa_get_library_version)();
- has_pulse_v2 = strtol(version, NULL, 10) >= 2;
-#endif
-
- ctx = calloc(1, sizeof(*ctx));
- assert(ctx);
-
- ctx->ops = &pulse_ops;
- ctx->libpulse = libpulse;
- if (cubeb_strings_init(&ctx->device_ids) != CUBEB_OK) {
- pulse_destroy(ctx);
- return CUBEB_ERROR;
- }
-
- ctx->mainloop = WRAP(pa_threaded_mainloop_new)();
- ctx->default_sink_info = NULL;
-
- WRAP(pa_threaded_mainloop_start)(ctx->mainloop);
-
- ctx->context_name = context_name ? strdup(context_name) : NULL;
- if (pulse_context_init(ctx) != 0) {
- pulse_destroy(ctx);
- return CUBEB_ERROR;
- }
-
- /* server_info_callback performs a second async query, which is
- responsible for initializing default_sink_info and signalling the
- mainloop to end the wait. */
- WRAP(pa_threaded_mainloop_lock)(ctx->mainloop);
- o = WRAP(pa_context_get_server_info)(ctx->context, server_info_callback, ctx);
- if (o) {
- operation_wait(ctx, NULL, o);
- WRAP(pa_operation_unref)(o);
- }
- WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
-
- /* Update `default_sink_info` when the default device changes. */
- pulse_subscribe_notifications(ctx, PA_SUBSCRIPTION_MASK_SERVER);
-
- *context = ctx;
-
- return CUBEB_OK;
-}
-
-static char const *
-pulse_get_backend_id(cubeb * ctx)
-{
- (void)ctx;
- return "pulse";
-}
-
-static int
-pulse_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
-{
- (void)ctx;
- assert(ctx && max_channels);
-
- if (!ctx->default_sink_info)
- return CUBEB_ERROR;
-
- *max_channels = ctx->default_sink_info->channel_map.channels;
-
- return CUBEB_OK;
-}
-
-static int
-pulse_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
-{
- assert(ctx && rate);
- (void)ctx;
-
- if (!ctx->default_sink_info)
- return CUBEB_ERROR;
-
- *rate = ctx->default_sink_info->sample_spec_rate;
-
- return CUBEB_OK;
-}
-
-static int
-pulse_get_min_latency(cubeb * ctx, cubeb_stream_params params,
- uint32_t * latency_frames)
-{
- (void)ctx;
- // According to PulseAudio developers, this is a safe minimum.
- *latency_frames = 25 * params.rate / 1000;
-
- return CUBEB_OK;
-}
-
-static void
-pulse_context_destroy(cubeb * ctx)
-{
- pa_operation * o;
-
- WRAP(pa_threaded_mainloop_lock)(ctx->mainloop);
- o = WRAP(pa_context_drain)(ctx->context, context_notify_callback, ctx);
- if (o) {
- operation_wait(ctx, NULL, o);
- WRAP(pa_operation_unref)(o);
- }
- WRAP(pa_context_set_state_callback)(ctx->context, NULL, NULL);
- WRAP(pa_context_disconnect)(ctx->context);
- WRAP(pa_context_unref)(ctx->context);
- WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
-}
-
-static void
-pulse_destroy(cubeb * ctx)
-{
- free(ctx->context_name);
- if (ctx->context) {
- pulse_context_destroy(ctx);
- }
-
- if (ctx->mainloop) {
- WRAP(pa_threaded_mainloop_stop)(ctx->mainloop);
- WRAP(pa_threaded_mainloop_free)(ctx->mainloop);
- }
-
- if (ctx->device_ids) {
- cubeb_strings_destroy(ctx->device_ids);
- }
-
- if (ctx->libpulse) {
- dlclose(ctx->libpulse);
- }
- free(ctx->default_sink_info);
- free(ctx);
-}
-
-static void
-pulse_stream_destroy(cubeb_stream * stm);
-
-static pa_sample_format_t
-to_pulse_format(cubeb_sample_format format)
-{
- switch (format) {
- case CUBEB_SAMPLE_S16LE:
- return PA_SAMPLE_S16LE;
- case CUBEB_SAMPLE_S16BE:
- return PA_SAMPLE_S16BE;
- case CUBEB_SAMPLE_FLOAT32LE:
- return PA_SAMPLE_FLOAT32LE;
- case CUBEB_SAMPLE_FLOAT32BE:
- return PA_SAMPLE_FLOAT32BE;
- default:
- return PA_SAMPLE_INVALID;
- }
-}
-
-static cubeb_channel_layout
-pulse_default_layout_for_channels(uint32_t ch)
-{
- assert(ch > 0 && ch <= 8);
- switch (ch) {
- case 1:
- return CUBEB_LAYOUT_MONO;
- case 2:
- return CUBEB_LAYOUT_STEREO;
- case 3:
- return CUBEB_LAYOUT_3F;
- case 4:
- return CUBEB_LAYOUT_QUAD;
- case 5:
- return CUBEB_LAYOUT_3F2;
- case 6:
- return CUBEB_LAYOUT_3F_LFE | CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT;
- case 7:
- return CUBEB_LAYOUT_3F3R_LFE;
- case 8:
- return CUBEB_LAYOUT_3F4_LFE;
- }
- // Never get here!
- return CUBEB_LAYOUT_UNDEFINED;
-}
-
-static int
-create_pa_stream(cubeb_stream * stm, pa_stream ** pa_stm,
- cubeb_stream_params * stream_params, char const * stream_name)
-{
- assert(stm && stream_params);
- assert(&stm->input_stream == pa_stm ||
- (&stm->output_stream == pa_stm &&
- (stream_params->layout == CUBEB_LAYOUT_UNDEFINED ||
- (stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
- cubeb_channel_layout_nb_channels(stream_params->layout) ==
- stream_params->channels))));
- if (stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) {
- return CUBEB_ERROR_NOT_SUPPORTED;
- }
- *pa_stm = NULL;
- pa_sample_spec ss;
- ss.format = to_pulse_format(stream_params->format);
- if (ss.format == PA_SAMPLE_INVALID)
- return CUBEB_ERROR_INVALID_FORMAT;
- ss.rate = stream_params->rate;
- if (stream_params->channels > UINT8_MAX)
- return CUBEB_ERROR_INVALID_FORMAT;
- ss.channels = (uint8_t)stream_params->channels;
-
- if (stream_params->layout == CUBEB_LAYOUT_UNDEFINED) {
- pa_channel_map cm;
- if (stream_params->channels <= 8 &&
- !WRAP(pa_channel_map_init_auto)(&cm, stream_params->channels,
- PA_CHANNEL_MAP_DEFAULT)) {
- LOG("Layout undefined and PulseAudio's default layout has not been "
- "configured, guess one.");
- layout_to_channel_map(
- pulse_default_layout_for_channels(stream_params->channels), &cm);
- *pa_stm =
- WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, &cm);
- } else {
- LOG("Layout undefined, PulseAudio will use its default.");
- *pa_stm =
- WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, NULL);
- }
- } else {
- pa_channel_map cm;
- layout_to_channel_map(stream_params->layout, &cm);
- *pa_stm = WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, &cm);
- }
- return (*pa_stm == NULL) ? CUBEB_ERROR : CUBEB_OK;
-}
-
-static pa_buffer_attr
-set_buffering_attribute(unsigned int latency_frames,
- pa_sample_spec * sample_spec)
-{
- pa_buffer_attr battr;
- battr.maxlength = -1;
- battr.prebuf = -1;
- battr.tlength = latency_frames * WRAP(pa_frame_size)(sample_spec);
- battr.minreq = battr.tlength / 4;
- battr.fragsize = battr.minreq;
-
- LOG("Requested buffer attributes maxlength %u, tlength %u, prebuf %u, minreq "
- "%u, fragsize %u",
- battr.maxlength, battr.tlength, battr.prebuf, battr.minreq,
- battr.fragsize);
-
- return battr;
-}
-
-static int
-pulse_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_frames,
- cubeb_data_callback data_callback,
- cubeb_state_callback state_callback, void * user_ptr)
-{
- cubeb_stream * stm;
- pa_buffer_attr battr;
- int r;
-
- assert(context);
-
- // If the connection failed for some reason, try to reconnect
- if (context->error == 1 && pulse_context_init(context) != 0) {
- return CUBEB_ERROR;
- }
-
- *stream = NULL;
-
- stm = calloc(1, sizeof(*stm));
- assert(stm);
-
- stm->context = context;
- stm->data_callback = data_callback;
- stm->state_callback = state_callback;
- stm->user_ptr = user_ptr;
- stm->volume = PULSE_NO_GAIN;
- stm->state = -1;
- assert(stm->shutdown == 0);
-
- WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
- if (output_stream_params) {
- r = create_pa_stream(stm, &stm->output_stream, output_stream_params,
- stream_name);
- if (r != CUBEB_OK) {
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
- pulse_stream_destroy(stm);
- return r;
- }
-
- stm->output_sample_spec =
- *(WRAP(pa_stream_get_sample_spec)(stm->output_stream));
-
- WRAP(pa_stream_set_state_callback)
- (stm->output_stream, stream_state_callback, stm);
- WRAP(pa_stream_set_write_callback)
- (stm->output_stream, stream_write_callback, stm);
-
- battr = set_buffering_attribute(latency_frames, &stm->output_sample_spec);
- WRAP(pa_stream_connect_playback)
- (stm->output_stream, (char const *)output_device, &battr,
- PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
- PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY,
- NULL, NULL);
- }
-
- // Set up input stream
- if (input_stream_params) {
- r = create_pa_stream(stm, &stm->input_stream, input_stream_params,
- stream_name);
- if (r != CUBEB_OK) {
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
- pulse_stream_destroy(stm);
- return r;
- }
-
- stm->input_sample_spec =
- *(WRAP(pa_stream_get_sample_spec)(stm->input_stream));
-
- WRAP(pa_stream_set_state_callback)
- (stm->input_stream, stream_state_callback, stm);
- WRAP(pa_stream_set_read_callback)
- (stm->input_stream, stream_read_callback, stm);
-
- battr = set_buffering_attribute(latency_frames, &stm->input_sample_spec);
- WRAP(pa_stream_connect_record)
- (stm->input_stream, (char const *)input_device, &battr,
- PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
- PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY);
- }
-
- r = wait_until_stream_ready(stm);
- if (r == 0) {
- /* force a timing update now, otherwise timing info does not become valid
- until some point after initialization has completed. */
- r = stream_update_timing_info(stm);
- }
-
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
-
- if (r != 0) {
- pulse_stream_destroy(stm);
- return CUBEB_ERROR;
- }
-
- if (g_cubeb_log_level) {
- if (output_stream_params) {
- const pa_buffer_attr * output_att;
- output_att = WRAP(pa_stream_get_buffer_attr)(stm->output_stream);
- LOG("Output buffer attributes maxlength %u, tlength %u, prebuf %u, "
- "minreq %u, fragsize %u",
- output_att->maxlength, output_att->tlength, output_att->prebuf,
- output_att->minreq, output_att->fragsize);
- }
-
- if (input_stream_params) {
- const pa_buffer_attr * input_att;
- input_att = WRAP(pa_stream_get_buffer_attr)(stm->input_stream);
- LOG("Input buffer attributes maxlength %u, tlength %u, prebuf %u, minreq "
- "%u, fragsize %u",
- input_att->maxlength, input_att->tlength, input_att->prebuf,
- input_att->minreq, input_att->fragsize);
- }
- }
-
- *stream = stm;
- LOG("Cubeb stream (%p) init successful.", *stream);
-
- return CUBEB_OK;
-}
-
-static void
-pulse_stream_destroy(cubeb_stream * stm)
-{
- stream_cork(stm, CORK);
-
- WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
- if (stm->output_stream) {
-
- if (stm->drain_timer) {
- /* there's no pa_rttime_free, so use this instead. */
- WRAP(pa_threaded_mainloop_get_api)
- (stm->context->mainloop)->time_free(stm->drain_timer);
- }
-
- WRAP(pa_stream_set_state_callback)(stm->output_stream, NULL, NULL);
- WRAP(pa_stream_set_write_callback)(stm->output_stream, NULL, NULL);
- WRAP(pa_stream_disconnect)(stm->output_stream);
- WRAP(pa_stream_unref)(stm->output_stream);
- }
-
- if (stm->input_stream) {
- WRAP(pa_stream_set_state_callback)(stm->input_stream, NULL, NULL);
- WRAP(pa_stream_set_read_callback)(stm->input_stream, NULL, NULL);
- WRAP(pa_stream_disconnect)(stm->input_stream);
- WRAP(pa_stream_unref)(stm->input_stream);
- }
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
-
- LOG("Cubeb stream (%p) destroyed successfully.", stm);
- free(stm);
-}
-
-static void
-pulse_defer_event_cb(pa_mainloop_api * a, void * userdata)
-{
- (void)a;
- cubeb_stream * stm = userdata;
- if (stm->shutdown) {
- return;
- }
- size_t writable_size = WRAP(pa_stream_writable_size)(stm->output_stream);
- trigger_user_callback(stm->output_stream, NULL, writable_size, stm);
-}
-
-static int
-pulse_stream_start(cubeb_stream * stm)
-{
- stm->shutdown = 0;
- stream_cork(stm, UNCORK | NOTIFY);
-
- if (stm->output_stream && !stm->input_stream) {
- /* On output only case need to manually call user cb once in order to make
- * things roll. This is done via a defer event in order to execute it
- * from PA server thread. */
- WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
- WRAP(pa_mainloop_api_once)
- (WRAP(pa_threaded_mainloop_get_api)(stm->context->mainloop),
- pulse_defer_event_cb, stm);
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
- }
-
- LOG("Cubeb stream (%p) started successfully.", stm);
- return CUBEB_OK;
-}
-
-static int
-pulse_stream_stop(cubeb_stream * stm)
-{
- WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
- stm->shutdown = 1;
- // If draining is taking place wait to finish
- while (stm->drain_timer) {
- WRAP(pa_threaded_mainloop_wait)(stm->context->mainloop);
- }
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
-
- stream_cork(stm, CORK | NOTIFY);
- LOG("Cubeb stream (%p) stopped successfully.", stm);
- return CUBEB_OK;
-}
-
-static int
-pulse_stream_get_position(cubeb_stream * stm, uint64_t * position)
-{
- int r, in_thread;
- pa_usec_t r_usec;
- uint64_t bytes;
-
- if (!stm || !stm->output_stream) {
- return CUBEB_ERROR;
- }
-
- in_thread = WRAP(pa_threaded_mainloop_in_thread)(stm->context->mainloop);
-
- if (!in_thread) {
- WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
- }
- r = WRAP(pa_stream_get_time)(stm->output_stream, &r_usec);
- if (!in_thread) {
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
- }
-
- if (r != 0) {
- return CUBEB_ERROR;
- }
-
- bytes = WRAP(pa_usec_to_bytes)(r_usec, &stm->output_sample_spec);
- *position = bytes / WRAP(pa_frame_size)(&stm->output_sample_spec);
-
- return CUBEB_OK;
-}
-
-static int
-pulse_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
-{
- pa_usec_t r_usec;
- int negative, r;
-
- if (!stm || !stm->output_stream) {
- return CUBEB_ERROR;
- }
-
- r = WRAP(pa_stream_get_latency)(stm->output_stream, &r_usec, &negative);
- assert(!negative);
- if (r) {
- return CUBEB_ERROR;
- }
-
- *latency = r_usec * stm->output_sample_spec.rate / PA_USEC_PER_SEC;
- return CUBEB_OK;
-}
-
-static void
-volume_success(pa_context * c, int success, void * userdata)
-{
- (void)success;
- (void)c;
- cubeb_stream * stream = userdata;
- assert(success);
- WRAP(pa_threaded_mainloop_signal)(stream->context->mainloop, 0);
-}
-
-static void
-rename_success(pa_stream * s, int success, void * userdata)
-{
- cubeb_stream * stream = userdata;
- assert(success);
- WRAP(pa_threaded_mainloop_signal)(stream->context->mainloop, 0);
-}
-
-static int
-pulse_stream_set_volume(cubeb_stream * stm, float volume)
-{
- uint32_t index;
- pa_operation * op;
- pa_volume_t vol;
- pa_cvolume cvol;
- const pa_sample_spec * ss;
- cubeb * ctx;
-
- if (!stm->output_stream) {
- return CUBEB_ERROR;
- }
-
- WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
-
- /* if the pulse daemon is configured to use flat volumes,
- * apply our own gain instead of changing the input volume on the sink. */
- ctx = stm->context;
- if (ctx->default_sink_info &&
- (ctx->default_sink_info->flags & PA_SINK_FLAT_VOLUME)) {
- stm->volume = volume;
- } else {
- ss = WRAP(pa_stream_get_sample_spec)(stm->output_stream);
-
- vol = WRAP(pa_sw_volume_from_linear)(volume);
- WRAP(pa_cvolume_set)(&cvol, ss->channels, vol);
-
- index = WRAP(pa_stream_get_index)(stm->output_stream);
-
- op = WRAP(pa_context_set_sink_input_volume)(ctx->context, index, &cvol,
- volume_success, stm);
- if (op) {
- operation_wait(ctx, stm->output_stream, op);
- WRAP(pa_operation_unref)(op);
- }
- }
-
- WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
-
- return CUBEB_OK;
-}
-
-static int
-pulse_stream_set_name(cubeb_stream * stm, char const * stream_name)
-{
- if (!stm || !stm->output_stream) {
- return CUBEB_ERROR;
- }
-
- WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
-
- pa_operation * op = WRAP(pa_stream_set_name)(stm->output_stream, stream_name,
- rename_success, stm);
-
- if (op) {
- operation_wait(stm->context, stm->output_stream, op);
- WRAP(pa_operation_unref)(op);
- }
-
- WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
-
- return CUBEB_OK;
-}
-
-typedef struct {
- char * default_sink_name;
- char * default_source_name;
-
- cubeb_device_info * devinfo;
- uint32_t max;
- uint32_t count;
- cubeb * context;
-} pulse_dev_list_data;
-
-static cubeb_device_fmt
-pulse_format_to_cubeb_format(pa_sample_format_t format)
-{
- switch (format) {
- case PA_SAMPLE_S16LE:
- return CUBEB_DEVICE_FMT_S16LE;
- case PA_SAMPLE_S16BE:
- return CUBEB_DEVICE_FMT_S16BE;
- case PA_SAMPLE_FLOAT32LE:
- return CUBEB_DEVICE_FMT_F32LE;
- case PA_SAMPLE_FLOAT32BE:
- return CUBEB_DEVICE_FMT_F32BE;
- default:
- return CUBEB_DEVICE_FMT_F32NE;
- }
-}
-
-static void
-pulse_ensure_dev_list_data_list_size(pulse_dev_list_data * list_data)
-{
- if (list_data->count == list_data->max) {
- list_data->max += 8;
- list_data->devinfo =
- realloc(list_data->devinfo, sizeof(cubeb_device_info) * list_data->max);
- }
-}
-
-static cubeb_device_state
-pulse_get_state_from_sink_port(pa_sink_port_info * info)
-{
- if (info != NULL) {
-#if PA_CHECK_VERSION(2, 0, 0)
- if (has_pulse_v2 && info->available == PA_PORT_AVAILABLE_NO)
- return CUBEB_DEVICE_STATE_UNPLUGGED;
- else /*if (info->available == PA_PORT_AVAILABLE_YES) + UNKNOWN */
-#endif
- return CUBEB_DEVICE_STATE_ENABLED;
- }
-
- return CUBEB_DEVICE_STATE_ENABLED;
-}
-
-static void
-pulse_sink_info_cb(pa_context * context, const pa_sink_info * info, int eol,
- void * user_data)
-{
- pulse_dev_list_data * list_data = user_data;
- cubeb_device_info * devinfo;
- char const * prop = NULL;
- char const * device_id = NULL;
-
- (void)context;
-
- if (eol) {
- WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
- return;
- }
-
- if (info == NULL)
- return;
-
- device_id = info->name;
- if (intern_device_id(list_data->context, &device_id) != CUBEB_OK) {
- assert(NULL);
- return;
- }
-
- pulse_ensure_dev_list_data_list_size(list_data);
- devinfo = &list_data->devinfo[list_data->count];
- memset(devinfo, 0, sizeof(cubeb_device_info));
-
- devinfo->device_id = device_id;
- devinfo->devid = (cubeb_devid)devinfo->device_id;
- devinfo->friendly_name = strdup(info->description);
- prop = WRAP(pa_proplist_gets)(info->proplist, "sysfs.path");
- if (prop)
- devinfo->group_id = strdup(prop);
- prop = WRAP(pa_proplist_gets)(info->proplist, "device.vendor.name");
- if (prop)
- devinfo->vendor_name = strdup(prop);
-
- devinfo->type = CUBEB_DEVICE_TYPE_OUTPUT;
- devinfo->state = pulse_get_state_from_sink_port(info->active_port);
- devinfo->preferred = (strcmp(info->name, list_data->default_sink_name) == 0)
- ? CUBEB_DEVICE_PREF_ALL
- : CUBEB_DEVICE_PREF_NONE;
-
- devinfo->format = CUBEB_DEVICE_FMT_ALL;
- devinfo->default_format =
- pulse_format_to_cubeb_format(info->sample_spec.format);
- devinfo->max_channels = info->channel_map.channels;
- devinfo->min_rate = 1;
- devinfo->max_rate = PA_RATE_MAX;
- devinfo->default_rate = info->sample_spec.rate;
-
- devinfo->latency_lo = 0;
- devinfo->latency_hi = 0;
-
- list_data->count += 1;
-}
-
-static cubeb_device_state
-pulse_get_state_from_source_port(pa_source_port_info * info)
-{
- if (info != NULL) {
-#if PA_CHECK_VERSION(2, 0, 0)
- if (has_pulse_v2 && info->available == PA_PORT_AVAILABLE_NO)
- return CUBEB_DEVICE_STATE_UNPLUGGED;
- else /*if (info->available == PA_PORT_AVAILABLE_YES) + UNKNOWN */
-#endif
- return CUBEB_DEVICE_STATE_ENABLED;
- }
-
- return CUBEB_DEVICE_STATE_ENABLED;
-}
-
-static void
-pulse_source_info_cb(pa_context * context, const pa_source_info * info, int eol,
- void * user_data)
-{
- pulse_dev_list_data * list_data = user_data;
- cubeb_device_info * devinfo;
- char const * prop = NULL;
- char const * device_id = NULL;
-
- (void)context;
-
- if (eol) {
- WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
- return;
- }
-
- device_id = info->name;
- if (intern_device_id(list_data->context, &device_id) != CUBEB_OK) {
- assert(NULL);
- return;
- }
-
- pulse_ensure_dev_list_data_list_size(list_data);
- devinfo = &list_data->devinfo[list_data->count];
- memset(devinfo, 0, sizeof(cubeb_device_info));
-
- devinfo->device_id = device_id;
- devinfo->devid = (cubeb_devid)devinfo->device_id;
- devinfo->friendly_name = strdup(info->description);
- prop = WRAP(pa_proplist_gets)(info->proplist, "sysfs.path");
- if (prop)
- devinfo->group_id = strdup(prop);
- prop = WRAP(pa_proplist_gets)(info->proplist, "device.vendor.name");
- if (prop)
- devinfo->vendor_name = strdup(prop);
-
- devinfo->type = CUBEB_DEVICE_TYPE_INPUT;
- devinfo->state = pulse_get_state_from_source_port(info->active_port);
- devinfo->preferred = (strcmp(info->name, list_data->default_source_name) == 0)
- ? CUBEB_DEVICE_PREF_ALL
- : CUBEB_DEVICE_PREF_NONE;
-
- devinfo->format = CUBEB_DEVICE_FMT_ALL;
- devinfo->default_format =
- pulse_format_to_cubeb_format(info->sample_spec.format);
- devinfo->max_channels = info->channel_map.channels;
- devinfo->min_rate = 1;
- devinfo->max_rate = PA_RATE_MAX;
- devinfo->default_rate = info->sample_spec.rate;
-
- devinfo->latency_lo = 0;
- devinfo->latency_hi = 0;
-
- list_data->count += 1;
-}
-
-static void
-pulse_server_info_cb(pa_context * c, const pa_server_info * i, void * userdata)
-{
- pulse_dev_list_data * list_data = userdata;
-
- (void)c;
-
- free(list_data->default_sink_name);
- free(list_data->default_source_name);
- list_data->default_sink_name =
- i->default_sink_name ? strdup(i->default_sink_name) : NULL;
- list_data->default_source_name =
- i->default_source_name ? strdup(i->default_source_name) : NULL;
-
- WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
-}
-
-static int
-pulse_enumerate_devices(cubeb * context, cubeb_device_type type,
- cubeb_device_collection * collection)
-{
- pulse_dev_list_data user_data = {NULL, NULL, NULL, 0, 0, context};
- pa_operation * o;
-
- WRAP(pa_threaded_mainloop_lock)(context->mainloop);
-
- o = WRAP(pa_context_get_server_info)(context->context, pulse_server_info_cb,
- &user_data);
- if (o) {
- operation_wait(context, NULL, o);
- WRAP(pa_operation_unref)(o);
- }
-
- if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
- o = WRAP(pa_context_get_sink_info_list)(context->context,
- pulse_sink_info_cb, &user_data);
- if (o) {
- operation_wait(context, NULL, o);
- WRAP(pa_operation_unref)(o);
- }
- }
-
- if (type & CUBEB_DEVICE_TYPE_INPUT) {
- o = WRAP(pa_context_get_source_info_list)(context->context,
- pulse_source_info_cb, &user_data);
- if (o) {
- operation_wait(context, NULL, o);
- WRAP(pa_operation_unref)(o);
- }
- }
-
- WRAP(pa_threaded_mainloop_unlock)(context->mainloop);
-
- collection->device = user_data.devinfo;
- collection->count = user_data.count;
-
- free(user_data.default_sink_name);
- free(user_data.default_source_name);
- return CUBEB_OK;
-}
-
-static int
-pulse_device_collection_destroy(cubeb * ctx,
- cubeb_device_collection * collection)
-{
- size_t n;
-
- for (n = 0; n < collection->count; n++) {
- free((void *)collection->device[n].friendly_name);
- free((void *)collection->device[n].vendor_name);
- free((void *)collection->device[n].group_id);
- }
-
- free(collection->device);
- return CUBEB_OK;
-}
-
-static int
-pulse_stream_get_current_device(cubeb_stream * stm,
- cubeb_device ** const device)
-{
-#if PA_CHECK_VERSION(0, 9, 8)
- *device = calloc(1, sizeof(cubeb_device));
- if (*device == NULL)
- return CUBEB_ERROR;
-
- if (stm->input_stream) {
- const char * name = WRAP(pa_stream_get_device_name)(stm->input_stream);
- (*device)->input_name = (name == NULL) ? NULL : strdup(name);
- }
-
- if (stm->output_stream) {
- const char * name = WRAP(pa_stream_get_device_name)(stm->output_stream);
- (*device)->output_name = (name == NULL) ? NULL : strdup(name);
- }
-
- return CUBEB_OK;
-#else
- return CUBEB_ERROR_NOT_SUPPORTED;
-#endif
-}
-
-static int
-pulse_stream_device_destroy(cubeb_stream * stream, cubeb_device * device)
-{
- (void)stream;
- free(device->input_name);
- free(device->output_name);
- free(device);
- return CUBEB_OK;
-}
-
-static void
-pulse_subscribe_callback(pa_context * ctx, pa_subscription_event_type_t t,
- uint32_t index, void * userdata)
-{
- (void)ctx;
- cubeb * context = userdata;
-
- switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
- case PA_SUBSCRIPTION_EVENT_SERVER:
- if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE) {
- LOG("Server changed %d", index);
- WRAP(pa_context_get_server_info)
- (context->context, server_info_callback, context);
- }
- break;
- case PA_SUBSCRIPTION_EVENT_SOURCE:
- case PA_SUBSCRIPTION_EVENT_SINK:
-
- if (g_cubeb_log_level) {
- if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) ==
- PA_SUBSCRIPTION_EVENT_SOURCE &&
- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
- PA_SUBSCRIPTION_EVENT_REMOVE) {
- LOG("Removing source index %d", index);
- } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) ==
- PA_SUBSCRIPTION_EVENT_SOURCE &&
- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
- PA_SUBSCRIPTION_EVENT_NEW) {
- LOG("Adding source index %d", index);
- }
- if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) ==
- PA_SUBSCRIPTION_EVENT_SINK &&
- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
- PA_SUBSCRIPTION_EVENT_REMOVE) {
- LOG("Removing sink index %d", index);
- } else if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) ==
- PA_SUBSCRIPTION_EVENT_SINK &&
- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
- PA_SUBSCRIPTION_EVENT_NEW) {
- LOG("Adding sink index %d", index);
- }
- }
-
- if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE ||
- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
- if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) ==
- PA_SUBSCRIPTION_EVENT_SOURCE) {
- context->input_collection_changed_callback(
- context, context->input_collection_changed_user_ptr);
- }
- if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) ==
- PA_SUBSCRIPTION_EVENT_SINK) {
- context->output_collection_changed_callback(
- context, context->output_collection_changed_user_ptr);
- }
- }
- break;
- }
-}
-
-static void
-subscribe_success(pa_context * c, int success, void * userdata)
-{
- (void)c;
- cubeb * context = userdata;
- assert(success);
- WRAP(pa_threaded_mainloop_signal)(context->mainloop, 0);
-}
-
-static int
-pulse_subscribe_notifications(cubeb * context, pa_subscription_mask_t mask)
-{
- WRAP(pa_threaded_mainloop_lock)(context->mainloop);
-
- WRAP(pa_context_set_subscribe_callback)
- (context->context, pulse_subscribe_callback, context);
-
- pa_operation * o;
- o = WRAP(pa_context_subscribe)(context->context, mask, subscribe_success,
- context);
- if (o == NULL) {
- WRAP(pa_threaded_mainloop_unlock)(context->mainloop);
- LOG("Context subscribe failed");
- return CUBEB_ERROR;
- }
- operation_wait(context, NULL, o);
- WRAP(pa_operation_unref)(o);
-
- WRAP(pa_threaded_mainloop_unlock)(context->mainloop);
-
- return CUBEB_OK;
-}
-
-static int
-pulse_register_device_collection_changed(
- cubeb * context, cubeb_device_type devtype,
- cubeb_device_collection_changed_callback collection_changed_callback,
- void * user_ptr)
-{
- if (devtype & CUBEB_DEVICE_TYPE_INPUT) {
- context->input_collection_changed_callback = collection_changed_callback;
- context->input_collection_changed_user_ptr = user_ptr;
- }
- if (devtype & CUBEB_DEVICE_TYPE_OUTPUT) {
- context->output_collection_changed_callback = collection_changed_callback;
- context->output_collection_changed_user_ptr = user_ptr;
- }
-
- pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_NULL;
- if (context->input_collection_changed_callback) {
- /* Input added or removed */
- mask |= PA_SUBSCRIPTION_MASK_SOURCE;
- }
- if (context->output_collection_changed_callback) {
- /* Output added or removed */
- mask |= PA_SUBSCRIPTION_MASK_SINK;
- }
- /* Default device changed, this is always registered in order to update the
- * `default_sink_info` when the default device changes. */
- mask |= PA_SUBSCRIPTION_MASK_SERVER;
-
- return pulse_subscribe_notifications(context, mask);
-}
-
-static struct cubeb_ops const pulse_ops = {
- .init = pulse_init,
- .get_backend_id = pulse_get_backend_id,
- .get_max_channel_count = pulse_get_max_channel_count,
- .get_min_latency = pulse_get_min_latency,
- .get_preferred_sample_rate = pulse_get_preferred_sample_rate,
- .enumerate_devices = pulse_enumerate_devices,
- .device_collection_destroy = pulse_device_collection_destroy,
- .destroy = pulse_destroy,
- .stream_init = pulse_stream_init,
- .stream_destroy = pulse_stream_destroy,
- .stream_start = pulse_stream_start,
- .stream_stop = pulse_stream_stop,
- .stream_get_position = pulse_stream_get_position,
- .stream_get_latency = pulse_stream_get_latency,
- .stream_get_input_latency = NULL,
- .stream_set_volume = pulse_stream_set_volume,
- .stream_set_name = pulse_stream_set_name,
- .stream_get_current_device = pulse_stream_get_current_device,
- .stream_device_destroy = pulse_stream_device_destroy,
- .stream_register_device_changed_callback = NULL,
- .register_device_collection_changed =
- pulse_register_device_collection_changed};
diff --git a/media/libcubeb/src/moz.build b/media/libcubeb/src/moz.build
index 50fffb6ff..bba0d5f8b 100644
--- a/media/libcubeb/src/moz.build
+++ b/media/libcubeb/src/moz.build
@@ -27,12 +27,6 @@ if CONFIG['MOZ_PULSEAUDIO'] or CONFIG['MOZ_JACK']:
'cubeb_resampler.cpp',
]
-if CONFIG['MOZ_PULSEAUDIO']:
- SOURCES += [
- 'cubeb_pulse.c',
- ]
- DEFINES['USE_PULSE'] = True
-
if CONFIG['MOZ_JACK']:
SOURCES += [
'cubeb_jack.cpp',
diff --git a/media/libcubeb/update.sh b/media/libcubeb/update.sh
index 14b608a4e..4229524b5 100755
--- a/media/libcubeb/update.sh
+++ b/media/libcubeb/update.sh
@@ -20,7 +20,6 @@ cp $1/src/cubeb_log.h src
cp $1/src/cubeb_mixer.cpp src
cp $1/src/cubeb_mixer.h src
cp $1/src/cubeb_opensl.c src
-cp $1/src/cubeb_pulse.c src
cp $1/src/cubeb_android.h src
cp $1/src/cubeb-jni.cpp src
cp $1/src/cubeb-jni.h src