diff options
-rw-r--r-- | Mk/bsd.gecko.mk | 4 | ||||
-rw-r--r-- | mail/thunderbird/Makefile | 2 | ||||
-rw-r--r-- | mail/thunderbird/files/patch-cubeb-dlopen | 793 | ||||
-rw-r--r-- | www/firefox-esr/Makefile | 2 | ||||
-rw-r--r-- | www/firefox-esr/files/patch-cubeb-dlopen | 793 | ||||
-rw-r--r-- | www/firefox/Makefile | 2 | ||||
-rw-r--r-- | www/firefox/Makefile.options | 2 | ||||
-rw-r--r-- | www/firefox/files/patch-cubeb-dlopen | 793 |
8 files changed, 2385 insertions, 6 deletions
diff --git a/Mk/bsd.gecko.mk b/Mk/bsd.gecko.mk index a527cb561836..0e25b0a497ca 100644 --- a/Mk/bsd.gecko.mk +++ b/Mk/bsd.gecko.mk @@ -245,7 +245,7 @@ MOZ_OPTIONS+= --disable-libproxy .endif .if ${PORT_OPTIONS:MALSA} -LIB_DEPENDS+= libasound.so:audio/alsa-lib +BUILD_DEPENDS+= ${LOCALBASE}/include/alsa/asoundlib.h:audio/alsa-lib RUN_DEPENDS+= ${LOCALBASE}/lib/alsa-lib/libasound_module_pcm_oss.so:audio/alsa-plugins RUN_DEPENDS+= alsa-lib>=1.1.1_1:audio/alsa-lib MOZ_OPTIONS+= --enable-alsa @@ -264,7 +264,7 @@ MOZ_OPTIONS+= --disable-pulseaudio .endif .if ${PORT_OPTIONS:MSNDIO} -LIB_DEPENDS+= libsndio.so:audio/sndio +BUILD_DEPENDS+= ${LOCALBASE}/include/sndio.h:audio/sndio post-patch-SNDIO-on: @${REINPLACE_CMD} -e 's|OpenBSD|${OPSYS}|g' \ ${MOZSRC}/media/libcubeb/src/moz.build \ diff --git a/mail/thunderbird/Makefile b/mail/thunderbird/Makefile index 0bd2f861213d..378663167442 100644 --- a/mail/thunderbird/Makefile +++ b/mail/thunderbird/Makefile @@ -3,7 +3,7 @@ PORTNAME= thunderbird DISTVERSION= 68.1.0 -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES= mail news net-im ipv6 MASTER_SITES= MOZILLA/${PORTNAME}/releases/${DISTVERSION}/source \ MOZILLA/${PORTNAME}/candidates/${DISTVERSION}-candidates/build2/source diff --git a/mail/thunderbird/files/patch-cubeb-dlopen b/mail/thunderbird/files/patch-cubeb-dlopen new file mode 100644 index 000000000000..9314ede79256 --- /dev/null +++ b/mail/thunderbird/files/patch-cubeb-dlopen @@ -0,0 +1,793 @@ +https://github.com/kinetiknz/cubeb/pull/539 + +diff --git media/libcubeb/gtest/moz.build media/libcubeb/gtest/moz.build +index 1ff0c02545251..ca364d1ef7845 100644 +--- media/libcubeb/gtest/moz.build ++++ media/libcubeb/gtest/moz.build +@@ -67,13 +67,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit': + '-framework CoreFoundation', + '-framework AudioToolbox', + ] +-elif CONFIG['OS_TARGET'] == 'OpenBSD': +- OS_LIBS += [ +- 'sndio', +- ] +-else: +- OS_LIBS += CONFIG['MOZ_ALSA_LIBS'] +- OS_LIBS += CONFIG['MOZ_PULSEAUDIO_LIBS'] + + if CONFIG['CC_TYPE'] in ('clang', 'gcc'): + CXXFLAGS += ['-Wno-error=shadow'] +diff --git media/libcubeb/src/cubeb.c media/libcubeb/src/cubeb.c +index 98a735f..db294b3 100644 +--- media/libcubeb/src/cubeb.c ++++ media/libcubeb/src/cubeb.c +@@ -180,6 +180,9 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam + #if defined(USE_JACK) + jack_init, + #endif ++#if defined(USE_SNDIO) ++ sndio_init, ++#endif + #if defined(USE_ALSA) + alsa_init, + #endif +@@ -192,9 +195,6 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam + #if defined(USE_WINMM) + winmm_init, + #endif +-#if defined(USE_SNDIO) +- sndio_init, +-#endif + #if defined(USE_OPENSL) + opensl_init, + #endif +diff --git media/libcubeb/src/cubeb_alsa.c media/libcubeb/src/cubeb_alsa.c +index bfd4d8f..a29eed0 100644 +--- media/libcubeb/src/cubeb_alsa.c ++++ media/libcubeb/src/cubeb_alsa.c +@@ -14,10 +14,58 @@ + #include <limits.h> + #include <poll.h> + #include <unistd.h> ++#include <dlfcn.h> + #include <alsa/asoundlib.h> + #include "cubeb/cubeb.h" + #include "cubeb-internal.h" + ++#ifdef DISABLE_LIBASOUND_DLOPEN ++#define WRAP(x) x ++#else ++#define WRAP(x) cubeb_##x ++#define LIBASOUND_API_VISIT(X) \ ++ X(snd_config) \ ++ X(snd_config_add) \ ++ X(snd_config_copy) \ ++ X(snd_config_delete) \ ++ X(snd_config_get_id) \ ++ X(snd_config_get_string) \ ++ X(snd_config_imake_integer) \ ++ X(snd_config_search) \ ++ X(snd_config_search_definition) \ ++ X(snd_lib_error_set_handler) \ ++ X(snd_pcm_avail_update) \ ++ X(snd_pcm_close) \ ++ X(snd_pcm_delay) \ ++ X(snd_pcm_drain) \ ++ X(snd_pcm_frames_to_bytes) \ ++ X(snd_pcm_get_params) \ ++ X(snd_pcm_hw_params_any) \ ++ X(snd_pcm_hw_params_get_channels_max) \ ++ X(snd_pcm_hw_params_get_rate) \ ++ X(snd_pcm_hw_params_set_rate_near) \ ++ X(snd_pcm_hw_params_sizeof) \ ++ X(snd_pcm_nonblock) \ ++ X(snd_pcm_open) \ ++ X(snd_pcm_open_lconf) \ ++ X(snd_pcm_pause) \ ++ X(snd_pcm_poll_descriptors) \ ++ X(snd_pcm_poll_descriptors_count) \ ++ X(snd_pcm_poll_descriptors_revents) \ ++ X(snd_pcm_readi) \ ++ X(snd_pcm_recover) \ ++ X(snd_pcm_set_params) \ ++ X(snd_pcm_start) \ ++ X(snd_pcm_state) \ ++ X(snd_pcm_writei) \ ++ ++#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x; ++LIBASOUND_API_VISIT(MAKE_TYPEDEF); ++#undef MAKE_TYPEDEF ++/* snd_pcm_hw_params_alloca is actually a macro */ ++#define snd_pcm_hw_params_sizeof cubeb_snd_pcm_hw_params_sizeof ++#endif ++ + #define CUBEB_STREAM_MAX 16 + #define CUBEB_WATCHDOG_MS 10000 + +@@ -36,6 +84,7 @@ static struct cubeb_ops const alsa_ops; + + struct cubeb { + struct cubeb_ops const * ops; ++ void * libasound; + + pthread_t thread; + +@@ -245,8 +294,8 @@ set_timeout(struct timeval * timeout, unsigned int ms) + static void + stream_buffer_decrement(cubeb_stream * stm, long count) + { +- char * bufremains = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, count); +- memmove(stm->buffer, bufremains, snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes - count)); ++ char * bufremains = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, count); ++ memmove(stm->buffer, bufremains, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes - count)); + stm->bufframes -= count; + } + +@@ -278,9 +327,9 @@ alsa_process_stream(cubeb_stream * stm) + /* Call _poll_descriptors_revents() even if we don't use it + to let underlying plugins clear null events. Otherwise poll() + may wake up again and again, producing unnecessary CPU usage. */ +- snd_pcm_poll_descriptors_revents(stm->pcm, stm->fds, stm->nfds, &revents); ++ WRAP(snd_pcm_poll_descriptors_revents)(stm->pcm, stm->fds, stm->nfds, &revents); + +- avail = snd_pcm_avail_update(stm->pcm); ++ avail = WRAP(snd_pcm_avail_update)(stm->pcm); + + /* Got null event? Bail and wait for another wakeup. */ + if (avail == 0) { +@@ -303,7 +352,7 @@ alsa_process_stream(cubeb_stream * stm) + // TODO: should it be marked as DRAINING? + } + +- got = snd_pcm_readi(stm->pcm, stm->buffer+stm->bufframes, avail); ++ got = WRAP(snd_pcm_readi)(stm->pcm, stm->buffer+stm->bufframes, avail); + + if (got < 0) { + avail = got; // the error handler below will recover us +@@ -347,7 +396,7 @@ alsa_process_stream(cubeb_stream * stm) + (!stm->other_stream || stm->other_stream->bufframes > 0)) { + long got = avail - stm->bufframes; + void * other_buffer = stm->other_stream ? stm->other_stream->buffer : NULL; +- char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes); ++ char * buftail = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes); + + /* Correct read size to the other stream available frames */ + if (stm->other_stream && got > (snd_pcm_sframes_t) stm->other_stream->bufframes) { +@@ -374,8 +423,8 @@ alsa_process_stream(cubeb_stream * stm) + long drain_frames = avail - stm->bufframes; + double drain_time = (double) drain_frames / stm->params.rate; + +- char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes); +- memset(buftail, 0, snd_pcm_frames_to_bytes(stm->pcm, drain_frames)); ++ char * buftail = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes); ++ memset(buftail, 0, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, drain_frames)); + stm->bufframes = avail; + + /* Mark as draining, unless we're waiting for capture */ +@@ -402,7 +451,7 @@ alsa_process_stream(cubeb_stream * stm) + } + } + +- wrote = snd_pcm_writei(stm->pcm, stm->buffer, avail); ++ wrote = WRAP(snd_pcm_writei)(stm->pcm, stm->buffer, avail); + if (wrote < 0) { + avail = wrote; // the error handler below will recover us + } else { +@@ -415,13 +464,13 @@ alsa_process_stream(cubeb_stream * stm) + + /* Got some error? Let's try to recover the stream. */ + if (avail < 0) { +- avail = snd_pcm_recover(stm->pcm, avail, 0); ++ avail = WRAP(snd_pcm_recover)(stm->pcm, avail, 0); + + /* Capture pcm must be started after initial setup/recover */ + if (avail >= 0 && + stm->stream_type == SND_PCM_STREAM_CAPTURE && +- snd_pcm_state(stm->pcm) == SND_PCM_STATE_PREPARED) { +- avail = snd_pcm_start(stm->pcm); ++ WRAP(snd_pcm_state)(stm->pcm) == SND_PCM_STATE_PREPARED) { ++ avail = WRAP(snd_pcm_start)(stm->pcm); + } + } + +@@ -537,26 +586,26 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + + slave_def = NULL; + +- r = snd_config_search(root_pcm, "slave", &slave_pcm); ++ r = WRAP(snd_config_search)(root_pcm, "slave", &slave_pcm); + if (r < 0) { + return NULL; + } + +- r = snd_config_get_string(slave_pcm, &string); ++ r = WRAP(snd_config_get_string)(slave_pcm, &string); + if (r >= 0) { +- r = snd_config_search_definition(lconf, "pcm_slave", string, &slave_def); ++ r = WRAP(snd_config_search_definition)(lconf, "pcm_slave", string, &slave_def); + if (r < 0) { + return NULL; + } + } + + do { +- r = snd_config_search(slave_def ? slave_def : slave_pcm, "pcm", &pcm); ++ r = WRAP(snd_config_search)(slave_def ? slave_def : slave_pcm, "pcm", &pcm); + if (r < 0) { + break; + } + +- r = snd_config_get_string(slave_def ? slave_def : slave_pcm, &string); ++ r = WRAP(snd_config_get_string)(slave_def ? slave_def : slave_pcm, &string); + if (r < 0) { + break; + } +@@ -565,7 +614,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + if (r < 0 || r > (int) sizeof(node_name)) { + break; + } +- r = snd_config_search(lconf, node_name, &pcm); ++ r = WRAP(snd_config_search)(lconf, node_name, &pcm); + if (r < 0) { + break; + } +@@ -574,7 +623,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + } while (0); + + if (slave_def) { +- snd_config_delete(slave_def); ++ WRAP(snd_config_delete)(slave_def); + } + + return NULL; +@@ -597,22 +646,22 @@ init_local_config_with_workaround(char const * pcm_name) + + lconf = NULL; + +- if (snd_config == NULL) { ++ if (*WRAP(snd_config) == NULL) { + return NULL; + } + +- r = snd_config_copy(&lconf, snd_config); ++ r = WRAP(snd_config_copy)(&lconf, *WRAP(snd_config)); + if (r < 0) { + return NULL; + } + + do { +- r = snd_config_search_definition(lconf, "pcm", pcm_name, &pcm_node); ++ r = WRAP(snd_config_search_definition)(lconf, "pcm", pcm_name, &pcm_node); + if (r < 0) { + break; + } + +- r = snd_config_get_id(pcm_node, &string); ++ r = WRAP(snd_config_get_id)(pcm_node, &string); + if (r < 0) { + break; + } +@@ -621,7 +670,7 @@ init_local_config_with_workaround(char const * pcm_name) + if (r < 0 || r > (int) sizeof(node_name)) { + break; + } +- r = snd_config_search(lconf, node_name, &pcm_node); ++ r = WRAP(snd_config_search)(lconf, node_name, &pcm_node); + if (r < 0) { + break; + } +@@ -632,12 +681,12 @@ init_local_config_with_workaround(char const * pcm_name) + } + + /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */ +- r = snd_config_search(pcm_node, "type", &node); ++ r = WRAP(snd_config_search)(pcm_node, "type", &node); + if (r < 0) { + break; + } + +- r = snd_config_get_string(node, &string); ++ r = WRAP(snd_config_get_string)(node, &string); + if (r < 0) { + break; + } +@@ -648,18 +697,18 @@ init_local_config_with_workaround(char const * pcm_name) + + /* Don't clobber an explicit existing handle_underrun value, set it only + if it doesn't already exist. */ +- r = snd_config_search(pcm_node, "handle_underrun", &node); ++ r = WRAP(snd_config_search)(pcm_node, "handle_underrun", &node); + if (r != -ENOENT) { + break; + } + + /* Disable pcm_pulse's asynchronous underrun handling. */ +- r = snd_config_imake_integer(&node, "handle_underrun", 0); ++ r = WRAP(snd_config_imake_integer)(&node, "handle_underrun", 0); + if (r < 0) { + break; + } + +- r = snd_config_add(pcm_node, node); ++ r = WRAP(snd_config_add)(pcm_node, node); + if (r < 0) { + break; + } +@@ -667,7 +716,7 @@ init_local_config_with_workaround(char const * pcm_name) + return lconf; + } while (0); + +- snd_config_delete(lconf); ++ WRAP(snd_config_delete)(lconf); + + return NULL; + } +@@ -679,9 +728,9 @@ alsa_locked_pcm_open(snd_pcm_t ** pcm, char const * pcm_name, snd_pcm_stream_t s + + pthread_mutex_lock(&cubeb_alsa_mutex); + if (local_config) { +- r = snd_pcm_open_lconf(pcm, pcm_name, stream, SND_PCM_NONBLOCK, local_config); ++ r = WRAP(snd_pcm_open_lconf)(pcm, pcm_name, stream, SND_PCM_NONBLOCK, local_config); + } else { +- r = snd_pcm_open(pcm, pcm_name, stream, SND_PCM_NONBLOCK); ++ r = WRAP(snd_pcm_open)(pcm, pcm_name, stream, SND_PCM_NONBLOCK); + } + pthread_mutex_unlock(&cubeb_alsa_mutex); + +@@ -694,7 +743,7 @@ alsa_locked_pcm_close(snd_pcm_t * pcm) + int r; + + pthread_mutex_lock(&cubeb_alsa_mutex); +- r = snd_pcm_close(pcm); ++ r = WRAP(snd_pcm_close)(pcm); + pthread_mutex_unlock(&cubeb_alsa_mutex); + + return r; +@@ -750,6 +799,7 @@ silent_error_handler(char const * file, int line, char const * function, + alsa_init(cubeb ** context, char const * context_name) + { + (void)context_name; ++ void * libasound = NULL; + cubeb * ctx; + int r; + int i; +@@ -760,9 +810,27 @@ alsa_init(cubeb ** context, char const * context_name) + assert(context); + *context = NULL; + ++#ifndef DISABLE_LIBASOUND_DLOPEN ++ libasound = dlopen("libasound.so", RTLD_LAZY); ++ if (!libasound) { ++ return CUBEB_ERROR; ++ } ++ ++#define LOAD(x) { \ ++ cubeb_##x = dlsym(libasound, #x); \ ++ if (!cubeb_##x) { \ ++ dlclose(libasound); \ ++ return CUBEB_ERROR; \ ++ } \ ++ } ++ ++ LIBASOUND_API_VISIT(LOAD); ++#undef LOAD ++#endif ++ + pthread_mutex_lock(&cubeb_alsa_mutex); + if (!cubeb_alsa_error_handler_set) { +- snd_lib_error_set_handler(silent_error_handler); ++ WRAP(snd_lib_error_set_handler)(silent_error_handler); + cubeb_alsa_error_handler_set = 1; + } + pthread_mutex_unlock(&cubeb_alsa_mutex); +@@ -771,6 +839,7 @@ alsa_init(cubeb ** context, char const * context_name) + assert(ctx); + + ctx->ops = &alsa_ops; ++ ctx->libasound = libasound; + + r = pthread_mutex_init(&ctx->mutex, NULL); + assert(r == 0); +@@ -819,7 +888,7 @@ alsa_init(cubeb ** context, char const * context_name) + config fails with EINVAL, the PA PCM is too old for this workaround. */ + if (r == -EINVAL) { + pthread_mutex_lock(&cubeb_alsa_mutex); +- snd_config_delete(ctx->local_config); ++ WRAP(snd_config_delete)(ctx->local_config); + pthread_mutex_unlock(&cubeb_alsa_mutex); + ctx->local_config = NULL; + } else if (r >= 0) { +@@ -861,10 +930,14 @@ alsa_destroy(cubeb * ctx) + + if (ctx->local_config) { + pthread_mutex_lock(&cubeb_alsa_mutex); +- snd_config_delete(ctx->local_config); ++ WRAP(snd_config_delete)(ctx->local_config); + pthread_mutex_unlock(&cubeb_alsa_mutex); + } + ++ if (ctx->libasound) { ++ dlclose(ctx->libasound); ++ } ++ + free(ctx); + } + +@@ -948,7 +1021,7 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + return CUBEB_ERROR; + } + +- r = snd_pcm_nonblock(stm->pcm, 1); ++ r = WRAP(snd_pcm_nonblock)(stm->pcm, 1); + assert(r == 0); + + latency_us = latency_frames * 1e6 / stm->params.rate; +@@ -961,7 +1034,7 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + latency_us = latency_us < min_latency ? min_latency: latency_us; + } + +- r = snd_pcm_set_params(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED, ++ r = WRAP(snd_pcm_set_params)(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED, + stm->params.channels, stm->params.rate, 1, + latency_us); + if (r < 0) { +@@ -969,20 +1042,20 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + return CUBEB_ERROR_INVALID_FORMAT; + } + +- r = snd_pcm_get_params(stm->pcm, &stm->buffer_size, &period_size); ++ r = WRAP(snd_pcm_get_params)(stm->pcm, &stm->buffer_size, &period_size); + assert(r == 0); + + /* Double internal buffer size to have enough space when waiting for the other side of duplex connection */ + stm->buffer_size *= 2; +- stm->buffer = calloc(1, snd_pcm_frames_to_bytes(stm->pcm, stm->buffer_size)); ++ stm->buffer = calloc(1, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->buffer_size)); + assert(stm->buffer); + +- stm->nfds = snd_pcm_poll_descriptors_count(stm->pcm); ++ stm->nfds = WRAP(snd_pcm_poll_descriptors_count)(stm->pcm); + assert(stm->nfds > 0); + + stm->saved_fds = calloc(stm->nfds, sizeof(struct pollfd)); + assert(stm->saved_fds); +- r = snd_pcm_poll_descriptors(stm->pcm, stm->saved_fds, stm->nfds); ++ r = WRAP(snd_pcm_poll_descriptors)(stm->pcm, stm->saved_fds, stm->nfds); + assert((nfds_t) r == stm->nfds); + + if (alsa_register_stream(ctx, stm) != 0) { +@@ -1054,7 +1127,7 @@ alsa_stream_destroy(cubeb_stream * stm) + pthread_mutex_lock(&stm->mutex); + if (stm->pcm) { + if (stm->state == DRAINING) { +- snd_pcm_drain(stm->pcm); ++ WRAP(snd_pcm_drain)(stm->pcm); + } + alsa_locked_pcm_close(stm->pcm); + stm->pcm = NULL; +@@ -1100,12 +1173,12 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) + + assert(stm); + +- r = snd_pcm_hw_params_any(stm->pcm, hw_params); ++ r = WRAP(snd_pcm_hw_params_any)(stm->pcm, hw_params); + if (r < 0) { + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_get_channels_max(hw_params, max_channels); ++ r = WRAP(snd_pcm_hw_params_get_channels_max)(hw_params, max_channels); + if (r < 0) { + return CUBEB_ERROR; + } +@@ -1126,34 +1199,34 @@ 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. */ +- r = snd_pcm_open(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE); ++ r = WRAP(snd_pcm_open)(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE); + if (r < 0) { + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_any(pcm, hw_params); ++ r = WRAP(snd_pcm_hw_params_any)(pcm, hw_params); + if (r < 0) { +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_get_rate(hw_params, rate, &dir); ++ r = WRAP(snd_pcm_hw_params_get_rate)(hw_params, rate, &dir); + if (r >= 0) { + /* There is a default rate: use it. */ +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_OK; + } + + /* Use a common rate, alsa may adjust it based on hw/etc. capabilities. */ + *rate = 44100; + +- r = snd_pcm_hw_params_set_rate_near(pcm, hw_params, rate, NULL); ++ r = WRAP(snd_pcm_hw_params_set_rate_near)(pcm, hw_params, rate, NULL); + if (r < 0) { +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_ERROR; + } + +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + + return CUBEB_OK; + } +@@ -1186,10 +1259,10 @@ alsa_stream_start(cubeb_stream * stm) + pthread_mutex_lock(&stm->mutex); + /* Capture pcm must be started after initial setup/recover */ + if (stm->stream_type == SND_PCM_STREAM_CAPTURE && +- snd_pcm_state(stm->pcm) == SND_PCM_STATE_PREPARED) { +- snd_pcm_start(stm->pcm); ++ WRAP(snd_pcm_state)(stm->pcm) == SND_PCM_STATE_PREPARED) { ++ WRAP(snd_pcm_start)(stm->pcm); + } +- snd_pcm_pause(stm->pcm, 0); ++ WRAP(snd_pcm_pause)(stm->pcm, 0); + gettimeofday(&stm->last_activity, NULL); + pthread_mutex_unlock(&stm->mutex); + +@@ -1229,7 +1302,7 @@ alsa_stream_stop(cubeb_stream * stm) + pthread_mutex_unlock(&ctx->mutex); + + pthread_mutex_lock(&stm->mutex); +- snd_pcm_pause(stm->pcm, 1); ++ WRAP(snd_pcm_pause)(stm->pcm, 1); + pthread_mutex_unlock(&stm->mutex); + + return CUBEB_OK; +@@ -1245,8 +1318,8 @@ alsa_stream_get_position(cubeb_stream * stm, uint64_t * position) + pthread_mutex_lock(&stm->mutex); + + delay = -1; +- if (snd_pcm_state(stm->pcm) != SND_PCM_STATE_RUNNING || +- snd_pcm_delay(stm->pcm, &delay) != 0) { ++ if (WRAP(snd_pcm_state)(stm->pcm) != SND_PCM_STATE_RUNNING || ++ WRAP(snd_pcm_delay)(stm->pcm, &delay) != 0) { + *position = stm->last_position; + pthread_mutex_unlock(&stm->mutex); + return CUBEB_OK; +@@ -1271,7 +1344,7 @@ alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency) + snd_pcm_sframes_t delay; + /* This function returns the delay in frames until a frame written using + snd_pcm_writei is sent to the DAC. The DAC delay should be < 1ms anyways. */ +- if (snd_pcm_delay(stm->pcm, &delay)) { ++ if (WRAP(snd_pcm_delay)(stm->pcm, &delay)) { + return CUBEB_ERROR; + } + +diff --git media/libcubeb/src/cubeb_sndio.c media/libcubeb/src/cubeb_sndio.c +index 9e99b2c..0559af4 100644 +--- media/libcubeb/src/cubeb_sndio.c ++++ media/libcubeb/src/cubeb_sndio.c +@@ -12,6 +12,7 @@ + #include <stdbool.h> + #include <stdlib.h> + #include <stdio.h> ++#include <dlfcn.h> + #include <assert.h> + #include "cubeb/cubeb.h" + #include "cubeb-internal.h" +@@ -22,10 +23,35 @@ + #define DPR(...) do {} while(0) + #endif + ++#ifdef DISABLE_LIBSNDIO_DLOPEN ++#define WRAP(x) x ++#else ++#define WRAP(x) cubeb_##x ++#define LIBSNDIO_API_VISIT(X) \ ++ X(sio_close) \ ++ X(sio_eof) \ ++ X(sio_getpar) \ ++ X(sio_initpar) \ ++ X(sio_onmove) \ ++ X(sio_open) \ ++ X(sio_pollfd) \ ++ X(sio_read) \ ++ X(sio_revents) \ ++ X(sio_setpar) \ ++ X(sio_start) \ ++ X(sio_stop) \ ++ X(sio_write) \ ++ ++#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x; ++LIBSNDIO_API_VISIT(MAKE_TYPEDEF); ++#undef MAKE_TYPEDEF ++#endif ++ + static struct cubeb_ops const sndio_ops; + + struct cubeb { + struct cubeb_ops const * ops; ++ void * libsndio; + }; + + struct cubeb_stream { +@@ -119,7 +145,7 @@ sndio_mainloop(void *arg) + DPR("sndio_mainloop()\n"); + s->state_cb(s, s->arg, CUBEB_STATE_STARTED); + pthread_mutex_lock(&s->mtx); +- if (!sio_start(s->hdl)) { ++ if (!WRAP(sio_start)(s->hdl)) { + pthread_mutex_unlock(&s->mtx); + return NULL; + } +@@ -203,7 +229,7 @@ sndio_mainloop(void *arg) + events |= POLLIN; + if ((s->mode & SIO_PLAY) && pstart < pend) + events |= POLLOUT; +- nfds = sio_pollfd(s->hdl, pfds, events); ++ nfds = WRAP(sio_pollfd)(s->hdl, pfds, events); + + if (nfds > 0) { + pthread_mutex_unlock(&s->mtx); +@@ -213,7 +239,7 @@ sndio_mainloop(void *arg) + continue; + } + +- revents = sio_revents(s->hdl, pfds); ++ revents = WRAP(sio_revents)(s->hdl, pfds); + + if (revents & POLLHUP) { + state = CUBEB_STATE_ERROR; +@@ -221,8 +247,8 @@ sndio_mainloop(void *arg) + } + + if (revents & POLLOUT) { +- n = sio_write(s->hdl, s->pbuf + pstart, pend - pstart); +- if (n == 0 && sio_eof(s->hdl)) { ++ n = WRAP(sio_write)(s->hdl, s->pbuf + pstart, pend - pstart); ++ if (n == 0 && WRAP(sio_eof)(s->hdl)) { + DPR("sndio_mainloop() werr\n"); + state = CUBEB_STATE_ERROR; + break; +@@ -231,8 +257,8 @@ sndio_mainloop(void *arg) + } + + if (revents & POLLIN) { +- n = sio_read(s->hdl, s->rbuf + rstart, rend - rstart); +- if (n == 0 && sio_eof(s->hdl)) { ++ n = WRAP(sio_read)(s->hdl, s->rbuf + rstart, rend - rstart); ++ if (n == 0 && WRAP(sio_eof)(s->hdl)) { + DPR("sndio_mainloop() rerr\n"); + state = CUBEB_STATE_ERROR; + break; +@@ -244,7 +270,7 @@ sndio_mainloop(void *arg) + if (prime > 0 && (s->mode & SIO_REC)) + rstart = rend; + } +- sio_stop(s->hdl); ++ WRAP(sio_stop)(s->hdl); + s->hwpos = s->swpos; + pthread_mutex_unlock(&s->mtx); + s->state_cb(s, s->arg, state); +@@ -254,8 +280,31 @@ sndio_mainloop(void *arg) + /*static*/ int + sndio_init(cubeb **context, char const *context_name) + { ++ void * libsndio = NULL; ++ ++#ifndef DISABLE_LIBSNDIO_DLOPEN ++ libsndio = dlopen("libsndio.so", RTLD_LAZY); ++ if (!libsndio) { ++ DPR("sndio_init(%s) failed dlopen(libsndio.so)\n", context_name); ++ return CUBEB_ERROR; ++ } ++ ++#define LOAD(x) { \ ++ cubeb_##x = dlsym(libsndio, #x); \ ++ if (!cubeb_##x) { \ ++ DPR("sndio_init(%s) failed dlsym(%s)\n", context_name, #x); \ ++ dlclose(libsndio); \ ++ return CUBEB_ERROR; \ ++ } \ ++ } ++ ++ LIBSNDIO_API_VISIT(LOAD); ++#undef LOAD ++#endif ++ + DPR("sndio_init(%s)\n", context_name); + *context = malloc(sizeof(*context)); ++ (*context)->libsndio = libsndio; + (*context)->ops = &sndio_ops; + (void)context_name; + return CUBEB_OK; +@@ -271,6 +320,8 @@ static void + sndio_destroy(cubeb *context) + { + DPR("sndio_destroy()\n"); ++ if (context->libsndio) ++ dlclose(context->libsndio); + free(context); + } + +@@ -323,12 +374,12 @@ sndio_stream_init(cubeb * context, + goto err; + } + s->context = context; +- s->hdl = sio_open(NULL, s->mode, 1); ++ s->hdl = WRAP(sio_open)(NULL, s->mode, 1); + if (s->hdl == NULL) { + DPR("sndio_stream_init(), sio_open() failed\n"); + goto err; + } +- sio_initpar(&wpar); ++ WRAP(sio_initpar)(&wpar); + wpar.sig = 1; + wpar.bits = 16; + switch (format) { +@@ -351,7 +402,7 @@ sndio_stream_init(cubeb * context, + if (s->mode & SIO_PLAY) + wpar.pchan = output_stream_params->channels; + wpar.appbufsz = latency_frames; +- if (!sio_setpar(s->hdl, &wpar) || !sio_getpar(s->hdl, &rpar)) { ++ if (!WRAP(sio_setpar)(s->hdl, &wpar) || !WRAP(sio_getpar)(s->hdl, &rpar)) { + DPR("sndio_stream_init(), sio_setpar() failed\n"); + goto err; + } +@@ -362,7 +413,7 @@ sndio_stream_init(cubeb * context, + DPR("sndio_stream_init() unsupported params\n"); + goto err; + } +- sio_onmove(s->hdl, sndio_onmove, s); ++ WRAP(sio_onmove)(s->hdl, sndio_onmove, s); + s->active = 0; + s->nfr = rpar.round; + s->rbpf = rpar.bps * rpar.rchan; +@@ -400,7 +451,7 @@ sndio_stream_init(cubeb * context, + return CUBEB_OK; + err: + if (s->hdl) +- sio_close(s->hdl); ++ WRAP(sio_close)(s->hdl); + if (s->pbuf) + free(s->pbuf); + if (s->rbuf) +@@ -446,7 +497,7 @@ static void + sndio_stream_destroy(cubeb_stream *s) + { + DPR("sndio_stream_destroy()\n"); +- sio_close(s->hdl); ++ WRAP(sio_close)(s->hdl); + if (s->mode & SIO_PLAY) + free(s->pbuf); + if (s->mode & SIO_REC) +diff --git toolkit/library/moz.build toolkit/library/moz.build +index 8ce595ff96bff..c318e96a1fdfc 100644 +--- toolkit/library/moz.build ++++ toolkit/library/moz.build +@@ -231,9 +231,6 @@ if CONFIG['MOZ_SYSTEM_LIBVPX']: + if not CONFIG['MOZ_TREE_PIXMAN']: + OS_LIBS += CONFIG['MOZ_PIXMAN_LIBS'] + +-if CONFIG['MOZ_ALSA']: +- OS_LIBS += CONFIG['MOZ_ALSA_LIBS'] +- + if CONFIG['HAVE_CLOCK_MONOTONIC']: + OS_LIBS += CONFIG['REALTIME_LIBS'] + +@@ -242,11 +239,6 @@ OS_LIBS += CONFIG['ICONV_LIBS'] + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'): + OS_LIBS += CONFIG['TK_LIBS'] + +-if CONFIG['OS_ARCH'] == 'OpenBSD': +- OS_LIBS += [ +- 'sndio', +- ] +- + if CONFIG['MOZ_ENABLE_DBUS']: + OS_LIBS += CONFIG['MOZ_DBUS_GLIB_LIBS'] + diff --git a/www/firefox-esr/Makefile b/www/firefox-esr/Makefile index 431d27725781..f5d6da8cc5da 100644 --- a/www/firefox-esr/Makefile +++ b/www/firefox-esr/Makefile @@ -3,7 +3,7 @@ PORTNAME= firefox DISTVERSION= 68.1.0 -PORTREVISION= 1 +PORTREVISION= 2 PORTEPOCH= 1 CATEGORIES= www ipv6 MASTER_SITES= MOZILLA/${PORTNAME}/releases/${DISTVERSION}esr/source \ diff --git a/www/firefox-esr/files/patch-cubeb-dlopen b/www/firefox-esr/files/patch-cubeb-dlopen new file mode 100644 index 000000000000..9314ede79256 --- /dev/null +++ b/www/firefox-esr/files/patch-cubeb-dlopen @@ -0,0 +1,793 @@ +https://github.com/kinetiknz/cubeb/pull/539 + +diff --git media/libcubeb/gtest/moz.build media/libcubeb/gtest/moz.build +index 1ff0c02545251..ca364d1ef7845 100644 +--- media/libcubeb/gtest/moz.build ++++ media/libcubeb/gtest/moz.build +@@ -67,13 +67,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit': + '-framework CoreFoundation', + '-framework AudioToolbox', + ] +-elif CONFIG['OS_TARGET'] == 'OpenBSD': +- OS_LIBS += [ +- 'sndio', +- ] +-else: +- OS_LIBS += CONFIG['MOZ_ALSA_LIBS'] +- OS_LIBS += CONFIG['MOZ_PULSEAUDIO_LIBS'] + + if CONFIG['CC_TYPE'] in ('clang', 'gcc'): + CXXFLAGS += ['-Wno-error=shadow'] +diff --git media/libcubeb/src/cubeb.c media/libcubeb/src/cubeb.c +index 98a735f..db294b3 100644 +--- media/libcubeb/src/cubeb.c ++++ media/libcubeb/src/cubeb.c +@@ -180,6 +180,9 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam + #if defined(USE_JACK) + jack_init, + #endif ++#if defined(USE_SNDIO) ++ sndio_init, ++#endif + #if defined(USE_ALSA) + alsa_init, + #endif +@@ -192,9 +195,6 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam + #if defined(USE_WINMM) + winmm_init, + #endif +-#if defined(USE_SNDIO) +- sndio_init, +-#endif + #if defined(USE_OPENSL) + opensl_init, + #endif +diff --git media/libcubeb/src/cubeb_alsa.c media/libcubeb/src/cubeb_alsa.c +index bfd4d8f..a29eed0 100644 +--- media/libcubeb/src/cubeb_alsa.c ++++ media/libcubeb/src/cubeb_alsa.c +@@ -14,10 +14,58 @@ + #include <limits.h> + #include <poll.h> + #include <unistd.h> ++#include <dlfcn.h> + #include <alsa/asoundlib.h> + #include "cubeb/cubeb.h" + #include "cubeb-internal.h" + ++#ifdef DISABLE_LIBASOUND_DLOPEN ++#define WRAP(x) x ++#else ++#define WRAP(x) cubeb_##x ++#define LIBASOUND_API_VISIT(X) \ ++ X(snd_config) \ ++ X(snd_config_add) \ ++ X(snd_config_copy) \ ++ X(snd_config_delete) \ ++ X(snd_config_get_id) \ ++ X(snd_config_get_string) \ ++ X(snd_config_imake_integer) \ ++ X(snd_config_search) \ ++ X(snd_config_search_definition) \ ++ X(snd_lib_error_set_handler) \ ++ X(snd_pcm_avail_update) \ ++ X(snd_pcm_close) \ ++ X(snd_pcm_delay) \ ++ X(snd_pcm_drain) \ ++ X(snd_pcm_frames_to_bytes) \ ++ X(snd_pcm_get_params) \ ++ X(snd_pcm_hw_params_any) \ ++ X(snd_pcm_hw_params_get_channels_max) \ ++ X(snd_pcm_hw_params_get_rate) \ ++ X(snd_pcm_hw_params_set_rate_near) \ ++ X(snd_pcm_hw_params_sizeof) \ ++ X(snd_pcm_nonblock) \ ++ X(snd_pcm_open) \ ++ X(snd_pcm_open_lconf) \ ++ X(snd_pcm_pause) \ ++ X(snd_pcm_poll_descriptors) \ ++ X(snd_pcm_poll_descriptors_count) \ ++ X(snd_pcm_poll_descriptors_revents) \ ++ X(snd_pcm_readi) \ ++ X(snd_pcm_recover) \ ++ X(snd_pcm_set_params) \ ++ X(snd_pcm_start) \ ++ X(snd_pcm_state) \ ++ X(snd_pcm_writei) \ ++ ++#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x; ++LIBASOUND_API_VISIT(MAKE_TYPEDEF); ++#undef MAKE_TYPEDEF ++/* snd_pcm_hw_params_alloca is actually a macro */ ++#define snd_pcm_hw_params_sizeof cubeb_snd_pcm_hw_params_sizeof ++#endif ++ + #define CUBEB_STREAM_MAX 16 + #define CUBEB_WATCHDOG_MS 10000 + +@@ -36,6 +84,7 @@ static struct cubeb_ops const alsa_ops; + + struct cubeb { + struct cubeb_ops const * ops; ++ void * libasound; + + pthread_t thread; + +@@ -245,8 +294,8 @@ set_timeout(struct timeval * timeout, unsigned int ms) + static void + stream_buffer_decrement(cubeb_stream * stm, long count) + { +- char * bufremains = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, count); +- memmove(stm->buffer, bufremains, snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes - count)); ++ char * bufremains = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, count); ++ memmove(stm->buffer, bufremains, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes - count)); + stm->bufframes -= count; + } + +@@ -278,9 +327,9 @@ alsa_process_stream(cubeb_stream * stm) + /* Call _poll_descriptors_revents() even if we don't use it + to let underlying plugins clear null events. Otherwise poll() + may wake up again and again, producing unnecessary CPU usage. */ +- snd_pcm_poll_descriptors_revents(stm->pcm, stm->fds, stm->nfds, &revents); ++ WRAP(snd_pcm_poll_descriptors_revents)(stm->pcm, stm->fds, stm->nfds, &revents); + +- avail = snd_pcm_avail_update(stm->pcm); ++ avail = WRAP(snd_pcm_avail_update)(stm->pcm); + + /* Got null event? Bail and wait for another wakeup. */ + if (avail == 0) { +@@ -303,7 +352,7 @@ alsa_process_stream(cubeb_stream * stm) + // TODO: should it be marked as DRAINING? + } + +- got = snd_pcm_readi(stm->pcm, stm->buffer+stm->bufframes, avail); ++ got = WRAP(snd_pcm_readi)(stm->pcm, stm->buffer+stm->bufframes, avail); + + if (got < 0) { + avail = got; // the error handler below will recover us +@@ -347,7 +396,7 @@ alsa_process_stream(cubeb_stream * stm) + (!stm->other_stream || stm->other_stream->bufframes > 0)) { + long got = avail - stm->bufframes; + void * other_buffer = stm->other_stream ? stm->other_stream->buffer : NULL; +- char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes); ++ char * buftail = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes); + + /* Correct read size to the other stream available frames */ + if (stm->other_stream && got > (snd_pcm_sframes_t) stm->other_stream->bufframes) { +@@ -374,8 +423,8 @@ alsa_process_stream(cubeb_stream * stm) + long drain_frames = avail - stm->bufframes; + double drain_time = (double) drain_frames / stm->params.rate; + +- char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes); +- memset(buftail, 0, snd_pcm_frames_to_bytes(stm->pcm, drain_frames)); ++ char * buftail = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes); ++ memset(buftail, 0, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, drain_frames)); + stm->bufframes = avail; + + /* Mark as draining, unless we're waiting for capture */ +@@ -402,7 +451,7 @@ alsa_process_stream(cubeb_stream * stm) + } + } + +- wrote = snd_pcm_writei(stm->pcm, stm->buffer, avail); ++ wrote = WRAP(snd_pcm_writei)(stm->pcm, stm->buffer, avail); + if (wrote < 0) { + avail = wrote; // the error handler below will recover us + } else { +@@ -415,13 +464,13 @@ alsa_process_stream(cubeb_stream * stm) + + /* Got some error? Let's try to recover the stream. */ + if (avail < 0) { +- avail = snd_pcm_recover(stm->pcm, avail, 0); ++ avail = WRAP(snd_pcm_recover)(stm->pcm, avail, 0); + + /* Capture pcm must be started after initial setup/recover */ + if (avail >= 0 && + stm->stream_type == SND_PCM_STREAM_CAPTURE && +- snd_pcm_state(stm->pcm) == SND_PCM_STATE_PREPARED) { +- avail = snd_pcm_start(stm->pcm); ++ WRAP(snd_pcm_state)(stm->pcm) == SND_PCM_STATE_PREPARED) { ++ avail = WRAP(snd_pcm_start)(stm->pcm); + } + } + +@@ -537,26 +586,26 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + + slave_def = NULL; + +- r = snd_config_search(root_pcm, "slave", &slave_pcm); ++ r = WRAP(snd_config_search)(root_pcm, "slave", &slave_pcm); + if (r < 0) { + return NULL; + } + +- r = snd_config_get_string(slave_pcm, &string); ++ r = WRAP(snd_config_get_string)(slave_pcm, &string); + if (r >= 0) { +- r = snd_config_search_definition(lconf, "pcm_slave", string, &slave_def); ++ r = WRAP(snd_config_search_definition)(lconf, "pcm_slave", string, &slave_def); + if (r < 0) { + return NULL; + } + } + + do { +- r = snd_config_search(slave_def ? slave_def : slave_pcm, "pcm", &pcm); ++ r = WRAP(snd_config_search)(slave_def ? slave_def : slave_pcm, "pcm", &pcm); + if (r < 0) { + break; + } + +- r = snd_config_get_string(slave_def ? slave_def : slave_pcm, &string); ++ r = WRAP(snd_config_get_string)(slave_def ? slave_def : slave_pcm, &string); + if (r < 0) { + break; + } +@@ -565,7 +614,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + if (r < 0 || r > (int) sizeof(node_name)) { + break; + } +- r = snd_config_search(lconf, node_name, &pcm); ++ r = WRAP(snd_config_search)(lconf, node_name, &pcm); + if (r < 0) { + break; + } +@@ -574,7 +623,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + } while (0); + + if (slave_def) { +- snd_config_delete(slave_def); ++ WRAP(snd_config_delete)(slave_def); + } + + return NULL; +@@ -597,22 +646,22 @@ init_local_config_with_workaround(char const * pcm_name) + + lconf = NULL; + +- if (snd_config == NULL) { ++ if (*WRAP(snd_config) == NULL) { + return NULL; + } + +- r = snd_config_copy(&lconf, snd_config); ++ r = WRAP(snd_config_copy)(&lconf, *WRAP(snd_config)); + if (r < 0) { + return NULL; + } + + do { +- r = snd_config_search_definition(lconf, "pcm", pcm_name, &pcm_node); ++ r = WRAP(snd_config_search_definition)(lconf, "pcm", pcm_name, &pcm_node); + if (r < 0) { + break; + } + +- r = snd_config_get_id(pcm_node, &string); ++ r = WRAP(snd_config_get_id)(pcm_node, &string); + if (r < 0) { + break; + } +@@ -621,7 +670,7 @@ init_local_config_with_workaround(char const * pcm_name) + if (r < 0 || r > (int) sizeof(node_name)) { + break; + } +- r = snd_config_search(lconf, node_name, &pcm_node); ++ r = WRAP(snd_config_search)(lconf, node_name, &pcm_node); + if (r < 0) { + break; + } +@@ -632,12 +681,12 @@ init_local_config_with_workaround(char const * pcm_name) + } + + /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */ +- r = snd_config_search(pcm_node, "type", &node); ++ r = WRAP(snd_config_search)(pcm_node, "type", &node); + if (r < 0) { + break; + } + +- r = snd_config_get_string(node, &string); ++ r = WRAP(snd_config_get_string)(node, &string); + if (r < 0) { + break; + } +@@ -648,18 +697,18 @@ init_local_config_with_workaround(char const * pcm_name) + + /* Don't clobber an explicit existing handle_underrun value, set it only + if it doesn't already exist. */ +- r = snd_config_search(pcm_node, "handle_underrun", &node); ++ r = WRAP(snd_config_search)(pcm_node, "handle_underrun", &node); + if (r != -ENOENT) { + break; + } + + /* Disable pcm_pulse's asynchronous underrun handling. */ +- r = snd_config_imake_integer(&node, "handle_underrun", 0); ++ r = WRAP(snd_config_imake_integer)(&node, "handle_underrun", 0); + if (r < 0) { + break; + } + +- r = snd_config_add(pcm_node, node); ++ r = WRAP(snd_config_add)(pcm_node, node); + if (r < 0) { + break; + } +@@ -667,7 +716,7 @@ init_local_config_with_workaround(char const * pcm_name) + return lconf; + } while (0); + +- snd_config_delete(lconf); ++ WRAP(snd_config_delete)(lconf); + + return NULL; + } +@@ -679,9 +728,9 @@ alsa_locked_pcm_open(snd_pcm_t ** pcm, char const * pcm_name, snd_pcm_stream_t s + + pthread_mutex_lock(&cubeb_alsa_mutex); + if (local_config) { +- r = snd_pcm_open_lconf(pcm, pcm_name, stream, SND_PCM_NONBLOCK, local_config); ++ r = WRAP(snd_pcm_open_lconf)(pcm, pcm_name, stream, SND_PCM_NONBLOCK, local_config); + } else { +- r = snd_pcm_open(pcm, pcm_name, stream, SND_PCM_NONBLOCK); ++ r = WRAP(snd_pcm_open)(pcm, pcm_name, stream, SND_PCM_NONBLOCK); + } + pthread_mutex_unlock(&cubeb_alsa_mutex); + +@@ -694,7 +743,7 @@ alsa_locked_pcm_close(snd_pcm_t * pcm) + int r; + + pthread_mutex_lock(&cubeb_alsa_mutex); +- r = snd_pcm_close(pcm); ++ r = WRAP(snd_pcm_close)(pcm); + pthread_mutex_unlock(&cubeb_alsa_mutex); + + return r; +@@ -750,6 +799,7 @@ silent_error_handler(char const * file, int line, char const * function, + alsa_init(cubeb ** context, char const * context_name) + { + (void)context_name; ++ void * libasound = NULL; + cubeb * ctx; + int r; + int i; +@@ -760,9 +810,27 @@ alsa_init(cubeb ** context, char const * context_name) + assert(context); + *context = NULL; + ++#ifndef DISABLE_LIBASOUND_DLOPEN ++ libasound = dlopen("libasound.so", RTLD_LAZY); ++ if (!libasound) { ++ return CUBEB_ERROR; ++ } ++ ++#define LOAD(x) { \ ++ cubeb_##x = dlsym(libasound, #x); \ ++ if (!cubeb_##x) { \ ++ dlclose(libasound); \ ++ return CUBEB_ERROR; \ ++ } \ ++ } ++ ++ LIBASOUND_API_VISIT(LOAD); ++#undef LOAD ++#endif ++ + pthread_mutex_lock(&cubeb_alsa_mutex); + if (!cubeb_alsa_error_handler_set) { +- snd_lib_error_set_handler(silent_error_handler); ++ WRAP(snd_lib_error_set_handler)(silent_error_handler); + cubeb_alsa_error_handler_set = 1; + } + pthread_mutex_unlock(&cubeb_alsa_mutex); +@@ -771,6 +839,7 @@ alsa_init(cubeb ** context, char const * context_name) + assert(ctx); + + ctx->ops = &alsa_ops; ++ ctx->libasound = libasound; + + r = pthread_mutex_init(&ctx->mutex, NULL); + assert(r == 0); +@@ -819,7 +888,7 @@ alsa_init(cubeb ** context, char const * context_name) + config fails with EINVAL, the PA PCM is too old for this workaround. */ + if (r == -EINVAL) { + pthread_mutex_lock(&cubeb_alsa_mutex); +- snd_config_delete(ctx->local_config); ++ WRAP(snd_config_delete)(ctx->local_config); + pthread_mutex_unlock(&cubeb_alsa_mutex); + ctx->local_config = NULL; + } else if (r >= 0) { +@@ -861,10 +930,14 @@ alsa_destroy(cubeb * ctx) + + if (ctx->local_config) { + pthread_mutex_lock(&cubeb_alsa_mutex); +- snd_config_delete(ctx->local_config); ++ WRAP(snd_config_delete)(ctx->local_config); + pthread_mutex_unlock(&cubeb_alsa_mutex); + } + ++ if (ctx->libasound) { ++ dlclose(ctx->libasound); ++ } ++ + free(ctx); + } + +@@ -948,7 +1021,7 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + return CUBEB_ERROR; + } + +- r = snd_pcm_nonblock(stm->pcm, 1); ++ r = WRAP(snd_pcm_nonblock)(stm->pcm, 1); + assert(r == 0); + + latency_us = latency_frames * 1e6 / stm->params.rate; +@@ -961,7 +1034,7 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + latency_us = latency_us < min_latency ? min_latency: latency_us; + } + +- r = snd_pcm_set_params(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED, ++ r = WRAP(snd_pcm_set_params)(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED, + stm->params.channels, stm->params.rate, 1, + latency_us); + if (r < 0) { +@@ -969,20 +1042,20 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + return CUBEB_ERROR_INVALID_FORMAT; + } + +- r = snd_pcm_get_params(stm->pcm, &stm->buffer_size, &period_size); ++ r = WRAP(snd_pcm_get_params)(stm->pcm, &stm->buffer_size, &period_size); + assert(r == 0); + + /* Double internal buffer size to have enough space when waiting for the other side of duplex connection */ + stm->buffer_size *= 2; +- stm->buffer = calloc(1, snd_pcm_frames_to_bytes(stm->pcm, stm->buffer_size)); ++ stm->buffer = calloc(1, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->buffer_size)); + assert(stm->buffer); + +- stm->nfds = snd_pcm_poll_descriptors_count(stm->pcm); ++ stm->nfds = WRAP(snd_pcm_poll_descriptors_count)(stm->pcm); + assert(stm->nfds > 0); + + stm->saved_fds = calloc(stm->nfds, sizeof(struct pollfd)); + assert(stm->saved_fds); +- r = snd_pcm_poll_descriptors(stm->pcm, stm->saved_fds, stm->nfds); ++ r = WRAP(snd_pcm_poll_descriptors)(stm->pcm, stm->saved_fds, stm->nfds); + assert((nfds_t) r == stm->nfds); + + if (alsa_register_stream(ctx, stm) != 0) { +@@ -1054,7 +1127,7 @@ alsa_stream_destroy(cubeb_stream * stm) + pthread_mutex_lock(&stm->mutex); + if (stm->pcm) { + if (stm->state == DRAINING) { +- snd_pcm_drain(stm->pcm); ++ WRAP(snd_pcm_drain)(stm->pcm); + } + alsa_locked_pcm_close(stm->pcm); + stm->pcm = NULL; +@@ -1100,12 +1173,12 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) + + assert(stm); + +- r = snd_pcm_hw_params_any(stm->pcm, hw_params); ++ r = WRAP(snd_pcm_hw_params_any)(stm->pcm, hw_params); + if (r < 0) { + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_get_channels_max(hw_params, max_channels); ++ r = WRAP(snd_pcm_hw_params_get_channels_max)(hw_params, max_channels); + if (r < 0) { + return CUBEB_ERROR; + } +@@ -1126,34 +1199,34 @@ 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. */ +- r = snd_pcm_open(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE); ++ r = WRAP(snd_pcm_open)(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE); + if (r < 0) { + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_any(pcm, hw_params); ++ r = WRAP(snd_pcm_hw_params_any)(pcm, hw_params); + if (r < 0) { +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_get_rate(hw_params, rate, &dir); ++ r = WRAP(snd_pcm_hw_params_get_rate)(hw_params, rate, &dir); + if (r >= 0) { + /* There is a default rate: use it. */ +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_OK; + } + + /* Use a common rate, alsa may adjust it based on hw/etc. capabilities. */ + *rate = 44100; + +- r = snd_pcm_hw_params_set_rate_near(pcm, hw_params, rate, NULL); ++ r = WRAP(snd_pcm_hw_params_set_rate_near)(pcm, hw_params, rate, NULL); + if (r < 0) { +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_ERROR; + } + +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + + return CUBEB_OK; + } +@@ -1186,10 +1259,10 @@ alsa_stream_start(cubeb_stream * stm) + pthread_mutex_lock(&stm->mutex); + /* Capture pcm must be started after initial setup/recover */ + if (stm->stream_type == SND_PCM_STREAM_CAPTURE && +- snd_pcm_state(stm->pcm) == SND_PCM_STATE_PREPARED) { +- snd_pcm_start(stm->pcm); ++ WRAP(snd_pcm_state)(stm->pcm) == SND_PCM_STATE_PREPARED) { ++ WRAP(snd_pcm_start)(stm->pcm); + } +- snd_pcm_pause(stm->pcm, 0); ++ WRAP(snd_pcm_pause)(stm->pcm, 0); + gettimeofday(&stm->last_activity, NULL); + pthread_mutex_unlock(&stm->mutex); + +@@ -1229,7 +1302,7 @@ alsa_stream_stop(cubeb_stream * stm) + pthread_mutex_unlock(&ctx->mutex); + + pthread_mutex_lock(&stm->mutex); +- snd_pcm_pause(stm->pcm, 1); ++ WRAP(snd_pcm_pause)(stm->pcm, 1); + pthread_mutex_unlock(&stm->mutex); + + return CUBEB_OK; +@@ -1245,8 +1318,8 @@ alsa_stream_get_position(cubeb_stream * stm, uint64_t * position) + pthread_mutex_lock(&stm->mutex); + + delay = -1; +- if (snd_pcm_state(stm->pcm) != SND_PCM_STATE_RUNNING || +- snd_pcm_delay(stm->pcm, &delay) != 0) { ++ if (WRAP(snd_pcm_state)(stm->pcm) != SND_PCM_STATE_RUNNING || ++ WRAP(snd_pcm_delay)(stm->pcm, &delay) != 0) { + *position = stm->last_position; + pthread_mutex_unlock(&stm->mutex); + return CUBEB_OK; +@@ -1271,7 +1344,7 @@ alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency) + snd_pcm_sframes_t delay; + /* This function returns the delay in frames until a frame written using + snd_pcm_writei is sent to the DAC. The DAC delay should be < 1ms anyways. */ +- if (snd_pcm_delay(stm->pcm, &delay)) { ++ if (WRAP(snd_pcm_delay)(stm->pcm, &delay)) { + return CUBEB_ERROR; + } + +diff --git media/libcubeb/src/cubeb_sndio.c media/libcubeb/src/cubeb_sndio.c +index 9e99b2c..0559af4 100644 +--- media/libcubeb/src/cubeb_sndio.c ++++ media/libcubeb/src/cubeb_sndio.c +@@ -12,6 +12,7 @@ + #include <stdbool.h> + #include <stdlib.h> + #include <stdio.h> ++#include <dlfcn.h> + #include <assert.h> + #include "cubeb/cubeb.h" + #include "cubeb-internal.h" +@@ -22,10 +23,35 @@ + #define DPR(...) do {} while(0) + #endif + ++#ifdef DISABLE_LIBSNDIO_DLOPEN ++#define WRAP(x) x ++#else ++#define WRAP(x) cubeb_##x ++#define LIBSNDIO_API_VISIT(X) \ ++ X(sio_close) \ ++ X(sio_eof) \ ++ X(sio_getpar) \ ++ X(sio_initpar) \ ++ X(sio_onmove) \ ++ X(sio_open) \ ++ X(sio_pollfd) \ ++ X(sio_read) \ ++ X(sio_revents) \ ++ X(sio_setpar) \ ++ X(sio_start) \ ++ X(sio_stop) \ ++ X(sio_write) \ ++ ++#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x; ++LIBSNDIO_API_VISIT(MAKE_TYPEDEF); ++#undef MAKE_TYPEDEF ++#endif ++ + static struct cubeb_ops const sndio_ops; + + struct cubeb { + struct cubeb_ops const * ops; ++ void * libsndio; + }; + + struct cubeb_stream { +@@ -119,7 +145,7 @@ sndio_mainloop(void *arg) + DPR("sndio_mainloop()\n"); + s->state_cb(s, s->arg, CUBEB_STATE_STARTED); + pthread_mutex_lock(&s->mtx); +- if (!sio_start(s->hdl)) { ++ if (!WRAP(sio_start)(s->hdl)) { + pthread_mutex_unlock(&s->mtx); + return NULL; + } +@@ -203,7 +229,7 @@ sndio_mainloop(void *arg) + events |= POLLIN; + if ((s->mode & SIO_PLAY) && pstart < pend) + events |= POLLOUT; +- nfds = sio_pollfd(s->hdl, pfds, events); ++ nfds = WRAP(sio_pollfd)(s->hdl, pfds, events); + + if (nfds > 0) { + pthread_mutex_unlock(&s->mtx); +@@ -213,7 +239,7 @@ sndio_mainloop(void *arg) + continue; + } + +- revents = sio_revents(s->hdl, pfds); ++ revents = WRAP(sio_revents)(s->hdl, pfds); + + if (revents & POLLHUP) { + state = CUBEB_STATE_ERROR; +@@ -221,8 +247,8 @@ sndio_mainloop(void *arg) + } + + if (revents & POLLOUT) { +- n = sio_write(s->hdl, s->pbuf + pstart, pend - pstart); +- if (n == 0 && sio_eof(s->hdl)) { ++ n = WRAP(sio_write)(s->hdl, s->pbuf + pstart, pend - pstart); ++ if (n == 0 && WRAP(sio_eof)(s->hdl)) { + DPR("sndio_mainloop() werr\n"); + state = CUBEB_STATE_ERROR; + break; +@@ -231,8 +257,8 @@ sndio_mainloop(void *arg) + } + + if (revents & POLLIN) { +- n = sio_read(s->hdl, s->rbuf + rstart, rend - rstart); +- if (n == 0 && sio_eof(s->hdl)) { ++ n = WRAP(sio_read)(s->hdl, s->rbuf + rstart, rend - rstart); ++ if (n == 0 && WRAP(sio_eof)(s->hdl)) { + DPR("sndio_mainloop() rerr\n"); + state = CUBEB_STATE_ERROR; + break; +@@ -244,7 +270,7 @@ sndio_mainloop(void *arg) + if (prime > 0 && (s->mode & SIO_REC)) + rstart = rend; + } +- sio_stop(s->hdl); ++ WRAP(sio_stop)(s->hdl); + s->hwpos = s->swpos; + pthread_mutex_unlock(&s->mtx); + s->state_cb(s, s->arg, state); +@@ -254,8 +280,31 @@ sndio_mainloop(void *arg) + /*static*/ int + sndio_init(cubeb **context, char const *context_name) + { ++ void * libsndio = NULL; ++ ++#ifndef DISABLE_LIBSNDIO_DLOPEN ++ libsndio = dlopen("libsndio.so", RTLD_LAZY); ++ if (!libsndio) { ++ DPR("sndio_init(%s) failed dlopen(libsndio.so)\n", context_name); ++ return CUBEB_ERROR; ++ } ++ ++#define LOAD(x) { \ ++ cubeb_##x = dlsym(libsndio, #x); \ ++ if (!cubeb_##x) { \ ++ DPR("sndio_init(%s) failed dlsym(%s)\n", context_name, #x); \ ++ dlclose(libsndio); \ ++ return CUBEB_ERROR; \ ++ } \ ++ } ++ ++ LIBSNDIO_API_VISIT(LOAD); ++#undef LOAD ++#endif ++ + DPR("sndio_init(%s)\n", context_name); + *context = malloc(sizeof(*context)); ++ (*context)->libsndio = libsndio; + (*context)->ops = &sndio_ops; + (void)context_name; + return CUBEB_OK; +@@ -271,6 +320,8 @@ static void + sndio_destroy(cubeb *context) + { + DPR("sndio_destroy()\n"); ++ if (context->libsndio) ++ dlclose(context->libsndio); + free(context); + } + +@@ -323,12 +374,12 @@ sndio_stream_init(cubeb * context, + goto err; + } + s->context = context; +- s->hdl = sio_open(NULL, s->mode, 1); ++ s->hdl = WRAP(sio_open)(NULL, s->mode, 1); + if (s->hdl == NULL) { + DPR("sndio_stream_init(), sio_open() failed\n"); + goto err; + } +- sio_initpar(&wpar); ++ WRAP(sio_initpar)(&wpar); + wpar.sig = 1; + wpar.bits = 16; + switch (format) { +@@ -351,7 +402,7 @@ sndio_stream_init(cubeb * context, + if (s->mode & SIO_PLAY) + wpar.pchan = output_stream_params->channels; + wpar.appbufsz = latency_frames; +- if (!sio_setpar(s->hdl, &wpar) || !sio_getpar(s->hdl, &rpar)) { ++ if (!WRAP(sio_setpar)(s->hdl, &wpar) || !WRAP(sio_getpar)(s->hdl, &rpar)) { + DPR("sndio_stream_init(), sio_setpar() failed\n"); + goto err; + } +@@ -362,7 +413,7 @@ sndio_stream_init(cubeb * context, + DPR("sndio_stream_init() unsupported params\n"); + goto err; + } +- sio_onmove(s->hdl, sndio_onmove, s); ++ WRAP(sio_onmove)(s->hdl, sndio_onmove, s); + s->active = 0; + s->nfr = rpar.round; + s->rbpf = rpar.bps * rpar.rchan; +@@ -400,7 +451,7 @@ sndio_stream_init(cubeb * context, + return CUBEB_OK; + err: + if (s->hdl) +- sio_close(s->hdl); ++ WRAP(sio_close)(s->hdl); + if (s->pbuf) + free(s->pbuf); + if (s->rbuf) +@@ -446,7 +497,7 @@ static void + sndio_stream_destroy(cubeb_stream *s) + { + DPR("sndio_stream_destroy()\n"); +- sio_close(s->hdl); ++ WRAP(sio_close)(s->hdl); + if (s->mode & SIO_PLAY) + free(s->pbuf); + if (s->mode & SIO_REC) +diff --git toolkit/library/moz.build toolkit/library/moz.build +index 8ce595ff96bff..c318e96a1fdfc 100644 +--- toolkit/library/moz.build ++++ toolkit/library/moz.build +@@ -231,9 +231,6 @@ if CONFIG['MOZ_SYSTEM_LIBVPX']: + if not CONFIG['MOZ_TREE_PIXMAN']: + OS_LIBS += CONFIG['MOZ_PIXMAN_LIBS'] + +-if CONFIG['MOZ_ALSA']: +- OS_LIBS += CONFIG['MOZ_ALSA_LIBS'] +- + if CONFIG['HAVE_CLOCK_MONOTONIC']: + OS_LIBS += CONFIG['REALTIME_LIBS'] + +@@ -242,11 +239,6 @@ OS_LIBS += CONFIG['ICONV_LIBS'] + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'): + OS_LIBS += CONFIG['TK_LIBS'] + +-if CONFIG['OS_ARCH'] == 'OpenBSD': +- OS_LIBS += [ +- 'sndio', +- ] +- + if CONFIG['MOZ_ENABLE_DBUS']: + OS_LIBS += CONFIG['MOZ_DBUS_GLIB_LIBS'] + diff --git a/www/firefox/Makefile b/www/firefox/Makefile index bbebd5046f32..dcfef1de663e 100644 --- a/www/firefox/Makefile +++ b/www/firefox/Makefile @@ -3,7 +3,7 @@ PORTNAME= firefox DISTVERSION= 69.0 -PORTREVISION= 1 +PORTREVISION= 2 PORTEPOCH= 1 CATEGORIES= www ipv6 MASTER_SITES= MOZILLA/${PORTNAME}/releases/${DISTVERSION}/source \ diff --git a/www/firefox/Makefile.options b/www/firefox/Makefile.options index cbb4e78f5a7e..c522dd1d1fc5 100644 --- a/www/firefox/Makefile.options +++ b/www/firefox/Makefile.options @@ -4,7 +4,7 @@ OPTIONS_DEFINE+= CANBERRA DBUS DEBUG FFMPEG GCONF \ LIBPROXY OPTIMIZED_CFLAGS PROFILE TEST OPTIONS_DEFAULT+= DBUS FFMPEG GCONF OPTIMIZED_CFLAGS PROFILE \ - ${OPTIONS_MULTI_AUDIO:NSNDIO} + ${OPTIONS_MULTI_AUDIO} OPTIONS_MULTI+= AUDIO OPTIONS_MULTI_AUDIO= ALSA JACK PULSEAUDIO SNDIO diff --git a/www/firefox/files/patch-cubeb-dlopen b/www/firefox/files/patch-cubeb-dlopen new file mode 100644 index 000000000000..cdf25e433802 --- /dev/null +++ b/www/firefox/files/patch-cubeb-dlopen @@ -0,0 +1,793 @@ +https://github.com/kinetiknz/cubeb/pull/539 + +diff --git media/libcubeb/gtest/moz.build media/libcubeb/gtest/moz.build +index 1ff0c02545251..ca364d1ef7845 100644 +--- media/libcubeb/gtest/moz.build ++++ media/libcubeb/gtest/moz.build +@@ -67,13 +67,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit': + '-framework CoreFoundation', + '-framework AudioToolbox', + ] +-elif CONFIG['OS_TARGET'] == 'OpenBSD': +- OS_LIBS += [ +- 'sndio', +- ] +-else: +- OS_LIBS += CONFIG['MOZ_ALSA_LIBS'] +- OS_LIBS += CONFIG['MOZ_PULSEAUDIO_LIBS'] + + if CONFIG['CC_TYPE'] in ('clang', 'gcc'): + CXXFLAGS += ['-Wno-error=shadow'] +diff --git media/libcubeb/src/cubeb.c media/libcubeb/src/cubeb.c +index 422f7c6..caac869 100644 +--- media/libcubeb/src/cubeb.c ++++ media/libcubeb/src/cubeb.c +@@ -194,6 +194,9 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam + #if defined(USE_JACK) + jack_init, + #endif ++#if defined(USE_SNDIO) ++ sndio_init, ++#endif + #if defined(USE_ALSA) + alsa_init, + #endif +@@ -209,9 +212,6 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam + #if defined(USE_WINMM) + winmm_init, + #endif +-#if defined(USE_SNDIO) +- sndio_init, +-#endif + #if defined(USE_SUN) + sun_init, + #endif +diff --git media/libcubeb/src/cubeb_alsa.c media/libcubeb/src/cubeb_alsa.c +index bfd4d8f..a29eed0 100644 +--- media/libcubeb/src/cubeb_alsa.c ++++ media/libcubeb/src/cubeb_alsa.c +@@ -14,10 +14,58 @@ + #include <limits.h> + #include <poll.h> + #include <unistd.h> ++#include <dlfcn.h> + #include <alsa/asoundlib.h> + #include "cubeb/cubeb.h" + #include "cubeb-internal.h" + ++#ifdef DISABLE_LIBASOUND_DLOPEN ++#define WRAP(x) x ++#else ++#define WRAP(x) cubeb_##x ++#define LIBASOUND_API_VISIT(X) \ ++ X(snd_config) \ ++ X(snd_config_add) \ ++ X(snd_config_copy) \ ++ X(snd_config_delete) \ ++ X(snd_config_get_id) \ ++ X(snd_config_get_string) \ ++ X(snd_config_imake_integer) \ ++ X(snd_config_search) \ ++ X(snd_config_search_definition) \ ++ X(snd_lib_error_set_handler) \ ++ X(snd_pcm_avail_update) \ ++ X(snd_pcm_close) \ ++ X(snd_pcm_delay) \ ++ X(snd_pcm_drain) \ ++ X(snd_pcm_frames_to_bytes) \ ++ X(snd_pcm_get_params) \ ++ X(snd_pcm_hw_params_any) \ ++ X(snd_pcm_hw_params_get_channels_max) \ ++ X(snd_pcm_hw_params_get_rate) \ ++ X(snd_pcm_hw_params_set_rate_near) \ ++ X(snd_pcm_hw_params_sizeof) \ ++ X(snd_pcm_nonblock) \ ++ X(snd_pcm_open) \ ++ X(snd_pcm_open_lconf) \ ++ X(snd_pcm_pause) \ ++ X(snd_pcm_poll_descriptors) \ ++ X(snd_pcm_poll_descriptors_count) \ ++ X(snd_pcm_poll_descriptors_revents) \ ++ X(snd_pcm_readi) \ ++ X(snd_pcm_recover) \ ++ X(snd_pcm_set_params) \ ++ X(snd_pcm_start) \ ++ X(snd_pcm_state) \ ++ X(snd_pcm_writei) \ ++ ++#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x; ++LIBASOUND_API_VISIT(MAKE_TYPEDEF); ++#undef MAKE_TYPEDEF ++/* snd_pcm_hw_params_alloca is actually a macro */ ++#define snd_pcm_hw_params_sizeof cubeb_snd_pcm_hw_params_sizeof ++#endif ++ + #define CUBEB_STREAM_MAX 16 + #define CUBEB_WATCHDOG_MS 10000 + +@@ -36,6 +84,7 @@ static struct cubeb_ops const alsa_ops; + + struct cubeb { + struct cubeb_ops const * ops; ++ void * libasound; + + pthread_t thread; + +@@ -245,8 +294,8 @@ set_timeout(struct timeval * timeout, unsigned int ms) + static void + stream_buffer_decrement(cubeb_stream * stm, long count) + { +- char * bufremains = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, count); +- memmove(stm->buffer, bufremains, snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes - count)); ++ char * bufremains = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, count); ++ memmove(stm->buffer, bufremains, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes - count)); + stm->bufframes -= count; + } + +@@ -278,9 +327,9 @@ alsa_process_stream(cubeb_stream * stm) + /* Call _poll_descriptors_revents() even if we don't use it + to let underlying plugins clear null events. Otherwise poll() + may wake up again and again, producing unnecessary CPU usage. */ +- snd_pcm_poll_descriptors_revents(stm->pcm, stm->fds, stm->nfds, &revents); ++ WRAP(snd_pcm_poll_descriptors_revents)(stm->pcm, stm->fds, stm->nfds, &revents); + +- avail = snd_pcm_avail_update(stm->pcm); ++ avail = WRAP(snd_pcm_avail_update)(stm->pcm); + + /* Got null event? Bail and wait for another wakeup. */ + if (avail == 0) { +@@ -303,7 +352,7 @@ alsa_process_stream(cubeb_stream * stm) + // TODO: should it be marked as DRAINING? + } + +- got = snd_pcm_readi(stm->pcm, stm->buffer+stm->bufframes, avail); ++ got = WRAP(snd_pcm_readi)(stm->pcm, stm->buffer+stm->bufframes, avail); + + if (got < 0) { + avail = got; // the error handler below will recover us +@@ -347,7 +396,7 @@ alsa_process_stream(cubeb_stream * stm) + (!stm->other_stream || stm->other_stream->bufframes > 0)) { + long got = avail - stm->bufframes; + void * other_buffer = stm->other_stream ? stm->other_stream->buffer : NULL; +- char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes); ++ char * buftail = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes); + + /* Correct read size to the other stream available frames */ + if (stm->other_stream && got > (snd_pcm_sframes_t) stm->other_stream->bufframes) { +@@ -374,8 +423,8 @@ alsa_process_stream(cubeb_stream * stm) + long drain_frames = avail - stm->bufframes; + double drain_time = (double) drain_frames / stm->params.rate; + +- char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes); +- memset(buftail, 0, snd_pcm_frames_to_bytes(stm->pcm, drain_frames)); ++ char * buftail = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes); ++ memset(buftail, 0, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, drain_frames)); + stm->bufframes = avail; + + /* Mark as draining, unless we're waiting for capture */ +@@ -402,7 +451,7 @@ alsa_process_stream(cubeb_stream * stm) + } + } + +- wrote = snd_pcm_writei(stm->pcm, stm->buffer, avail); ++ wrote = WRAP(snd_pcm_writei)(stm->pcm, stm->buffer, avail); + if (wrote < 0) { + avail = wrote; // the error handler below will recover us + } else { +@@ -415,13 +464,13 @@ alsa_process_stream(cubeb_stream * stm) + + /* Got some error? Let's try to recover the stream. */ + if (avail < 0) { +- avail = snd_pcm_recover(stm->pcm, avail, 0); ++ avail = WRAP(snd_pcm_recover)(stm->pcm, avail, 0); + + /* Capture pcm must be started after initial setup/recover */ + if (avail >= 0 && + stm->stream_type == SND_PCM_STREAM_CAPTURE && +- snd_pcm_state(stm->pcm) == SND_PCM_STATE_PREPARED) { +- avail = snd_pcm_start(stm->pcm); ++ WRAP(snd_pcm_state)(stm->pcm) == SND_PCM_STATE_PREPARED) { ++ avail = WRAP(snd_pcm_start)(stm->pcm); + } + } + +@@ -537,26 +586,26 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + + slave_def = NULL; + +- r = snd_config_search(root_pcm, "slave", &slave_pcm); ++ r = WRAP(snd_config_search)(root_pcm, "slave", &slave_pcm); + if (r < 0) { + return NULL; + } + +- r = snd_config_get_string(slave_pcm, &string); ++ r = WRAP(snd_config_get_string)(slave_pcm, &string); + if (r >= 0) { +- r = snd_config_search_definition(lconf, "pcm_slave", string, &slave_def); ++ r = WRAP(snd_config_search_definition)(lconf, "pcm_slave", string, &slave_def); + if (r < 0) { + return NULL; + } + } + + do { +- r = snd_config_search(slave_def ? slave_def : slave_pcm, "pcm", &pcm); ++ r = WRAP(snd_config_search)(slave_def ? slave_def : slave_pcm, "pcm", &pcm); + if (r < 0) { + break; + } + +- r = snd_config_get_string(slave_def ? slave_def : slave_pcm, &string); ++ r = WRAP(snd_config_get_string)(slave_def ? slave_def : slave_pcm, &string); + if (r < 0) { + break; + } +@@ -565,7 +614,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + if (r < 0 || r > (int) sizeof(node_name)) { + break; + } +- r = snd_config_search(lconf, node_name, &pcm); ++ r = WRAP(snd_config_search)(lconf, node_name, &pcm); + if (r < 0) { + break; + } +@@ -574,7 +623,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + } while (0); + + if (slave_def) { +- snd_config_delete(slave_def); ++ WRAP(snd_config_delete)(slave_def); + } + + return NULL; +@@ -597,22 +646,22 @@ init_local_config_with_workaround(char const * pcm_name) + + lconf = NULL; + +- if (snd_config == NULL) { ++ if (*WRAP(snd_config) == NULL) { + return NULL; + } + +- r = snd_config_copy(&lconf, snd_config); ++ r = WRAP(snd_config_copy)(&lconf, *WRAP(snd_config)); + if (r < 0) { + return NULL; + } + + do { +- r = snd_config_search_definition(lconf, "pcm", pcm_name, &pcm_node); ++ r = WRAP(snd_config_search_definition)(lconf, "pcm", pcm_name, &pcm_node); + if (r < 0) { + break; + } + +- r = snd_config_get_id(pcm_node, &string); ++ r = WRAP(snd_config_get_id)(pcm_node, &string); + if (r < 0) { + break; + } +@@ -621,7 +670,7 @@ init_local_config_with_workaround(char const * pcm_name) + if (r < 0 || r > (int) sizeof(node_name)) { + break; + } +- r = snd_config_search(lconf, node_name, &pcm_node); ++ r = WRAP(snd_config_search)(lconf, node_name, &pcm_node); + if (r < 0) { + break; + } +@@ -632,12 +681,12 @@ init_local_config_with_workaround(char const * pcm_name) + } + + /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */ +- r = snd_config_search(pcm_node, "type", &node); ++ r = WRAP(snd_config_search)(pcm_node, "type", &node); + if (r < 0) { + break; + } + +- r = snd_config_get_string(node, &string); ++ r = WRAP(snd_config_get_string)(node, &string); + if (r < 0) { + break; + } +@@ -648,18 +697,18 @@ init_local_config_with_workaround(char const * pcm_name) + + /* Don't clobber an explicit existing handle_underrun value, set it only + if it doesn't already exist. */ +- r = snd_config_search(pcm_node, "handle_underrun", &node); ++ r = WRAP(snd_config_search)(pcm_node, "handle_underrun", &node); + if (r != -ENOENT) { + break; + } + + /* Disable pcm_pulse's asynchronous underrun handling. */ +- r = snd_config_imake_integer(&node, "handle_underrun", 0); ++ r = WRAP(snd_config_imake_integer)(&node, "handle_underrun", 0); + if (r < 0) { + break; + } + +- r = snd_config_add(pcm_node, node); ++ r = WRAP(snd_config_add)(pcm_node, node); + if (r < 0) { + break; + } +@@ -667,7 +716,7 @@ init_local_config_with_workaround(char const * pcm_name) + return lconf; + } while (0); + +- snd_config_delete(lconf); ++ WRAP(snd_config_delete)(lconf); + + return NULL; + } +@@ -679,9 +728,9 @@ alsa_locked_pcm_open(snd_pcm_t ** pcm, char const * pcm_name, snd_pcm_stream_t s + + pthread_mutex_lock(&cubeb_alsa_mutex); + if (local_config) { +- r = snd_pcm_open_lconf(pcm, pcm_name, stream, SND_PCM_NONBLOCK, local_config); ++ r = WRAP(snd_pcm_open_lconf)(pcm, pcm_name, stream, SND_PCM_NONBLOCK, local_config); + } else { +- r = snd_pcm_open(pcm, pcm_name, stream, SND_PCM_NONBLOCK); ++ r = WRAP(snd_pcm_open)(pcm, pcm_name, stream, SND_PCM_NONBLOCK); + } + pthread_mutex_unlock(&cubeb_alsa_mutex); + +@@ -694,7 +743,7 @@ alsa_locked_pcm_close(snd_pcm_t * pcm) + int r; + + pthread_mutex_lock(&cubeb_alsa_mutex); +- r = snd_pcm_close(pcm); ++ r = WRAP(snd_pcm_close)(pcm); + pthread_mutex_unlock(&cubeb_alsa_mutex); + + return r; +@@ -750,6 +799,7 @@ silent_error_handler(char const * file, int line, char const * function, + alsa_init(cubeb ** context, char const * context_name) + { + (void)context_name; ++ void * libasound = NULL; + cubeb * ctx; + int r; + int i; +@@ -760,9 +810,27 @@ alsa_init(cubeb ** context, char const * context_name) + assert(context); + *context = NULL; + ++#ifndef DISABLE_LIBASOUND_DLOPEN ++ libasound = dlopen("libasound.so", RTLD_LAZY); ++ if (!libasound) { ++ return CUBEB_ERROR; ++ } ++ ++#define LOAD(x) { \ ++ cubeb_##x = dlsym(libasound, #x); \ ++ if (!cubeb_##x) { \ ++ dlclose(libasound); \ ++ return CUBEB_ERROR; \ ++ } \ ++ } ++ ++ LIBASOUND_API_VISIT(LOAD); ++#undef LOAD ++#endif ++ + pthread_mutex_lock(&cubeb_alsa_mutex); + if (!cubeb_alsa_error_handler_set) { +- snd_lib_error_set_handler(silent_error_handler); ++ WRAP(snd_lib_error_set_handler)(silent_error_handler); + cubeb_alsa_error_handler_set = 1; + } + pthread_mutex_unlock(&cubeb_alsa_mutex); +@@ -771,6 +839,7 @@ alsa_init(cubeb ** context, char const * context_name) + assert(ctx); + + ctx->ops = &alsa_ops; ++ ctx->libasound = libasound; + + r = pthread_mutex_init(&ctx->mutex, NULL); + assert(r == 0); +@@ -819,7 +888,7 @@ alsa_init(cubeb ** context, char const * context_name) + config fails with EINVAL, the PA PCM is too old for this workaround. */ + if (r == -EINVAL) { + pthread_mutex_lock(&cubeb_alsa_mutex); +- snd_config_delete(ctx->local_config); ++ WRAP(snd_config_delete)(ctx->local_config); + pthread_mutex_unlock(&cubeb_alsa_mutex); + ctx->local_config = NULL; + } else if (r >= 0) { +@@ -861,10 +930,14 @@ alsa_destroy(cubeb * ctx) + + if (ctx->local_config) { + pthread_mutex_lock(&cubeb_alsa_mutex); +- snd_config_delete(ctx->local_config); ++ WRAP(snd_config_delete)(ctx->local_config); + pthread_mutex_unlock(&cubeb_alsa_mutex); + } + ++ if (ctx->libasound) { ++ dlclose(ctx->libasound); ++ } ++ + free(ctx); + } + +@@ -948,7 +1021,7 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + return CUBEB_ERROR; + } + +- r = snd_pcm_nonblock(stm->pcm, 1); ++ r = WRAP(snd_pcm_nonblock)(stm->pcm, 1); + assert(r == 0); + + latency_us = latency_frames * 1e6 / stm->params.rate; +@@ -961,7 +1034,7 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + latency_us = latency_us < min_latency ? min_latency: latency_us; + } + +- r = snd_pcm_set_params(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED, ++ r = WRAP(snd_pcm_set_params)(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED, + stm->params.channels, stm->params.rate, 1, + latency_us); + if (r < 0) { +@@ -969,20 +1042,20 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + return CUBEB_ERROR_INVALID_FORMAT; + } + +- r = snd_pcm_get_params(stm->pcm, &stm->buffer_size, &period_size); ++ r = WRAP(snd_pcm_get_params)(stm->pcm, &stm->buffer_size, &period_size); + assert(r == 0); + + /* Double internal buffer size to have enough space when waiting for the other side of duplex connection */ + stm->buffer_size *= 2; +- stm->buffer = calloc(1, snd_pcm_frames_to_bytes(stm->pcm, stm->buffer_size)); ++ stm->buffer = calloc(1, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->buffer_size)); + assert(stm->buffer); + +- stm->nfds = snd_pcm_poll_descriptors_count(stm->pcm); ++ stm->nfds = WRAP(snd_pcm_poll_descriptors_count)(stm->pcm); + assert(stm->nfds > 0); + + stm->saved_fds = calloc(stm->nfds, sizeof(struct pollfd)); + assert(stm->saved_fds); +- r = snd_pcm_poll_descriptors(stm->pcm, stm->saved_fds, stm->nfds); ++ r = WRAP(snd_pcm_poll_descriptors)(stm->pcm, stm->saved_fds, stm->nfds); + assert((nfds_t) r == stm->nfds); + + if (alsa_register_stream(ctx, stm) != 0) { +@@ -1054,7 +1127,7 @@ alsa_stream_destroy(cubeb_stream * stm) + pthread_mutex_lock(&stm->mutex); + if (stm->pcm) { + if (stm->state == DRAINING) { +- snd_pcm_drain(stm->pcm); ++ WRAP(snd_pcm_drain)(stm->pcm); + } + alsa_locked_pcm_close(stm->pcm); + stm->pcm = NULL; +@@ -1100,12 +1173,12 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) + + assert(stm); + +- r = snd_pcm_hw_params_any(stm->pcm, hw_params); ++ r = WRAP(snd_pcm_hw_params_any)(stm->pcm, hw_params); + if (r < 0) { + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_get_channels_max(hw_params, max_channels); ++ r = WRAP(snd_pcm_hw_params_get_channels_max)(hw_params, max_channels); + if (r < 0) { + return CUBEB_ERROR; + } +@@ -1126,34 +1199,34 @@ 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. */ +- r = snd_pcm_open(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE); ++ r = WRAP(snd_pcm_open)(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE); + if (r < 0) { + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_any(pcm, hw_params); ++ r = WRAP(snd_pcm_hw_params_any)(pcm, hw_params); + if (r < 0) { +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_get_rate(hw_params, rate, &dir); ++ r = WRAP(snd_pcm_hw_params_get_rate)(hw_params, rate, &dir); + if (r >= 0) { + /* There is a default rate: use it. */ +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_OK; + } + + /* Use a common rate, alsa may adjust it based on hw/etc. capabilities. */ + *rate = 44100; + +- r = snd_pcm_hw_params_set_rate_near(pcm, hw_params, rate, NULL); ++ r = WRAP(snd_pcm_hw_params_set_rate_near)(pcm, hw_params, rate, NULL); + if (r < 0) { +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_ERROR; + } + +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + + return CUBEB_OK; + } +@@ -1186,10 +1259,10 @@ alsa_stream_start(cubeb_stream * stm) + pthread_mutex_lock(&stm->mutex); + /* Capture pcm must be started after initial setup/recover */ + if (stm->stream_type == SND_PCM_STREAM_CAPTURE && +- snd_pcm_state(stm->pcm) == SND_PCM_STATE_PREPARED) { +- snd_pcm_start(stm->pcm); ++ WRAP(snd_pcm_state)(stm->pcm) == SND_PCM_STATE_PREPARED) { ++ WRAP(snd_pcm_start)(stm->pcm); + } +- snd_pcm_pause(stm->pcm, 0); ++ WRAP(snd_pcm_pause)(stm->pcm, 0); + gettimeofday(&stm->last_activity, NULL); + pthread_mutex_unlock(&stm->mutex); + +@@ -1229,7 +1302,7 @@ alsa_stream_stop(cubeb_stream * stm) + pthread_mutex_unlock(&ctx->mutex); + + pthread_mutex_lock(&stm->mutex); +- snd_pcm_pause(stm->pcm, 1); ++ WRAP(snd_pcm_pause)(stm->pcm, 1); + pthread_mutex_unlock(&stm->mutex); + + return CUBEB_OK; +@@ -1245,8 +1318,8 @@ alsa_stream_get_position(cubeb_stream * stm, uint64_t * position) + pthread_mutex_lock(&stm->mutex); + + delay = -1; +- if (snd_pcm_state(stm->pcm) != SND_PCM_STATE_RUNNING || +- snd_pcm_delay(stm->pcm, &delay) != 0) { ++ if (WRAP(snd_pcm_state)(stm->pcm) != SND_PCM_STATE_RUNNING || ++ WRAP(snd_pcm_delay)(stm->pcm, &delay) != 0) { + *position = stm->last_position; + pthread_mutex_unlock(&stm->mutex); + return CUBEB_OK; +@@ -1271,7 +1344,7 @@ alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency) + snd_pcm_sframes_t delay; + /* This function returns the delay in frames until a frame written using + snd_pcm_writei is sent to the DAC. The DAC delay should be < 1ms anyways. */ +- if (snd_pcm_delay(stm->pcm, &delay)) { ++ if (WRAP(snd_pcm_delay)(stm->pcm, &delay)) { + return CUBEB_ERROR; + } + +diff --git media/libcubeb/src/cubeb_sndio.c media/libcubeb/src/cubeb_sndio.c +index 9e99b2c..0559af4 100644 +--- media/libcubeb/src/cubeb_sndio.c ++++ media/libcubeb/src/cubeb_sndio.c +@@ -12,6 +12,7 @@ + #include <stdbool.h> + #include <stdlib.h> + #include <stdio.h> ++#include <dlfcn.h> + #include <assert.h> + #include "cubeb/cubeb.h" + #include "cubeb-internal.h" +@@ -22,10 +23,35 @@ + #define DPR(...) do {} while(0) + #endif + ++#ifdef DISABLE_LIBSNDIO_DLOPEN ++#define WRAP(x) x ++#else ++#define WRAP(x) cubeb_##x ++#define LIBSNDIO_API_VISIT(X) \ ++ X(sio_close) \ ++ X(sio_eof) \ ++ X(sio_getpar) \ ++ X(sio_initpar) \ ++ X(sio_onmove) \ ++ X(sio_open) \ ++ X(sio_pollfd) \ ++ X(sio_read) \ ++ X(sio_revents) \ ++ X(sio_setpar) \ ++ X(sio_start) \ ++ X(sio_stop) \ ++ X(sio_write) \ ++ ++#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x; ++LIBSNDIO_API_VISIT(MAKE_TYPEDEF); ++#undef MAKE_TYPEDEF ++#endif ++ + static struct cubeb_ops const sndio_ops; + + struct cubeb { + struct cubeb_ops const * ops; ++ void * libsndio; + }; + + struct cubeb_stream { +@@ -119,7 +145,7 @@ sndio_mainloop(void *arg) + DPR("sndio_mainloop()\n"); + s->state_cb(s, s->arg, CUBEB_STATE_STARTED); + pthread_mutex_lock(&s->mtx); +- if (!sio_start(s->hdl)) { ++ if (!WRAP(sio_start)(s->hdl)) { + pthread_mutex_unlock(&s->mtx); + return NULL; + } +@@ -203,7 +229,7 @@ sndio_mainloop(void *arg) + events |= POLLIN; + if ((s->mode & SIO_PLAY) && pstart < pend) + events |= POLLOUT; +- nfds = sio_pollfd(s->hdl, pfds, events); ++ nfds = WRAP(sio_pollfd)(s->hdl, pfds, events); + + if (nfds > 0) { + pthread_mutex_unlock(&s->mtx); +@@ -213,7 +239,7 @@ sndio_mainloop(void *arg) + continue; + } + +- revents = sio_revents(s->hdl, pfds); ++ revents = WRAP(sio_revents)(s->hdl, pfds); + + if (revents & POLLHUP) { + state = CUBEB_STATE_ERROR; +@@ -221,8 +247,8 @@ sndio_mainloop(void *arg) + } + + if (revents & POLLOUT) { +- n = sio_write(s->hdl, s->pbuf + pstart, pend - pstart); +- if (n == 0 && sio_eof(s->hdl)) { ++ n = WRAP(sio_write)(s->hdl, s->pbuf + pstart, pend - pstart); ++ if (n == 0 && WRAP(sio_eof)(s->hdl)) { + DPR("sndio_mainloop() werr\n"); + state = CUBEB_STATE_ERROR; + break; +@@ -231,8 +257,8 @@ sndio_mainloop(void *arg) + } + + if (revents & POLLIN) { +- n = sio_read(s->hdl, s->rbuf + rstart, rend - rstart); +- if (n == 0 && sio_eof(s->hdl)) { ++ n = WRAP(sio_read)(s->hdl, s->rbuf + rstart, rend - rstart); ++ if (n == 0 && WRAP(sio_eof)(s->hdl)) { + DPR("sndio_mainloop() rerr\n"); + state = CUBEB_STATE_ERROR; + break; +@@ -244,7 +270,7 @@ sndio_mainloop(void *arg) + if (prime > 0 && (s->mode & SIO_REC)) + rstart = rend; + } +- sio_stop(s->hdl); ++ WRAP(sio_stop)(s->hdl); + s->hwpos = s->swpos; + pthread_mutex_unlock(&s->mtx); + s->state_cb(s, s->arg, state); +@@ -254,8 +280,31 @@ sndio_mainloop(void *arg) + /*static*/ int + sndio_init(cubeb **context, char const *context_name) + { ++ void * libsndio = NULL; ++ ++#ifndef DISABLE_LIBSNDIO_DLOPEN ++ libsndio = dlopen("libsndio.so", RTLD_LAZY); ++ if (!libsndio) { ++ DPR("sndio_init(%s) failed dlopen(libsndio.so)\n", context_name); ++ return CUBEB_ERROR; ++ } ++ ++#define LOAD(x) { \ ++ cubeb_##x = dlsym(libsndio, #x); \ ++ if (!cubeb_##x) { \ ++ DPR("sndio_init(%s) failed dlsym(%s)\n", context_name, #x); \ ++ dlclose(libsndio); \ ++ return CUBEB_ERROR; \ ++ } \ ++ } ++ ++ LIBSNDIO_API_VISIT(LOAD); ++#undef LOAD ++#endif ++ + DPR("sndio_init(%s)\n", context_name); + *context = malloc(sizeof(*context)); ++ (*context)->libsndio = libsndio; + (*context)->ops = &sndio_ops; + (void)context_name; + return CUBEB_OK; +@@ -271,6 +320,8 @@ static void + sndio_destroy(cubeb *context) + { + DPR("sndio_destroy()\n"); ++ if (context->libsndio) ++ dlclose(context->libsndio); + free(context); + } + +@@ -323,12 +374,12 @@ sndio_stream_init(cubeb * context, + goto err; + } + s->context = context; +- s->hdl = sio_open(NULL, s->mode, 1); ++ s->hdl = WRAP(sio_open)(NULL, s->mode, 1); + if (s->hdl == NULL) { + DPR("sndio_stream_init(), sio_open() failed\n"); + goto err; + } +- sio_initpar(&wpar); ++ WRAP(sio_initpar)(&wpar); + wpar.sig = 1; + wpar.bits = 16; + switch (format) { +@@ -351,7 +402,7 @@ sndio_stream_init(cubeb * context, + if (s->mode & SIO_PLAY) + wpar.pchan = output_stream_params->channels; + wpar.appbufsz = latency_frames; +- if (!sio_setpar(s->hdl, &wpar) || !sio_getpar(s->hdl, &rpar)) { ++ if (!WRAP(sio_setpar)(s->hdl, &wpar) || !WRAP(sio_getpar)(s->hdl, &rpar)) { + DPR("sndio_stream_init(), sio_setpar() failed\n"); + goto err; + } +@@ -362,7 +413,7 @@ sndio_stream_init(cubeb * context, + DPR("sndio_stream_init() unsupported params\n"); + goto err; + } +- sio_onmove(s->hdl, sndio_onmove, s); ++ WRAP(sio_onmove)(s->hdl, sndio_onmove, s); + s->active = 0; + s->nfr = rpar.round; + s->rbpf = rpar.bps * rpar.rchan; +@@ -400,7 +451,7 @@ sndio_stream_init(cubeb * context, + return CUBEB_OK; + err: + if (s->hdl) +- sio_close(s->hdl); ++ WRAP(sio_close)(s->hdl); + if (s->pbuf) + free(s->pbuf); + if (s->rbuf) +@@ -446,7 +497,7 @@ static void + sndio_stream_destroy(cubeb_stream *s) + { + DPR("sndio_stream_destroy()\n"); +- sio_close(s->hdl); ++ WRAP(sio_close)(s->hdl); + if (s->mode & SIO_PLAY) + free(s->pbuf); + if (s->mode & SIO_REC) +diff --git toolkit/library/moz.build toolkit/library/moz.build +index 8ce595ff96bff..c318e96a1fdfc 100644 +--- toolkit/library/moz.build ++++ toolkit/library/moz.build +@@ -231,9 +231,6 @@ if CONFIG['MOZ_SYSTEM_LIBVPX']: + if not CONFIG['MOZ_TREE_PIXMAN']: + OS_LIBS += CONFIG['MOZ_PIXMAN_LIBS'] + +-if CONFIG['MOZ_ALSA']: +- OS_LIBS += CONFIG['MOZ_ALSA_LIBS'] +- + if CONFIG['HAVE_CLOCK_MONOTONIC']: + OS_LIBS += CONFIG['REALTIME_LIBS'] + +@@ -242,11 +239,6 @@ OS_LIBS += CONFIG['ICONV_LIBS'] + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'): + OS_LIBS += CONFIG['TK_LIBS'] + +-if CONFIG['OS_ARCH'] == 'OpenBSD': +- OS_LIBS += [ +- 'sndio', +- ] +- + if CONFIG['MOZ_ENABLE_DBUS']: + OS_LIBS += CONFIG['MOZ_DBUS_GLIB_LIBS'] + |