diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Devices/Audio/DrvHostAudioPulseAudioStubs.cpp | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/Audio/DrvHostAudioPulseAudioStubs.cpp')
-rw-r--r-- | src/VBox/Devices/Audio/DrvHostAudioPulseAudioStubs.cpp | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/src/VBox/Devices/Audio/DrvHostAudioPulseAudioStubs.cpp b/src/VBox/Devices/Audio/DrvHostAudioPulseAudioStubs.cpp new file mode 100644 index 00000000..15f2e34e --- /dev/null +++ b/src/VBox/Devices/Audio/DrvHostAudioPulseAudioStubs.cpp @@ -0,0 +1,375 @@ +/* $Id: DrvHostAudioPulseAudioStubs.cpp $ */ +/** @file + * Stubs for libpulse. + */ + +/* + * Copyright (C) 2006-2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO +#include <iprt/assert.h> +#include <iprt/errcore.h> +#include <iprt/ldr.h> +#include <VBox/log.h> +#include <iprt/once.h> + +#include <pulse/pulseaudio.h> + +#include "DrvHostAudioPulseAudioStubs.h" + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#define VBOX_PULSE_LIB "libpulse.so.0" + +#define PROXY_STUB(function, rettype, signature, shortsig) \ + static rettype (*g_pfn_ ## function) signature; \ + \ + extern "C" rettype VBox_##function signature; \ + rettype VBox_##function signature \ + { \ + return g_pfn_ ## function shortsig; \ + } + +#define PROXY_STUB_VOID(function, signature, shortsig) \ + static void (*g_pfn_ ## function) signature; \ + \ + extern "C" void VBox_##function signature; \ + void VBox_##function signature \ + { \ + g_pfn_ ## function shortsig; \ + } + +PROXY_STUB (pa_bytes_per_second, size_t, + (const pa_sample_spec *spec), + (spec)) +PROXY_STUB (pa_bytes_to_usec, pa_usec_t, + (uint64_t l, const pa_sample_spec *spec), + (l, spec)) +PROXY_STUB (pa_channel_map_init_auto, pa_channel_map*, + (pa_channel_map *m, unsigned channels, pa_channel_map_def_t def), + (m, channels, def)) + +PROXY_STUB (pa_context_connect, int, + (pa_context *c, const char *server, pa_context_flags_t flags, + const pa_spawn_api *api), + (c, server, flags, api)) +PROXY_STUB_VOID(pa_context_disconnect, + (pa_context *c), + (c)) +PROXY_STUB (pa_context_get_server_info, pa_operation*, + (pa_context *c, pa_server_info_cb_t cb, void *userdata), + (c, cb, userdata)) +PROXY_STUB (pa_context_get_sink_info_by_name, pa_operation*, + (pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata), + (c, name, cb, userdata)) +PROXY_STUB (pa_context_get_sink_info_list, pa_operation *, + (pa_context *c, pa_sink_info_cb_t cb, void *userdata), + (c, cb, userdata)) +PROXY_STUB (pa_context_get_source_info_by_name, pa_operation*, + (pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata), + (c, name, cb, userdata)) +PROXY_STUB (pa_context_get_source_info_list, pa_operation *, + (pa_context *c, pa_source_info_cb_t cb, void *userdata), + (c, cb, userdata)) +PROXY_STUB (pa_context_get_state, pa_context_state_t, + (pa_context *c), + (c)) +PROXY_STUB_VOID(pa_context_unref, + (pa_context *c), + (c)) +PROXY_STUB (pa_context_errno, int, + (pa_context *c), + (c)) +PROXY_STUB (pa_context_new, pa_context*, + (pa_mainloop_api *mainloop, const char *name), + (mainloop, name)) +PROXY_STUB_VOID(pa_context_set_state_callback, + (pa_context *c, pa_context_notify_cb_t cb, void *userdata), + (c, cb, userdata)) + +PROXY_STUB (pa_frame_size, size_t, + (const pa_sample_spec *spec), + (spec)) +PROXY_STUB (pa_get_library_version, const char *, (void), ()) +PROXY_STUB_VOID(pa_operation_unref, + (pa_operation *o), + (o)) +PROXY_STUB (pa_operation_get_state, pa_operation_state_t, + (pa_operation *o), + (o)) +PROXY_STUB_VOID(pa_operation_cancel, + (pa_operation *o), + (o)) + +PROXY_STUB (pa_rtclock_now, pa_usec_t, + (void), + ()) +PROXY_STUB (pa_sample_format_to_string, const char*, + (pa_sample_format_t f), + (f)) +PROXY_STUB (pa_sample_spec_valid, int, + (const pa_sample_spec *spec), + (spec)) +PROXY_STUB (pa_strerror, const char*, + (int error), + (error)) + +#if PA_PROTOCOL_VERSION >= 16 +PROXY_STUB (pa_stream_connect_playback, int, + (pa_stream *s, const char *dev, const pa_buffer_attr *attr, + pa_stream_flags_t flags, const pa_cvolume *volume, pa_stream *sync_stream), + (s, dev, attr, flags, volume, sync_stream)) +#else +PROXY_STUB (pa_stream_connect_playback, int, + (pa_stream *s, const char *dev, const pa_buffer_attr *attr, + pa_stream_flags_t flags, pa_cvolume *volume, pa_stream *sync_stream), + (s, dev, attr, flags, volume, sync_stream)) +#endif +PROXY_STUB (pa_stream_connect_record, int, + (pa_stream *s, const char *dev, const pa_buffer_attr *attr, + pa_stream_flags_t flags), + (s, dev, attr, flags)) +PROXY_STUB (pa_stream_disconnect, int, + (pa_stream *s), + (s)) +PROXY_STUB (pa_stream_get_sample_spec, const pa_sample_spec*, + (pa_stream *s), + (s)) +PROXY_STUB_VOID(pa_stream_set_latency_update_callback, + (pa_stream *p, pa_stream_notify_cb_t cb, void *userdata), + (p, cb, userdata)) +PROXY_STUB (pa_stream_write, int, + (pa_stream *p, const void *data, size_t bytes, pa_free_cb_t free_cb, + int64_t offset, pa_seek_mode_t seek), + (p, data, bytes, free_cb, offset, seek)) +PROXY_STUB_VOID(pa_stream_unref, + (pa_stream *s), + (s)) +PROXY_STUB (pa_stream_get_state, pa_stream_state_t, + (pa_stream *p), + (p)) +PROXY_STUB (pa_stream_get_latency, int, + (pa_stream *s, pa_usec_t *r_usec, int *negative), + (s, r_usec, negative)) +PROXY_STUB (pa_stream_get_timing_info, pa_timing_info*, + (pa_stream *s), + (s)) +PROXY_STUB (pa_stream_readable_size, size_t, + (pa_stream *p), + (p)) +PROXY_STUB (pa_stream_set_buffer_attr, pa_operation *, + (pa_stream *s, const pa_buffer_attr *attr, pa_stream_success_cb_t cb, void *userdata), + (s, attr, cb, userdata)) +PROXY_STUB_VOID(pa_stream_set_state_callback, + (pa_stream *s, pa_stream_notify_cb_t cb, void *userdata), + (s, cb, userdata)) +PROXY_STUB_VOID(pa_stream_set_underflow_callback, + (pa_stream *s, pa_stream_notify_cb_t cb, void *userdata), + (s, cb, userdata)) +PROXY_STUB_VOID(pa_stream_set_overflow_callback, + (pa_stream *s, pa_stream_notify_cb_t cb, void *userdata), + (s, cb, userdata)) +PROXY_STUB_VOID(pa_stream_set_write_callback, + (pa_stream *s, pa_stream_request_cb_t cb, void *userdata), + (s, cb, userdata)) +PROXY_STUB (pa_stream_flush, pa_operation*, + (pa_stream *s, pa_stream_success_cb_t cb, void *userdata), + (s, cb, userdata)) +PROXY_STUB (pa_stream_drain, pa_operation*, + (pa_stream *s, pa_stream_success_cb_t cb, void *userdata), + (s, cb, userdata)) +PROXY_STUB (pa_stream_trigger, pa_operation*, + (pa_stream *s, pa_stream_success_cb_t cb, void *userdata), + (s, cb, userdata)) +PROXY_STUB (pa_stream_new, pa_stream*, + (pa_context *c, const char *name, const pa_sample_spec *ss, + const pa_channel_map *map), + (c, name, ss, map)) +PROXY_STUB (pa_stream_get_buffer_attr, const pa_buffer_attr*, + (pa_stream *s), + (s)) +PROXY_STUB (pa_stream_peek, int, + (pa_stream *p, const void **data, size_t *bytes), + (p, data, bytes)) +PROXY_STUB (pa_stream_cork, pa_operation*, + (pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata), + (s, b, cb, userdata)) +PROXY_STUB (pa_stream_drop, int, + (pa_stream *p), + (p)) +PROXY_STUB (pa_stream_writable_size, size_t, + (pa_stream *p), + (p)) + +PROXY_STUB_VOID(pa_threaded_mainloop_stop, + (pa_threaded_mainloop *m), + (m)) +PROXY_STUB (pa_threaded_mainloop_get_api, pa_mainloop_api*, + (pa_threaded_mainloop *m), + (m)) +PROXY_STUB_VOID(pa_threaded_mainloop_free, + (pa_threaded_mainloop* m), + (m)) +PROXY_STUB_VOID(pa_threaded_mainloop_signal, + (pa_threaded_mainloop *m, int wait_for_accept), + (m, wait_for_accept)) +PROXY_STUB_VOID(pa_threaded_mainloop_unlock, + (pa_threaded_mainloop *m), + (m)) +PROXY_STUB (pa_threaded_mainloop_new, pa_threaded_mainloop *, + (void), + ()) +PROXY_STUB_VOID(pa_threaded_mainloop_wait, + (pa_threaded_mainloop *m), + (m)) +PROXY_STUB (pa_threaded_mainloop_start, int, + (pa_threaded_mainloop *m), + (m)) +PROXY_STUB_VOID(pa_threaded_mainloop_lock, + (pa_threaded_mainloop *m), + (m)) + +PROXY_STUB (pa_usec_to_bytes, size_t, + (pa_usec_t t, const pa_sample_spec *spec), + (t, spec)) + +#define FUNC_ENTRY(function) { #function , (void (**)(void)) & g_pfn_ ## function } +static struct +{ + const char *pszName; + void (**pfn)(void); +} const g_aImportedFunctions[] = +{ + FUNC_ENTRY(pa_bytes_per_second), + FUNC_ENTRY(pa_bytes_to_usec), + FUNC_ENTRY(pa_channel_map_init_auto), + + FUNC_ENTRY(pa_context_connect), + FUNC_ENTRY(pa_context_disconnect), + FUNC_ENTRY(pa_context_get_server_info), + FUNC_ENTRY(pa_context_get_sink_info_by_name), + FUNC_ENTRY(pa_context_get_sink_info_list), + FUNC_ENTRY(pa_context_get_source_info_by_name), + FUNC_ENTRY(pa_context_get_source_info_list), + FUNC_ENTRY(pa_context_get_state), + FUNC_ENTRY(pa_context_unref), + FUNC_ENTRY(pa_context_errno), + FUNC_ENTRY(pa_context_new), + FUNC_ENTRY(pa_context_set_state_callback), + + FUNC_ENTRY(pa_frame_size), + FUNC_ENTRY(pa_get_library_version), + FUNC_ENTRY(pa_operation_unref), + FUNC_ENTRY(pa_operation_get_state), + FUNC_ENTRY(pa_operation_cancel), + FUNC_ENTRY(pa_rtclock_now), + FUNC_ENTRY(pa_sample_format_to_string), + FUNC_ENTRY(pa_sample_spec_valid), + FUNC_ENTRY(pa_strerror), + + FUNC_ENTRY(pa_stream_connect_playback), + FUNC_ENTRY(pa_stream_connect_record), + FUNC_ENTRY(pa_stream_disconnect), + FUNC_ENTRY(pa_stream_get_sample_spec), + FUNC_ENTRY(pa_stream_set_latency_update_callback), + FUNC_ENTRY(pa_stream_write), + FUNC_ENTRY(pa_stream_unref), + FUNC_ENTRY(pa_stream_get_state), + FUNC_ENTRY(pa_stream_get_latency), + FUNC_ENTRY(pa_stream_get_timing_info), + FUNC_ENTRY(pa_stream_readable_size), + FUNC_ENTRY(pa_stream_set_buffer_attr), + FUNC_ENTRY(pa_stream_set_state_callback), + FUNC_ENTRY(pa_stream_set_underflow_callback), + FUNC_ENTRY(pa_stream_set_overflow_callback), + FUNC_ENTRY(pa_stream_set_write_callback), + FUNC_ENTRY(pa_stream_flush), + FUNC_ENTRY(pa_stream_drain), + FUNC_ENTRY(pa_stream_trigger), + FUNC_ENTRY(pa_stream_new), + FUNC_ENTRY(pa_stream_get_buffer_attr), + FUNC_ENTRY(pa_stream_peek), + FUNC_ENTRY(pa_stream_cork), + FUNC_ENTRY(pa_stream_drop), + FUNC_ENTRY(pa_stream_writable_size), + + FUNC_ENTRY(pa_threaded_mainloop_stop), + FUNC_ENTRY(pa_threaded_mainloop_get_api), + FUNC_ENTRY(pa_threaded_mainloop_free), + FUNC_ENTRY(pa_threaded_mainloop_signal), + FUNC_ENTRY(pa_threaded_mainloop_unlock), + FUNC_ENTRY(pa_threaded_mainloop_new), + FUNC_ENTRY(pa_threaded_mainloop_wait), + FUNC_ENTRY(pa_threaded_mainloop_start), + FUNC_ENTRY(pa_threaded_mainloop_lock), + + FUNC_ENTRY(pa_usec_to_bytes) +}; +#undef FUNC_ENTRY + +/** Init once. */ +static RTONCE g_PulseAudioLibInitOnce = RTONCE_INITIALIZER; + +/** @callback_method_impl{FNRTONCE} */ +static DECLCALLBACK(int32_t) drvHostAudioPulseLibInitOnce(void *pvUser) +{ + RT_NOREF(pvUser); + LogFlowFunc(("\n")); + + RTLDRMOD hMod = NIL_RTLDRMOD; + int rc = RTLdrLoadSystemEx(VBOX_PULSE_LIB, RTLDRLOAD_FLAGS_NO_UNLOAD, &hMod); + if (RT_SUCCESS(rc)) + { + for (unsigned i = 0; i < RT_ELEMENTS(g_aImportedFunctions); i++) + { + rc = RTLdrGetSymbol(hMod, g_aImportedFunctions[i].pszName, (void **)g_aImportedFunctions[i].pfn); + if (RT_FAILURE(rc)) + { + LogRelFunc(("Failed to resolve function #%u: '%s' (%Rrc)\n", i, g_aImportedFunctions[i].pszName, rc)); + break; + } + } + + RTLdrClose(hMod); + } + else + LogRelFunc(("Failed to load library %s: %Rrc\n", VBOX_PULSE_LIB, rc)); + return rc; +} + +/** + * Try to dynamically load the PulseAudio libraries. + * + * @returns VBox status code. + */ +int audioLoadPulseLib(void) +{ + LogFlowFunc(("\n")); + return RTOnce(&g_PulseAudioLibInitOnce, drvHostAudioPulseLibInitOnce, NULL); +} + |