[26289] | 1 | /* $Id: DrvHostAudioAlsaStubs.cpp 89471 2021-06-02 20:53:43Z vboxsync $ */
|
---|
[6077] | 2 | /** @file
|
---|
| 3 | * Stubs for libasound.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[82968] | 7 | * Copyright (C) 2006-2020 Oracle Corporation
|
---|
[6077] | 8 | *
|
---|
| 9 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
| 10 | * available from http://www.virtualbox.org. This file is free software;
|
---|
| 11 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
| 12 | * General Public License (GPL) as published by the Free Software
|
---|
| 13 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
| 14 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
| 15 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
| 16 | */
|
---|
[88226] | 17 |
|
---|
[56648] | 18 | #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
|
---|
[5092] | 19 | #include <iprt/assert.h>
|
---|
[89427] | 20 | #include <iprt/err.h>
|
---|
[5092] | 21 | #include <iprt/ldr.h>
|
---|
| 22 | #include <VBox/log.h>
|
---|
[89425] | 23 | #include <iprt/once.h>
|
---|
[5092] | 24 |
|
---|
| 25 | #include <alsa/asoundlib.h>
|
---|
[88966] | 26 | #include <errno.h>
|
---|
[5092] | 27 |
|
---|
[88226] | 28 | #include "DrvHostAudioAlsaStubs.h"
|
---|
[5092] | 29 |
|
---|
| 30 | #define VBOX_ALSA_LIB "libasound.so.2"
|
---|
| 31 |
|
---|
[6077] | 32 | #define PROXY_STUB(function, rettype, signature, shortsig) \
|
---|
[26289] | 33 | static rettype (*pfn_ ## function) signature; \
|
---|
| 34 | \
|
---|
[88226] | 35 | extern "C" rettype VBox_##function signature; \
|
---|
[45136] | 36 | rettype VBox_##function signature \
|
---|
[26289] | 37 | { \
|
---|
| 38 | return pfn_ ## function shortsig; \
|
---|
| 39 | }
|
---|
[5092] | 40 |
|
---|
[73161] | 41 | PROXY_STUB(snd_lib_error_set_handler, int, (snd_lib_error_handler_t handler),
|
---|
| 42 | (handler))
|
---|
| 43 | PROXY_STUB(snd_strerror, const char *, (int errnum), (errnum))
|
---|
| 44 |
|
---|
[59987] | 45 | PROXY_STUB(snd_device_name_hint, int,
|
---|
| 46 | (int card, const char *iface, void ***hints),
|
---|
| 47 | (card, iface, hints))
|
---|
| 48 | PROXY_STUB(snd_device_name_free_hint, int,
|
---|
[64632] | 49 | (void **hints),
|
---|
[59987] | 50 | (hints))
|
---|
| 51 | PROXY_STUB(snd_device_name_get_hint, char *,
|
---|
| 52 | (const void *hint, const char *id),
|
---|
| 53 | (hint, id))
|
---|
| 54 |
|
---|
[88966] | 55 | static int fallback_snd_device_name_hint(int card, const char *iface, void ***hints)
|
---|
| 56 | {
|
---|
| 57 | RT_NOREF(card, iface);
|
---|
| 58 | *hints = NULL;
|
---|
| 59 | return -ENOSYS;
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | static int fallback_snd_device_name_free_hint(void **hints)
|
---|
| 63 | {
|
---|
| 64 | RT_NOREF(hints);
|
---|
| 65 | return 0;
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | static char *fallback_snd_device_name_get_hint(const void *hint, const char *id)
|
---|
| 69 | {
|
---|
| 70 | RT_NOREF(hint, id);
|
---|
| 71 | return NULL;
|
---|
| 72 | }
|
---|
| 73 |
|
---|
[73161] | 74 | /*
|
---|
| 75 | * PCM
|
---|
| 76 | */
|
---|
| 77 |
|
---|
[88966] | 78 | PROXY_STUB(snd_pcm_avail_update, snd_pcm_sframes_t, (snd_pcm_t *pcm), (pcm))
|
---|
[88432] | 79 | PROXY_STUB(snd_pcm_avail_delay, int,
|
---|
| 80 | (snd_pcm_t *pcm, snd_pcm_sframes_t *availp, snd_pcm_sframes_t *delayp),
|
---|
| 81 | (pcm, availp, delayp))
|
---|
[88966] | 82 | PROXY_STUB(snd_pcm_close, int, (snd_pcm_t *pcm), (pcm))
|
---|
| 83 | PROXY_STUB(snd_pcm_delay, int, (snd_pcm_t *pcm, snd_pcm_sframes_t *delayp), (pcm, delayp))
|
---|
[73160] | 84 | PROXY_STUB(snd_pcm_nonblock, int, (snd_pcm_t *pcm, int *onoff),
|
---|
| 85 | (pcm, onoff))
|
---|
| 86 | PROXY_STUB(snd_pcm_drain, int, (snd_pcm_t *pcm),
|
---|
| 87 | (pcm))
|
---|
[73161] | 88 | PROXY_STUB(snd_pcm_drop, int, (snd_pcm_t *pcm), (pcm))
|
---|
[5092] | 89 | PROXY_STUB(snd_pcm_open, int,
|
---|
| 90 | (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode),
|
---|
[6077] | 91 | (pcm, name, stream, mode))
|
---|
[73161] | 92 | PROXY_STUB(snd_pcm_prepare, int, (snd_pcm_t *pcm), (pcm))
|
---|
| 93 | PROXY_STUB(snd_pcm_readi, snd_pcm_sframes_t,
|
---|
| 94 | (snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size),
|
---|
| 95 | (pcm, buffer, size))
|
---|
| 96 | PROXY_STUB(snd_pcm_resume, int, (snd_pcm_t *pcm), (pcm))
|
---|
[89471] | 97 | PROXY_STUB(snd_pcm_set_chmap, int, (snd_pcm_t *pcm, snd_pcm_chmap_t const *map), (pcm, map))
|
---|
[73161] | 98 | PROXY_STUB(snd_pcm_state, snd_pcm_state_t, (snd_pcm_t *pcm), (pcm))
|
---|
[88220] | 99 | PROXY_STUB(snd_pcm_state_name, const char *, (snd_pcm_state_t state), (state))
|
---|
[5092] | 100 | PROXY_STUB(snd_pcm_writei, snd_pcm_sframes_t,
|
---|
| 101 | (snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size),
|
---|
[6077] | 102 | (pcm, buffer, size))
|
---|
[68376] | 103 | PROXY_STUB(snd_pcm_start, int, (snd_pcm_t *pcm), (pcm))
|
---|
[73161] | 104 |
|
---|
[88966] | 105 | static int fallback_snd_pcm_avail_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *availp, snd_pcm_sframes_t *delayp)
|
---|
| 106 | {
|
---|
| 107 | *availp = pfn_snd_pcm_avail_update(pcm);
|
---|
| 108 | int ret = pfn_snd_pcm_delay(pcm, delayp);
|
---|
| 109 | if (ret >= 0 && *availp < 0)
|
---|
| 110 | ret = (int)*availp;
|
---|
| 111 | return ret;
|
---|
| 112 | }
|
---|
| 113 |
|
---|
[89471] | 114 | static int fallback_snd_pcm_set_chmap(snd_pcm_t *pcm, snd_pcm_chmap_t const *map)
|
---|
| 115 | {
|
---|
| 116 | RT_NOREF(pcm, map);
|
---|
| 117 | return 0;
|
---|
| 118 | }
|
---|
| 119 |
|
---|
[73161] | 120 | /*
|
---|
| 121 | * HW
|
---|
| 122 | */
|
---|
| 123 |
|
---|
| 124 | PROXY_STUB(snd_pcm_hw_params, int,
|
---|
| 125 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params),
|
---|
| 126 | (pcm, params))
|
---|
| 127 | PROXY_STUB(snd_pcm_hw_params_any, int,
|
---|
| 128 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params),
|
---|
| 129 | (pcm, params))
|
---|
[5092] | 130 | PROXY_STUB(snd_pcm_hw_params_get_buffer_size, int,
|
---|
| 131 | (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val),
|
---|
[6077] | 132 | (params, val))
|
---|
[73161] | 133 | PROXY_STUB(snd_pcm_hw_params_get_buffer_size_min, int,
|
---|
| 134 | (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val),
|
---|
| 135 | (params, val))
|
---|
| 136 | PROXY_STUB(snd_pcm_hw_params_get_period_size, int,
|
---|
| 137 | (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir),
|
---|
| 138 | (params, frames, dir))
|
---|
| 139 | PROXY_STUB(snd_pcm_hw_params_get_period_size_min, int,
|
---|
| 140 | (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir),
|
---|
| 141 | (params, frames, dir))
|
---|
[5092] | 142 | PROXY_STUB(snd_pcm_hw_params_set_rate_near, int,
|
---|
| 143 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir),
|
---|
[6077] | 144 | (pcm, params, val, dir))
|
---|
[5092] | 145 | PROXY_STUB(snd_pcm_hw_params_set_access, int,
|
---|
| 146 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access),
|
---|
[6077] | 147 | (pcm, params, _access))
|
---|
[5092] | 148 | PROXY_STUB(snd_pcm_hw_params_set_buffer_time_near, int,
|
---|
| 149 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir),
|
---|
[6077] | 150 | (pcm, params, val, dir))
|
---|
[5092] | 151 | PROXY_STUB(snd_pcm_hw_params_set_buffer_size_near, int,
|
---|
| 152 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val),
|
---|
[6077] | 153 | (pcm, params, val))
|
---|
[73161] | 154 | PROXY_STUB(snd_pcm_hw_params_set_channels_near, int,
|
---|
| 155 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val),
|
---|
| 156 | (pcm, params, val))
|
---|
| 157 | PROXY_STUB(snd_pcm_hw_params_set_period_size_near, int,
|
---|
| 158 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir),
|
---|
| 159 | (pcm, params, val, dir))
|
---|
| 160 | PROXY_STUB(snd_pcm_hw_params_set_period_time_near, int,
|
---|
| 161 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir),
|
---|
| 162 | (pcm, params, val, dir))
|
---|
| 163 | PROXY_STUB(snd_pcm_hw_params_sizeof, size_t, (void), ())
|
---|
[5092] | 164 | PROXY_STUB(snd_pcm_hw_params_set_format, int,
|
---|
| 165 | (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val),
|
---|
[6077] | 166 | (pcm, params, val))
|
---|
[73161] | 167 |
|
---|
| 168 | /*
|
---|
| 169 | * SW
|
---|
| 170 | */
|
---|
| 171 |
|
---|
| 172 | PROXY_STUB(snd_pcm_sw_params, int,
|
---|
| 173 | (snd_pcm_t *pcm, snd_pcm_sw_params_t *params),
|
---|
| 174 | (pcm, params))
|
---|
[5092] | 175 | PROXY_STUB(snd_pcm_sw_params_current, int,
|
---|
| 176 | (snd_pcm_t *pcm, snd_pcm_sw_params_t *params),
|
---|
[6077] | 177 | (pcm, params))
|
---|
[73642] | 178 | PROXY_STUB(snd_pcm_sw_params_get_start_threshold, int,
|
---|
| 179 | (const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val),
|
---|
| 180 | (params, val))
|
---|
[73161] | 181 | PROXY_STUB(snd_pcm_sw_params_set_avail_min, int,
|
---|
[5092] | 182 | (snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val),
|
---|
[6077] | 183 | (pcm, params, val))
|
---|
[73161] | 184 | PROXY_STUB(snd_pcm_sw_params_set_start_threshold, int,
|
---|
[61523] | 185 | (snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val),
|
---|
| 186 | (pcm, params, val))
|
---|
[73161] | 187 | PROXY_STUB(snd_pcm_sw_params_sizeof, size_t, (void), ())
|
---|
[6077] | 188 |
|
---|
| 189 | typedef struct
|
---|
| 190 | {
|
---|
| 191 | const char *name;
|
---|
[88966] | 192 | void (**pfn)(void);
|
---|
| 193 | void (*pfnFallback)(void);
|
---|
[6077] | 194 | } SHARED_FUNC;
|
---|
| 195 |
|
---|
[88966] | 196 | #define ELEMENT(function) { #function , (void (**)(void)) & pfn_ ## function, NULL }
|
---|
| 197 | #define ELEMENT_FALLBACK(function) { #function , (void (**)(void)) & pfn_ ## function, (void (*)(void))fallback_ ## function }
|
---|
[6077] | 198 | static SHARED_FUNC SharedFuncs[] =
|
---|
| 199 | {
|
---|
[73161] | 200 | ELEMENT(snd_lib_error_set_handler),
|
---|
| 201 | ELEMENT(snd_strerror),
|
---|
| 202 |
|
---|
[88966] | 203 | ELEMENT_FALLBACK(snd_device_name_hint),
|
---|
| 204 | ELEMENT_FALLBACK(snd_device_name_get_hint),
|
---|
| 205 | ELEMENT_FALLBACK(snd_device_name_free_hint),
|
---|
[59987] | 206 |
|
---|
[73161] | 207 | ELEMENT(snd_pcm_avail_update),
|
---|
[88966] | 208 | ELEMENT_FALLBACK(snd_pcm_avail_delay),
|
---|
[6077] | 209 | ELEMENT(snd_pcm_close),
|
---|
[88966] | 210 | ELEMENT(snd_pcm_delay),
|
---|
[73160] | 211 | ELEMENT(snd_pcm_drain),
|
---|
[73161] | 212 | ELEMENT(snd_pcm_drop),
|
---|
[73160] | 213 | ELEMENT(snd_pcm_nonblock),
|
---|
[73161] | 214 | ELEMENT(snd_pcm_open),
|
---|
[6077] | 215 | ELEMENT(snd_pcm_prepare),
|
---|
[73161] | 216 | ELEMENT(snd_pcm_resume),
|
---|
[89471] | 217 | ELEMENT_FALLBACK(snd_pcm_set_chmap),
|
---|
[6077] | 218 | ELEMENT(snd_pcm_state),
|
---|
[88220] | 219 | ELEMENT(snd_pcm_state_name),
|
---|
[73161] | 220 |
|
---|
[6077] | 221 | ELEMENT(snd_pcm_readi),
|
---|
[68376] | 222 | ELEMENT(snd_pcm_start),
|
---|
[73161] | 223 | ELEMENT(snd_pcm_writei),
|
---|
| 224 |
|
---|
| 225 | ELEMENT(snd_pcm_hw_params),
|
---|
| 226 | ELEMENT(snd_pcm_hw_params_any),
|
---|
| 227 | ELEMENT(snd_pcm_hw_params_sizeof),
|
---|
[6077] | 228 | ELEMENT(snd_pcm_hw_params_get_buffer_size),
|
---|
[73161] | 229 | ELEMENT(snd_pcm_hw_params_get_buffer_size_min),
|
---|
| 230 | ELEMENT(snd_pcm_hw_params_get_period_size_min),
|
---|
[6077] | 231 | ELEMENT(snd_pcm_hw_params_set_access),
|
---|
[73161] | 232 | ELEMENT(snd_pcm_hw_params_set_buffer_size_near),
|
---|
[6077] | 233 | ELEMENT(snd_pcm_hw_params_set_buffer_time_near),
|
---|
[73161] | 234 | ELEMENT(snd_pcm_hw_params_set_channels_near),
|
---|
[6077] | 235 | ELEMENT(snd_pcm_hw_params_set_format),
|
---|
[73161] | 236 | ELEMENT(snd_pcm_hw_params_get_period_size),
|
---|
| 237 | ELEMENT(snd_pcm_hw_params_set_period_size_near),
|
---|
| 238 | ELEMENT(snd_pcm_hw_params_set_period_time_near),
|
---|
| 239 | ELEMENT(snd_pcm_hw_params_set_rate_near),
|
---|
| 240 |
|
---|
| 241 | ELEMENT(snd_pcm_sw_params),
|
---|
[6077] | 242 | ELEMENT(snd_pcm_sw_params_current),
|
---|
[73642] | 243 | ELEMENT(snd_pcm_sw_params_get_start_threshold),
|
---|
| 244 | ELEMENT(snd_pcm_sw_params_set_avail_min),
|
---|
[6077] | 245 | ELEMENT(snd_pcm_sw_params_set_start_threshold),
|
---|
[73161] | 246 | ELEMENT(snd_pcm_sw_params_sizeof),
|
---|
[6077] | 247 | };
|
---|
| 248 | #undef ELEMENT
|
---|
| 249 |
|
---|
[89425] | 250 | /** Init once. */
|
---|
| 251 | static RTONCE g_AlsaLibInitOnce = RTONCE_INITIALIZER;
|
---|
| 252 |
|
---|
| 253 |
|
---|
| 254 | /** @callback_method_impl{FNRTONCE} */
|
---|
| 255 | static DECLCALLBACK(int32_t) drvHostAudioAlsaLibInitOnce(void *pvUser)
|
---|
[6077] | 256 | {
|
---|
[89425] | 257 | RT_NOREF(pvUser);
|
---|
| 258 | LogFlowFunc(("\n"));
|
---|
[6077] | 259 |
|
---|
[89425] | 260 | RTLDRMOD hMod = NIL_RTLDRMOD;
|
---|
| 261 | int rc = RTLdrLoadSystemEx(VBOX_ALSA_LIB, RTLDRLOAD_FLAGS_NO_UNLOAD, &hMod);
|
---|
| 262 | if (RT_SUCCESS(rc))
|
---|
[6077] | 263 | {
|
---|
[89425] | 264 | for (uintptr_t i = 0; i < RT_ELEMENTS(SharedFuncs); i++)
|
---|
[88966] | 265 | {
|
---|
[89425] | 266 | rc = RTLdrGetSymbol(hMod, SharedFuncs[i].name, (void **)SharedFuncs[i].pfn);
|
---|
| 267 | if (RT_SUCCESS(rc))
|
---|
| 268 | { /* likely */ }
|
---|
| 269 | else if (SharedFuncs[i].pfnFallback && rc == VERR_SYMBOL_NOT_FOUND)
|
---|
| 270 | *SharedFuncs[i].pfn = SharedFuncs[i].pfnFallback;
|
---|
| 271 | else
|
---|
| 272 | {
|
---|
| 273 | LogRelFunc(("Failed to load library %s: Getting symbol %s failed: %Rrc\n", VBOX_ALSA_LIB, SharedFuncs[i].name, rc));
|
---|
| 274 | return rc;
|
---|
| 275 | }
|
---|
[88966] | 276 | }
|
---|
[6077] | 277 | }
|
---|
[89425] | 278 | else
|
---|
| 279 | LogRelFunc(("Failed to load library %s (%Rrc)\n", VBOX_ALSA_LIB, rc));
|
---|
[6077] | 280 | return rc;
|
---|
| 281 | }
|
---|
[69119] | 282 |
|
---|
[89425] | 283 |
|
---|
| 284 | /**
|
---|
| 285 | * Try to dynamically load the ALSA libraries.
|
---|
| 286 | *
|
---|
| 287 | * @returns VBox status code.
|
---|
| 288 | */
|
---|
| 289 | int audioLoadAlsaLib(void)
|
---|
| 290 | {
|
---|
| 291 | LogFlowFunc(("\n"));
|
---|
| 292 | return RTOnce(&g_AlsaLibInitOnce, drvHostAudioAlsaLibInitOnce, NULL);
|
---|
| 293 | }
|
---|
| 294 |
|
---|