PipeWire: Clean up to runtime linking.

This will cleanly fail when a required entry point is unavailable.

Public issue https://github.com/mackron/miniaudio/issues/1104
This commit is contained in:
David Reid
2026-04-26 09:18:26 +10:00
parent 72a6203849
commit dad1060489
+74 -86
View File
@@ -32024,12 +32024,33 @@ static void ma_backend_info__pipewire(ma_device_backend_info* pBackendInfo)
pBackendInfo->pName = "PipeWire"; pBackendInfo->pName = "PipeWire";
} }
#ifndef MA_NO_RUNTIME_LINKING
#define MA_PIPEWIRE_SYM(functionName) \
pContextStatePipeWire->functionName = (ma_##functionName##_proc)ma_dlsym(pLog, hPipeWire, #functionName); \
if (pContextStatePipeWire->functionName == NULL) { \
ma_dlclose(pLog, hPipeWire); \
ma_free(pContextStatePipeWire, ma_context_get_allocation_callbacks(pContext)); \
return MA_NO_BACKEND; \
}
#else
#define MA_PIPEWIRE_SYM(functionName) \
pContextStatePipeWire->functionName = pContextStatePipeWire->functionName;
#endif
static ma_result ma_context_init__pipewire(ma_context* pContext, const void* pContextBackendConfig, void** ppContextState) static ma_result ma_context_init__pipewire(ma_context* pContext, const void* pContextBackendConfig, void** ppContextState)
{ {
/* We'll use a list of possible shared object names for easier extensibility. */ /* We'll use a list of possible shared object names for easier extensibility. */
ma_context_state_pipewire* pContextStatePipeWire; ma_context_state_pipewire* pContextStatePipeWire;
ma_context_config_pipewire* pContextConfigPipeWire = (ma_context_config_pipewire*)pContextBackendConfig; ma_context_config_pipewire* pContextConfigPipeWire = (ma_context_config_pipewire*)pContextBackendConfig;
ma_log* pLog = ma_context_get_log(pContext); ma_log* pLog = ma_context_get_log(pContext);
#ifndef MA_NO_RUNTIME_LINKING
ma_handle hPipeWire;
size_t iName;
const char* pSONames[] = {
"libpipewire-0.3.so.0",
"libpipewire.so"
};
#endif
(void)pContextConfigPipeWire; (void)pContextConfigPipeWire;
@@ -32040,17 +32061,9 @@ static ma_result ma_context_init__pipewire(ma_context* pContext, const void* pCo
pContextStatePipeWire->pLog = pLog; pContextStatePipeWire->pLog = pLog;
/* Check if we have a PipeWire SO. If we can't find this we need to abort. */ /* Check if we have a PipeWire SO. If we can't find this we need to abort. */
#ifndef MA_NO_RUNTIME_LINKING #ifndef MA_NO_RUNTIME_LINKING
{ {
ma_handle hPipeWire;
size_t iName;
const char* pSONames[] = {
"libpipewire-0.3.so.0",
"libpipewire.so"
};
for (iName = 0; iName < ma_countof(pSONames); iName += 1) { for (iName = 0; iName < ma_countof(pSONames); iName += 1) {
hPipeWire = ma_dlopen(pLog, pSONames[iName]); hPipeWire = ma_dlopen(pLog, pSONames[iName]);
if (hPipeWire != NULL) { if (hPipeWire != NULL) {
@@ -32064,90 +32077,65 @@ static ma_result ma_context_init__pipewire(ma_context* pContext, const void* pCo
} }
pContextStatePipeWire->hPipeWire = hPipeWire; pContextStatePipeWire->hPipeWire = hPipeWire;
pContextStatePipeWire->pw_init = (ma_pw_init_proc )ma_dlsym(pLog, hPipeWire, "pw_init"); }
pContextStatePipeWire->pw_deinit = (ma_pw_deinit_proc )ma_dlsym(pLog, hPipeWire, "pw_deinit"); #endif
pContextStatePipeWire->pw_loop_new = (ma_pw_loop_new_proc )ma_dlsym(pLog, hPipeWire, "pw_loop_new");
pContextStatePipeWire->pw_loop_destroy = (ma_pw_loop_destroy_proc )ma_dlsym(pLog, hPipeWire, "pw_loop_destroy"); MA_PIPEWIRE_SYM(pw_init)
pContextStatePipeWire->pw_loop_set_name = (ma_pw_loop_set_name_proc )ma_dlsym(pLog, hPipeWire, "pw_loop_set_name"); MA_PIPEWIRE_SYM(pw_deinit)
pContextStatePipeWire->pw_loop_enter = (ma_pw_loop_enter_proc )ma_dlsym(pLog, hPipeWire, "pw_loop_enter"); MA_PIPEWIRE_SYM(pw_loop_new)
pContextStatePipeWire->pw_loop_leave = (ma_pw_loop_leave_proc )ma_dlsym(pLog, hPipeWire, "pw_loop_leave"); MA_PIPEWIRE_SYM(pw_loop_destroy)
pContextStatePipeWire->pw_loop_iterate = (ma_pw_loop_iterate_proc )ma_dlsym(pLog, hPipeWire, "pw_loop_iterate"); MA_PIPEWIRE_SYM(pw_loop_set_name)
pContextStatePipeWire->pw_loop_add_event = (ma_pw_loop_add_event_proc )ma_dlsym(pLog, hPipeWire, "pw_loop_add_event"); MA_PIPEWIRE_SYM(pw_loop_enter)
pContextStatePipeWire->pw_loop_signal_event = (ma_pw_loop_signal_event_proc )ma_dlsym(pLog, hPipeWire, "pw_loop_signal_event"); MA_PIPEWIRE_SYM(pw_loop_leave)
pContextStatePipeWire->pw_thread_loop_new = (ma_pw_thread_loop_new_proc )ma_dlsym(pLog, hPipeWire, "pw_thread_loop_new"); MA_PIPEWIRE_SYM(pw_loop_iterate)
pContextStatePipeWire->pw_thread_loop_destroy = (ma_pw_thread_loop_destroy_proc )ma_dlsym(pLog, hPipeWire, "pw_thread_loop_destroy"); MA_PIPEWIRE_SYM(pw_loop_add_event)
pContextStatePipeWire->pw_thread_loop_get_loop = (ma_pw_thread_loop_get_loop_proc )ma_dlsym(pLog, hPipeWire, "pw_thread_loop_get_loop"); MA_PIPEWIRE_SYM(pw_loop_signal_event)
pContextStatePipeWire->pw_thread_loop_start = (ma_pw_thread_loop_start_proc )ma_dlsym(pLog, hPipeWire, "pw_thread_loop_start"); MA_PIPEWIRE_SYM(pw_thread_loop_new)
pContextStatePipeWire->pw_thread_loop_lock = (ma_pw_thread_loop_lock_proc )ma_dlsym(pLog, hPipeWire, "pw_thread_loop_lock"); MA_PIPEWIRE_SYM(pw_thread_loop_destroy)
pContextStatePipeWire->pw_thread_loop_unlock = (ma_pw_thread_loop_unlock_proc )ma_dlsym(pLog, hPipeWire, "pw_thread_loop_unlock"); MA_PIPEWIRE_SYM(pw_thread_loop_get_loop)
pContextStatePipeWire->pw_context_new = (ma_pw_context_new_proc )ma_dlsym(pLog, hPipeWire, "pw_context_new"); MA_PIPEWIRE_SYM(pw_thread_loop_start)
pContextStatePipeWire->pw_context_destroy = (ma_pw_context_destroy_proc )ma_dlsym(pLog, hPipeWire, "pw_context_destroy"); MA_PIPEWIRE_SYM(pw_thread_loop_lock)
pContextStatePipeWire->pw_context_connect = (ma_pw_context_connect_proc )ma_dlsym(pLog, hPipeWire, "pw_context_connect"); MA_PIPEWIRE_SYM(pw_thread_loop_unlock)
pContextStatePipeWire->pw_core_disconnect = (ma_pw_core_disconnect_proc )ma_dlsym(pLog, hPipeWire, "pw_core_disconnect"); MA_PIPEWIRE_SYM(pw_context_new)
pContextStatePipeWire->pw_core_add_listener = (ma_pw_core_add_listener_proc )ma_dlsym(pLog, hPipeWire, "pw_core_add_listener"); MA_PIPEWIRE_SYM(pw_context_destroy)
pContextStatePipeWire->pw_core_get_registry = (ma_pw_core_get_registry_proc )ma_dlsym(pLog, hPipeWire, "pw_core_get_registry"); MA_PIPEWIRE_SYM(pw_context_connect)
pContextStatePipeWire->pw_core_sync = (ma_pw_core_sync_proc )ma_dlsym(pLog, hPipeWire, "pw_core_sync"); MA_PIPEWIRE_SYM(pw_core_disconnect)
pContextStatePipeWire->pw_registry_add_listener = (ma_pw_registry_add_listener_proc )ma_dlsym(pLog, hPipeWire, "pw_registry_add_listener"); MA_PIPEWIRE_SYM(pw_core_add_listener)
pContextStatePipeWire->pw_registry_bind = (ma_pw_registry_bind_proc )ma_dlsym(pLog, hPipeWire, "pw_registry_bind"); MA_PIPEWIRE_SYM(pw_core_get_registry)
pContextStatePipeWire->pw_proxy_destroy = (ma_pw_proxy_destroy_proc )ma_dlsym(pLog, hPipeWire, "pw_proxy_destroy"); MA_PIPEWIRE_SYM(pw_core_sync)
pContextStatePipeWire->pw_properties_new = (ma_pw_properties_new_proc )ma_dlsym(pLog, hPipeWire, "pw_properties_new"); MA_PIPEWIRE_SYM(pw_registry_add_listener)
pContextStatePipeWire->pw_properties_free = (ma_pw_properties_free_proc )ma_dlsym(pLog, hPipeWire, "pw_properties_free"); MA_PIPEWIRE_SYM(pw_registry_bind)
pContextStatePipeWire->pw_properties_set = (ma_pw_properties_set_proc )ma_dlsym(pLog, hPipeWire, "pw_properties_set"); MA_PIPEWIRE_SYM(pw_proxy_destroy)
pContextStatePipeWire->pw_stream_new = (ma_pw_stream_new_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_new"); MA_PIPEWIRE_SYM(pw_properties_new)
pContextStatePipeWire->pw_stream_destroy = (ma_pw_stream_destroy_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_destroy"); MA_PIPEWIRE_SYM(pw_properties_free)
pContextStatePipeWire->pw_stream_add_listener = (ma_pw_stream_add_listener_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_add_listener"); MA_PIPEWIRE_SYM(pw_properties_set)
pContextStatePipeWire->pw_stream_connect = (ma_pw_stream_connect_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_connect"); MA_PIPEWIRE_SYM(pw_stream_new)
pContextStatePipeWire->pw_stream_set_active = (ma_pw_stream_set_active_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_set_active"); MA_PIPEWIRE_SYM(pw_stream_destroy)
pContextStatePipeWire->pw_stream_dequeue_buffer = (ma_pw_stream_dequeue_buffer_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_dequeue_buffer"); MA_PIPEWIRE_SYM(pw_stream_add_listener)
pContextStatePipeWire->pw_stream_queue_buffer = (ma_pw_stream_queue_buffer_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_queue_buffer"); MA_PIPEWIRE_SYM(pw_stream_connect)
pContextStatePipeWire->pw_stream_update_params = (ma_pw_stream_update_params_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_update_params"); MA_PIPEWIRE_SYM(pw_stream_dequeue_buffer)
pContextStatePipeWire->pw_stream_update_properties = (ma_pw_stream_update_properties_proc)ma_dlsym(pLog, hPipeWire, "pw_stream_update_properties"); MA_PIPEWIRE_SYM(pw_stream_queue_buffer)
pContextStatePipeWire->pw_stream_get_time_n = (ma_pw_stream_get_time_n_proc )ma_dlsym(pLog, hPipeWire, "pw_stream_get_time_n"); MA_PIPEWIRE_SYM(pw_stream_update_params)
MA_PIPEWIRE_SYM(pw_stream_update_properties)
MA_PIPEWIRE_SYM(pw_stream_get_time_n)
/*
Just an annoying detail here for functions that use `bool`. For C89 compatibility we don't actually use `bool`, but
instead `unsigned char`. This requires an explicit cast. We'll just do a hack here to work around it. We could update
`MA_PIPEWIRE_SYM` to do a cast in the general case, but I want the compile time linking path to catch any potential
API and ABI compatibility errors in our own function declarations.
*/
#ifndef MA_NO_RUNTIME_LINKING
{
MA_PIPEWIRE_SYM(pw_stream_set_active)
} }
#else #else
{ {
pContextStatePipeWire->pw_init = pw_init; pContextStatePipeWire->pw_stream_set_active = (ma_pw_stream_set_active_proc)(void*)pw_stream_set_active;
pContextStatePipeWire->pw_deinit = pw_deinit;
pContextStatePipeWire->pw_loop_new = pw_loop_new;
pContextStatePipeWire->pw_loop_destroy = pw_loop_destroy;
pContextStatePipeWire->pw_loop_set_name = pw_loop_set_name;
pContextStatePipeWire->pw_loop_enter = pw_loop_enter;
pContextStatePipeWire->pw_loop_leave = pw_loop_leave;
pContextStatePipeWire->pw_loop_iterate = pw_loop_iterate;
pContextStatePipeWire->pw_loop_add_event = pw_loop_add_event;
pContextStatePipeWire->pw_loop_signal_event = pw_loop_signal_event;
pContextStatePipeWire->pw_thread_loop_new = pw_thread_loop_new;
pContextStatePipeWire->pw_thread_loop_destroy = pw_thread_loop_destroy;
pContextStatePipeWire->pw_thread_loop_get_loop = pw_thread_loop_get_loop;
pContextStatePipeWire->pw_thread_loop_start = pw_thread_loop_start;
pContextStatePipeWire->pw_thread_loop_lock = pw_thread_loop_lock;
pContextStatePipeWire->pw_thread_loop_unlock = pw_thread_loop_unlock;
pContextStatePipeWire->pw_context_new = pw_context_new;
pContextStatePipeWire->pw_context_destroy = pw_context_destroy;
pContextStatePipeWire->pw_context_connect = pw_context_connect;
pContextStatePipeWire->pw_core_disconnect = pw_core_disconnect;
pContextStatePipeWire->pw_core_add_listener = pw_core_add_listener;
pContextStatePipeWire->pw_core_get_registry = pw_core_get_registry;
pContextStatePipeWire->pw_core_sync = pw_core_sync;
pContextStatePipeWire->pw_registry_add_listener = pw_registry_add_listener;
pContextStatePipeWire->pw_registry_bind = pw_registry_bind;
pContextStatePipeWire->pw_proxy_destroy = pw_proxy_destroy;
pContextStatePipeWire->pw_properties_new = pw_properties_new;
pContextStatePipeWire->pw_properties_free = pw_properties_free;
pContextStatePipeWire->pw_properties_set = pw_properties_set;
pContextStatePipeWire->pw_stream_new = pw_stream_new;
pContextStatePipeWire->pw_stream_destroy = pw_stream_destroy;
pContextStatePipeWire->pw_stream_add_listener = pw_stream_add_listener;
pContextStatePipeWire->pw_stream_connect = pw_stream_connect;
pContextStatePipeWire->pw_stream_set_active = (ma_pw_stream_set_active_proc)(void*)pw_stream_set_active; /* This cast is because we use `unsigned char` instead of `bool`. */
pContextStatePipeWire->pw_stream_dequeue_buffer = pw_stream_dequeue_buffer;
pContextStatePipeWire->pw_stream_queue_buffer = pw_stream_queue_buffer;
pContextStatePipeWire->pw_stream_update_params = pw_stream_update_params;
pContextStatePipeWire->pw_stream_update_properties = pw_stream_update_properties;
pContextStatePipeWire->pw_stream_get_time_n = pw_stream_get_time_n;
} }
#endif #endif
if (pContextStatePipeWire->pw_init != NULL) { if (pContextStatePipeWire->pw_init != NULL) {
pContextStatePipeWire->pw_init(NULL, NULL); pContextStatePipeWire->pw_init(NULL, NULL);
} }