VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DrvHostAudioAlsaStubs.cpp@ 104473

Last change on this file since 104473 was 103310, checked in by vboxsync, 10 months ago

Devices/DrvAudioAlsaStubs: Corrected snd_pcm_nonblock() proxy stub (found by Parfait). bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1/* $Id: DrvHostAudioAlsaStubs.cpp 103310 2024-02-12 12:13:26Z vboxsync $ */
2/** @file
3 * Stubs for libasound.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
29#include <iprt/assert.h>
30#include <iprt/err.h>
31#include <iprt/ldr.h>
32#include <VBox/log.h>
33#include <iprt/once.h>
34
35#include <alsa/asoundlib.h>
36#include <errno.h>
37
38#include "DrvHostAudioAlsaStubs.h"
39
40#define VBOX_ALSA_LIB "libasound.so.2"
41
42#define PROXY_STUB(function, rettype, signature, shortsig) \
43 static rettype (*pfn_ ## function) signature; \
44 \
45 extern "C" rettype VBox_##function signature; \
46 rettype VBox_##function signature \
47 { \
48 return pfn_ ## function shortsig; \
49 }
50
51PROXY_STUB(snd_lib_error_set_handler, int, (snd_lib_error_handler_t handler),
52 (handler))
53PROXY_STUB(snd_strerror, const char *, (int errnum), (errnum))
54
55PROXY_STUB(snd_device_name_hint, int,
56 (int card, const char *iface, void ***hints),
57 (card, iface, hints))
58PROXY_STUB(snd_device_name_free_hint, int,
59 (void **hints),
60 (hints))
61PROXY_STUB(snd_device_name_get_hint, char *,
62 (const void *hint, const char *id),
63 (hint, id))
64
65static int fallback_snd_device_name_hint(int card, const char *iface, void ***hints)
66{
67 RT_NOREF(card, iface);
68 *hints = NULL;
69 return -ENOSYS;
70}
71
72static int fallback_snd_device_name_free_hint(void **hints)
73{
74 RT_NOREF(hints);
75 return 0;
76}
77
78static char *fallback_snd_device_name_get_hint(const void *hint, const char *id)
79{
80 RT_NOREF(hint, id);
81 return NULL;
82}
83
84/*
85 * PCM
86 */
87
88PROXY_STUB(snd_pcm_avail_update, snd_pcm_sframes_t, (snd_pcm_t *pcm), (pcm))
89PROXY_STUB(snd_pcm_avail_delay, int,
90 (snd_pcm_t *pcm, snd_pcm_sframes_t *availp, snd_pcm_sframes_t *delayp),
91 (pcm, availp, delayp))
92PROXY_STUB(snd_pcm_close, int, (snd_pcm_t *pcm), (pcm))
93PROXY_STUB(snd_pcm_delay, int, (snd_pcm_t *pcm, snd_pcm_sframes_t *delayp), (pcm, delayp))
94PROXY_STUB(snd_pcm_nonblock, int, (snd_pcm_t *pcm, int onoff),
95 (pcm, onoff))
96PROXY_STUB(snd_pcm_drain, int, (snd_pcm_t *pcm),
97 (pcm))
98PROXY_STUB(snd_pcm_drop, int, (snd_pcm_t *pcm), (pcm))
99PROXY_STUB(snd_pcm_open, int,
100 (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode),
101 (pcm, name, stream, mode))
102PROXY_STUB(snd_pcm_prepare, int, (snd_pcm_t *pcm), (pcm))
103PROXY_STUB(snd_pcm_readi, snd_pcm_sframes_t,
104 (snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size),
105 (pcm, buffer, size))
106PROXY_STUB(snd_pcm_resume, int, (snd_pcm_t *pcm), (pcm))
107PROXY_STUB(snd_pcm_set_chmap, int, (snd_pcm_t *pcm, snd_pcm_chmap_t const *map), (pcm, map))
108PROXY_STUB(snd_pcm_state, snd_pcm_state_t, (snd_pcm_t *pcm), (pcm))
109PROXY_STUB(snd_pcm_state_name, const char *, (snd_pcm_state_t state), (state))
110PROXY_STUB(snd_pcm_writei, snd_pcm_sframes_t,
111 (snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size),
112 (pcm, buffer, size))
113PROXY_STUB(snd_pcm_start, int, (snd_pcm_t *pcm), (pcm))
114
115static int fallback_snd_pcm_avail_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *availp, snd_pcm_sframes_t *delayp)
116{
117 *availp = pfn_snd_pcm_avail_update(pcm);
118 int ret = pfn_snd_pcm_delay(pcm, delayp);
119 if (ret >= 0 && *availp < 0)
120 ret = (int)*availp;
121 return ret;
122}
123
124static int fallback_snd_pcm_set_chmap(snd_pcm_t *pcm, snd_pcm_chmap_t const *map)
125{
126 RT_NOREF(pcm, map);
127 return 0;
128}
129
130/*
131 * HW
132 */
133
134PROXY_STUB(snd_pcm_hw_params, int,
135 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params),
136 (pcm, params))
137PROXY_STUB(snd_pcm_hw_params_any, int,
138 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params),
139 (pcm, params))
140PROXY_STUB(snd_pcm_hw_params_get_buffer_size, int,
141 (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val),
142 (params, val))
143PROXY_STUB(snd_pcm_hw_params_get_buffer_size_min, int,
144 (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val),
145 (params, val))
146PROXY_STUB(snd_pcm_hw_params_get_period_size, int,
147 (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir),
148 (params, frames, dir))
149PROXY_STUB(snd_pcm_hw_params_get_period_size_min, int,
150 (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir),
151 (params, frames, dir))
152PROXY_STUB(snd_pcm_hw_params_set_rate_near, int,
153 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir),
154 (pcm, params, val, dir))
155PROXY_STUB(snd_pcm_hw_params_set_access, int,
156 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access),
157 (pcm, params, _access))
158PROXY_STUB(snd_pcm_hw_params_set_buffer_time_near, int,
159 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir),
160 (pcm, params, val, dir))
161PROXY_STUB(snd_pcm_hw_params_set_buffer_size_near, int,
162 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val),
163 (pcm, params, val))
164PROXY_STUB(snd_pcm_hw_params_set_channels_near, int,
165 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val),
166 (pcm, params, val))
167PROXY_STUB(snd_pcm_hw_params_set_period_size_near, int,
168 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir),
169 (pcm, params, val, dir))
170PROXY_STUB(snd_pcm_hw_params_set_period_time_near, int,
171 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir),
172 (pcm, params, val, dir))
173PROXY_STUB(snd_pcm_hw_params_sizeof, size_t, (void), ())
174PROXY_STUB(snd_pcm_hw_params_set_format, int,
175 (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val),
176 (pcm, params, val))
177
178/*
179 * SW
180 */
181
182PROXY_STUB(snd_pcm_sw_params, int,
183 (snd_pcm_t *pcm, snd_pcm_sw_params_t *params),
184 (pcm, params))
185PROXY_STUB(snd_pcm_sw_params_current, int,
186 (snd_pcm_t *pcm, snd_pcm_sw_params_t *params),
187 (pcm, params))
188PROXY_STUB(snd_pcm_sw_params_get_start_threshold, int,
189 (const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val),
190 (params, val))
191PROXY_STUB(snd_pcm_sw_params_set_avail_min, int,
192 (snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val),
193 (pcm, params, val))
194PROXY_STUB(snd_pcm_sw_params_set_start_threshold, int,
195 (snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val),
196 (pcm, params, val))
197PROXY_STUB(snd_pcm_sw_params_sizeof, size_t, (void), ())
198
199/*
200 * Mixer
201 */
202
203PROXY_STUB(snd_mixer_selem_id_sizeof, size_t,
204 (void), ())
205PROXY_STUB(snd_mixer_open, int,
206 (snd_mixer_t **mixer, int mode),
207 (mixer, mode))
208PROXY_STUB(snd_mixer_attach, int,
209 (snd_mixer_t *mixer, const char *name),
210 (mixer, name))
211PROXY_STUB(snd_mixer_close, int,
212 (snd_mixer_t *mixer),
213 (mixer))
214PROXY_STUB(snd_mixer_selem_id_set_index, void,
215 (snd_mixer_selem_id_t *obj, unsigned int val),
216 (obj, val))
217PROXY_STUB(snd_mixer_selem_id_set_name, void,
218 (snd_mixer_selem_id_t *obj, const char *val),
219 (obj, val))
220PROXY_STUB(snd_mixer_selem_set_playback_volume, int,
221 (snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value),
222 (elem, channel, value))
223PROXY_STUB(snd_mixer_selem_get_playback_volume_range, int,
224 (snd_mixer_elem_t *elem, long *min, long *max),
225 (elem, min, max))
226PROXY_STUB(snd_mixer_selem_set_capture_volume, int,
227 (snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value),
228 (elem, channel, value))
229PROXY_STUB(snd_mixer_selem_get_capture_volume_range, int,
230 (snd_mixer_elem_t *elem, long *min, long *max),
231 (elem, min, max))
232PROXY_STUB(snd_mixer_selem_register, int,
233 (snd_mixer_t *mixer, snd_mixer_selem_regopt *options, snd_mixer_class_t **classp),
234 (mixer, options, classp))
235PROXY_STUB(snd_mixer_load, int,
236 (snd_mixer_t *mixer),
237 (mixer))
238PROXY_STUB(snd_mixer_find_selem, snd_mixer_elem_t *,
239 (snd_mixer_t *mixer, const snd_mixer_selem_id_t *id),
240 (mixer, id))
241
242typedef struct
243{
244 const char *name;
245 void (**pfn)(void);
246 void (*pfnFallback)(void);
247} SHARED_FUNC;
248
249#define ELEMENT(function) { #function , (void (**)(void)) & pfn_ ## function, NULL }
250#define ELEMENT_FALLBACK(function) { #function , (void (**)(void)) & pfn_ ## function, (void (*)(void))fallback_ ## function }
251static SHARED_FUNC SharedFuncs[] =
252{
253 ELEMENT(snd_lib_error_set_handler),
254 ELEMENT(snd_strerror),
255
256 ELEMENT_FALLBACK(snd_device_name_hint),
257 ELEMENT_FALLBACK(snd_device_name_get_hint),
258 ELEMENT_FALLBACK(snd_device_name_free_hint),
259
260 ELEMENT(snd_pcm_avail_update),
261 ELEMENT_FALLBACK(snd_pcm_avail_delay),
262 ELEMENT(snd_pcm_close),
263 ELEMENT(snd_pcm_delay),
264 ELEMENT(snd_pcm_drain),
265 ELEMENT(snd_pcm_drop),
266 ELEMENT(snd_pcm_nonblock),
267 ELEMENT(snd_pcm_open),
268 ELEMENT(snd_pcm_prepare),
269 ELEMENT(snd_pcm_resume),
270 ELEMENT_FALLBACK(snd_pcm_set_chmap),
271 ELEMENT(snd_pcm_state),
272 ELEMENT(snd_pcm_state_name),
273
274 ELEMENT(snd_pcm_readi),
275 ELEMENT(snd_pcm_start),
276 ELEMENT(snd_pcm_writei),
277
278 ELEMENT(snd_pcm_hw_params),
279 ELEMENT(snd_pcm_hw_params_any),
280 ELEMENT(snd_pcm_hw_params_sizeof),
281 ELEMENT(snd_pcm_hw_params_get_buffer_size),
282 ELEMENT(snd_pcm_hw_params_get_buffer_size_min),
283 ELEMENT(snd_pcm_hw_params_get_period_size_min),
284 ELEMENT(snd_pcm_hw_params_set_access),
285 ELEMENT(snd_pcm_hw_params_set_buffer_size_near),
286 ELEMENT(snd_pcm_hw_params_set_buffer_time_near),
287 ELEMENT(snd_pcm_hw_params_set_channels_near),
288 ELEMENT(snd_pcm_hw_params_set_format),
289 ELEMENT(snd_pcm_hw_params_get_period_size),
290 ELEMENT(snd_pcm_hw_params_set_period_size_near),
291 ELEMENT(snd_pcm_hw_params_set_period_time_near),
292 ELEMENT(snd_pcm_hw_params_set_rate_near),
293
294 ELEMENT(snd_pcm_sw_params),
295 ELEMENT(snd_pcm_sw_params_current),
296 ELEMENT(snd_pcm_sw_params_get_start_threshold),
297 ELEMENT(snd_pcm_sw_params_set_avail_min),
298 ELEMENT(snd_pcm_sw_params_set_start_threshold),
299 ELEMENT(snd_pcm_sw_params_sizeof),
300
301 ELEMENT(snd_mixer_selem_id_sizeof),
302 ELEMENT(snd_mixer_open),
303 ELEMENT(snd_mixer_attach),
304 ELEMENT(snd_mixer_close),
305 ELEMENT(snd_mixer_selem_id_set_index),
306 ELEMENT(snd_mixer_selem_id_set_name),
307 ELEMENT(snd_mixer_selem_set_playback_volume),
308 ELEMENT(snd_mixer_selem_get_playback_volume_range),
309 ELEMENT(snd_mixer_selem_set_capture_volume),
310 ELEMENT(snd_mixer_selem_get_capture_volume_range),
311 ELEMENT(snd_mixer_selem_register),
312 ELEMENT(snd_mixer_load),
313 ELEMENT(snd_mixer_find_selem),
314
315};
316#undef ELEMENT
317
318/** Init once. */
319static RTONCE g_AlsaLibInitOnce = RTONCE_INITIALIZER;
320
321
322/** @callback_method_impl{FNRTONCE} */
323static DECLCALLBACK(int32_t) drvHostAudioAlsaLibInitOnce(void *pvUser)
324{
325 RT_NOREF(pvUser);
326 LogFlowFunc(("\n"));
327
328 RTLDRMOD hMod = NIL_RTLDRMOD;
329 int rc = RTLdrLoadSystemEx(VBOX_ALSA_LIB, RTLDRLOAD_FLAGS_NO_UNLOAD, &hMod);
330 if (RT_SUCCESS(rc))
331 {
332 for (uintptr_t i = 0; i < RT_ELEMENTS(SharedFuncs); i++)
333 {
334 rc = RTLdrGetSymbol(hMod, SharedFuncs[i].name, (void **)SharedFuncs[i].pfn);
335 if (RT_SUCCESS(rc))
336 { /* likely */ }
337 else if (SharedFuncs[i].pfnFallback && rc == VERR_SYMBOL_NOT_FOUND)
338 *SharedFuncs[i].pfn = SharedFuncs[i].pfnFallback;
339 else
340 {
341 LogRelFunc(("Failed to load library %s: Getting symbol %s failed: %Rrc\n", VBOX_ALSA_LIB, SharedFuncs[i].name, rc));
342 return rc;
343 }
344 }
345
346 RTLdrClose(hMod);
347 }
348 else
349 LogRelFunc(("Failed to load library %s (%Rrc)\n", VBOX_ALSA_LIB, rc));
350 return rc;
351}
352
353
354/**
355 * Try to dynamically load the ALSA libraries.
356 *
357 * @returns VBox status code.
358 */
359int audioLoadAlsaLib(void)
360{
361 LogFlowFunc(("\n"));
362 return RTOnce(&g_AlsaLibInitOnce, drvHostAudioAlsaLibInitOnce, NULL);
363}
364
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette