VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DrvHostAudioPulseAudioStubs.cpp

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.2 KB
Line 
1/* $Id: DrvHostAudioPulseAudioStubs.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Stubs for libpulse.
4 */
5
6/*
7 * Copyright (C) 2006-2024 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
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
33#include <iprt/assert.h>
34#include <iprt/errcore.h>
35#include <iprt/ldr.h>
36#include <VBox/log.h>
37#include <iprt/once.h>
38
39#include <pulse/pulseaudio.h>
40
41#include "DrvHostAudioPulseAudioStubs.h"
42
43
44/*********************************************************************************************************************************
45* Defined Constants And Macros *
46*********************************************************************************************************************************/
47#define VBOX_PULSE_LIB "libpulse.so.0"
48
49#define PROXY_STUB(function, rettype, signature, shortsig) \
50 static rettype (*g_pfn_ ## function) signature; \
51 \
52 extern "C" rettype VBox_##function signature; \
53 rettype VBox_##function signature \
54 { \
55 return g_pfn_ ## function shortsig; \
56 }
57
58#define PROXY_STUB_VOID(function, signature, shortsig) \
59 static void (*g_pfn_ ## function) signature; \
60 \
61 extern "C" void VBox_##function signature; \
62 void VBox_##function signature \
63 { \
64 g_pfn_ ## function shortsig; \
65 }
66
67PROXY_STUB (pa_bytes_per_second, size_t,
68 (const pa_sample_spec *spec),
69 (spec))
70PROXY_STUB (pa_bytes_to_usec, pa_usec_t,
71 (uint64_t l, const pa_sample_spec *spec),
72 (l, spec))
73PROXY_STUB (pa_channel_map_init_auto, pa_channel_map*,
74 (pa_channel_map *m, unsigned channels, pa_channel_map_def_t def),
75 (m, channels, def))
76
77PROXY_STUB (pa_context_connect, int,
78 (pa_context *c, const char *server, pa_context_flags_t flags,
79 const pa_spawn_api *api),
80 (c, server, flags, api))
81PROXY_STUB_VOID(pa_context_disconnect,
82 (pa_context *c),
83 (c))
84PROXY_STUB (pa_context_get_server_info, pa_operation*,
85 (pa_context *c, pa_server_info_cb_t cb, void *userdata),
86 (c, cb, userdata))
87PROXY_STUB (pa_context_get_sink_info_by_name, pa_operation*,
88 (pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata),
89 (c, name, cb, userdata))
90PROXY_STUB (pa_context_get_sink_info_list, pa_operation *,
91 (pa_context *c, pa_sink_info_cb_t cb, void *userdata),
92 (c, cb, userdata))
93PROXY_STUB (pa_context_get_source_info_by_name, pa_operation*,
94 (pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata),
95 (c, name, cb, userdata))
96PROXY_STUB (pa_context_get_source_info_list, pa_operation *,
97 (pa_context *c, pa_source_info_cb_t cb, void *userdata),
98 (c, cb, userdata))
99PROXY_STUB (pa_context_get_state, pa_context_state_t,
100 (pa_context *c),
101 (c))
102PROXY_STUB_VOID(pa_context_unref,
103 (pa_context *c),
104 (c))
105PROXY_STUB (pa_context_errno, int,
106 (pa_context *c),
107 (c))
108PROXY_STUB (pa_context_new, pa_context*,
109 (pa_mainloop_api *mainloop, const char *name),
110 (mainloop, name))
111PROXY_STUB_VOID(pa_context_set_state_callback,
112 (pa_context *c, pa_context_notify_cb_t cb, void *userdata),
113 (c, cb, userdata))
114
115PROXY_STUB (pa_frame_size, size_t,
116 (const pa_sample_spec *spec),
117 (spec))
118PROXY_STUB (pa_get_library_version, const char *, (void), ())
119PROXY_STUB_VOID(pa_operation_unref,
120 (pa_operation *o),
121 (o))
122PROXY_STUB (pa_operation_get_state, pa_operation_state_t,
123 (pa_operation *o),
124 (o))
125PROXY_STUB_VOID(pa_operation_cancel,
126 (pa_operation *o),
127 (o))
128
129PROXY_STUB (pa_rtclock_now, pa_usec_t,
130 (void),
131 ())
132PROXY_STUB (pa_sample_format_to_string, const char*,
133 (pa_sample_format_t f),
134 (f))
135PROXY_STUB (pa_sample_spec_valid, int,
136 (const pa_sample_spec *spec),
137 (spec))
138PROXY_STUB (pa_strerror, const char*,
139 (int error),
140 (error))
141
142#if PA_PROTOCOL_VERSION >= 16
143PROXY_STUB (pa_stream_connect_playback, int,
144 (pa_stream *s, const char *dev, const pa_buffer_attr *attr,
145 pa_stream_flags_t flags, const pa_cvolume *volume, pa_stream *sync_stream),
146 (s, dev, attr, flags, volume, sync_stream))
147#else
148PROXY_STUB (pa_stream_connect_playback, int,
149 (pa_stream *s, const char *dev, const pa_buffer_attr *attr,
150 pa_stream_flags_t flags, pa_cvolume *volume, pa_stream *sync_stream),
151 (s, dev, attr, flags, volume, sync_stream))
152#endif
153PROXY_STUB (pa_stream_connect_record, int,
154 (pa_stream *s, const char *dev, const pa_buffer_attr *attr,
155 pa_stream_flags_t flags),
156 (s, dev, attr, flags))
157PROXY_STUB (pa_stream_disconnect, int,
158 (pa_stream *s),
159 (s))
160PROXY_STUB (pa_stream_get_sample_spec, const pa_sample_spec*,
161 (pa_stream *s),
162 (s))
163PROXY_STUB_VOID(pa_stream_set_latency_update_callback,
164 (pa_stream *p, pa_stream_notify_cb_t cb, void *userdata),
165 (p, cb, userdata))
166PROXY_STUB (pa_stream_write, int,
167 (pa_stream *p, const void *data, size_t bytes, pa_free_cb_t free_cb,
168 int64_t offset, pa_seek_mode_t seek),
169 (p, data, bytes, free_cb, offset, seek))
170PROXY_STUB_VOID(pa_stream_unref,
171 (pa_stream *s),
172 (s))
173PROXY_STUB (pa_stream_get_state, pa_stream_state_t,
174 (pa_stream *p),
175 (p))
176PROXY_STUB (pa_stream_get_latency, int,
177 (pa_stream *s, pa_usec_t *r_usec, int *negative),
178 (s, r_usec, negative))
179PROXY_STUB (pa_stream_get_timing_info, pa_timing_info*,
180 (pa_stream *s),
181 (s))
182PROXY_STUB (pa_stream_readable_size, size_t,
183 (pa_stream *p),
184 (p))
185PROXY_STUB (pa_stream_set_buffer_attr, pa_operation *,
186 (pa_stream *s, const pa_buffer_attr *attr, pa_stream_success_cb_t cb, void *userdata),
187 (s, attr, cb, userdata))
188PROXY_STUB_VOID(pa_stream_set_state_callback,
189 (pa_stream *s, pa_stream_notify_cb_t cb, void *userdata),
190 (s, cb, userdata))
191PROXY_STUB_VOID(pa_stream_set_underflow_callback,
192 (pa_stream *s, pa_stream_notify_cb_t cb, void *userdata),
193 (s, cb, userdata))
194PROXY_STUB_VOID(pa_stream_set_overflow_callback,
195 (pa_stream *s, pa_stream_notify_cb_t cb, void *userdata),
196 (s, cb, userdata))
197PROXY_STUB_VOID(pa_stream_set_write_callback,
198 (pa_stream *s, pa_stream_request_cb_t cb, void *userdata),
199 (s, cb, userdata))
200PROXY_STUB (pa_stream_flush, pa_operation*,
201 (pa_stream *s, pa_stream_success_cb_t cb, void *userdata),
202 (s, cb, userdata))
203PROXY_STUB (pa_stream_drain, pa_operation*,
204 (pa_stream *s, pa_stream_success_cb_t cb, void *userdata),
205 (s, cb, userdata))
206PROXY_STUB (pa_stream_trigger, pa_operation*,
207 (pa_stream *s, pa_stream_success_cb_t cb, void *userdata),
208 (s, cb, userdata))
209PROXY_STUB (pa_stream_new, pa_stream*,
210 (pa_context *c, const char *name, const pa_sample_spec *ss,
211 const pa_channel_map *map),
212 (c, name, ss, map))
213PROXY_STUB (pa_stream_get_buffer_attr, const pa_buffer_attr*,
214 (pa_stream *s),
215 (s))
216PROXY_STUB (pa_stream_peek, int,
217 (pa_stream *p, const void **data, size_t *bytes),
218 (p, data, bytes))
219PROXY_STUB (pa_stream_cork, pa_operation*,
220 (pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata),
221 (s, b, cb, userdata))
222PROXY_STUB (pa_stream_drop, int,
223 (pa_stream *p),
224 (p))
225PROXY_STUB (pa_stream_writable_size, size_t,
226 (pa_stream *p),
227 (p))
228
229PROXY_STUB_VOID(pa_threaded_mainloop_stop,
230 (pa_threaded_mainloop *m),
231 (m))
232PROXY_STUB (pa_threaded_mainloop_get_api, pa_mainloop_api*,
233 (pa_threaded_mainloop *m),
234 (m))
235PROXY_STUB_VOID(pa_threaded_mainloop_free,
236 (pa_threaded_mainloop* m),
237 (m))
238PROXY_STUB_VOID(pa_threaded_mainloop_signal,
239 (pa_threaded_mainloop *m, int wait_for_accept),
240 (m, wait_for_accept))
241PROXY_STUB_VOID(pa_threaded_mainloop_unlock,
242 (pa_threaded_mainloop *m),
243 (m))
244PROXY_STUB (pa_threaded_mainloop_new, pa_threaded_mainloop *,
245 (void),
246 ())
247PROXY_STUB_VOID(pa_threaded_mainloop_wait,
248 (pa_threaded_mainloop *m),
249 (m))
250PROXY_STUB (pa_threaded_mainloop_start, int,
251 (pa_threaded_mainloop *m),
252 (m))
253PROXY_STUB_VOID(pa_threaded_mainloop_lock,
254 (pa_threaded_mainloop *m),
255 (m))
256
257PROXY_STUB (pa_usec_to_bytes, size_t,
258 (pa_usec_t t, const pa_sample_spec *spec),
259 (t, spec))
260
261#define FUNC_ENTRY(function) { #function , (void (**)(void)) & g_pfn_ ## function }
262static struct
263{
264 const char *pszName;
265 void (**pfn)(void);
266} const g_aImportedFunctions[] =
267{
268 FUNC_ENTRY(pa_bytes_per_second),
269 FUNC_ENTRY(pa_bytes_to_usec),
270 FUNC_ENTRY(pa_channel_map_init_auto),
271
272 FUNC_ENTRY(pa_context_connect),
273 FUNC_ENTRY(pa_context_disconnect),
274 FUNC_ENTRY(pa_context_get_server_info),
275 FUNC_ENTRY(pa_context_get_sink_info_by_name),
276 FUNC_ENTRY(pa_context_get_sink_info_list),
277 FUNC_ENTRY(pa_context_get_source_info_by_name),
278 FUNC_ENTRY(pa_context_get_source_info_list),
279 FUNC_ENTRY(pa_context_get_state),
280 FUNC_ENTRY(pa_context_unref),
281 FUNC_ENTRY(pa_context_errno),
282 FUNC_ENTRY(pa_context_new),
283 FUNC_ENTRY(pa_context_set_state_callback),
284
285 FUNC_ENTRY(pa_frame_size),
286 FUNC_ENTRY(pa_get_library_version),
287 FUNC_ENTRY(pa_operation_unref),
288 FUNC_ENTRY(pa_operation_get_state),
289 FUNC_ENTRY(pa_operation_cancel),
290 FUNC_ENTRY(pa_rtclock_now),
291 FUNC_ENTRY(pa_sample_format_to_string),
292 FUNC_ENTRY(pa_sample_spec_valid),
293 FUNC_ENTRY(pa_strerror),
294
295 FUNC_ENTRY(pa_stream_connect_playback),
296 FUNC_ENTRY(pa_stream_connect_record),
297 FUNC_ENTRY(pa_stream_disconnect),
298 FUNC_ENTRY(pa_stream_get_sample_spec),
299 FUNC_ENTRY(pa_stream_set_latency_update_callback),
300 FUNC_ENTRY(pa_stream_write),
301 FUNC_ENTRY(pa_stream_unref),
302 FUNC_ENTRY(pa_stream_get_state),
303 FUNC_ENTRY(pa_stream_get_latency),
304 FUNC_ENTRY(pa_stream_get_timing_info),
305 FUNC_ENTRY(pa_stream_readable_size),
306 FUNC_ENTRY(pa_stream_set_buffer_attr),
307 FUNC_ENTRY(pa_stream_set_state_callback),
308 FUNC_ENTRY(pa_stream_set_underflow_callback),
309 FUNC_ENTRY(pa_stream_set_overflow_callback),
310 FUNC_ENTRY(pa_stream_set_write_callback),
311 FUNC_ENTRY(pa_stream_flush),
312 FUNC_ENTRY(pa_stream_drain),
313 FUNC_ENTRY(pa_stream_trigger),
314 FUNC_ENTRY(pa_stream_new),
315 FUNC_ENTRY(pa_stream_get_buffer_attr),
316 FUNC_ENTRY(pa_stream_peek),
317 FUNC_ENTRY(pa_stream_cork),
318 FUNC_ENTRY(pa_stream_drop),
319 FUNC_ENTRY(pa_stream_writable_size),
320
321 FUNC_ENTRY(pa_threaded_mainloop_stop),
322 FUNC_ENTRY(pa_threaded_mainloop_get_api),
323 FUNC_ENTRY(pa_threaded_mainloop_free),
324 FUNC_ENTRY(pa_threaded_mainloop_signal),
325 FUNC_ENTRY(pa_threaded_mainloop_unlock),
326 FUNC_ENTRY(pa_threaded_mainloop_new),
327 FUNC_ENTRY(pa_threaded_mainloop_wait),
328 FUNC_ENTRY(pa_threaded_mainloop_start),
329 FUNC_ENTRY(pa_threaded_mainloop_lock),
330
331 FUNC_ENTRY(pa_usec_to_bytes)
332};
333#undef FUNC_ENTRY
334
335/** Init once. */
336static RTONCE g_PulseAudioLibInitOnce = RTONCE_INITIALIZER;
337
338/** @callback_method_impl{FNRTONCE} */
339static DECLCALLBACK(int32_t) drvHostAudioPulseLibInitOnce(void *pvUser)
340{
341 RT_NOREF(pvUser);
342 LogFlowFunc(("\n"));
343
344 RTLDRMOD hMod = NIL_RTLDRMOD;
345 int rc = RTLdrLoadSystemEx(VBOX_PULSE_LIB, RTLDRLOAD_FLAGS_NO_UNLOAD, &hMod);
346 if (RT_SUCCESS(rc))
347 {
348 for (unsigned i = 0; i < RT_ELEMENTS(g_aImportedFunctions); i++)
349 {
350 rc = RTLdrGetSymbol(hMod, g_aImportedFunctions[i].pszName, (void **)g_aImportedFunctions[i].pfn);
351 if (RT_FAILURE(rc))
352 {
353 LogRelFunc(("Failed to resolve function #%u: '%s' (%Rrc)\n", i, g_aImportedFunctions[i].pszName, rc));
354 break;
355 }
356 }
357
358 RTLdrClose(hMod);
359 }
360 else
361 LogRelFunc(("Failed to load library %s: %Rrc\n", VBOX_PULSE_LIB, rc));
362 return rc;
363}
364
365/**
366 * Try to dynamically load the PulseAudio libraries.
367 *
368 * @returns VBox status code.
369 */
370int audioLoadPulseLib(void)
371{
372 LogFlowFunc(("\n"));
373 return RTOnce(&g_PulseAudioLibInitOnce, drvHostAudioPulseLibInitOnce, NULL);
374}
375
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