Merge commit '852f2a6343518919e5ca8d3c1bbcab9f493e3cd8'

This commit is contained in:
2024-01-17 17:02:59 +01:00
1244 changed files with 50102 additions and 28146 deletions

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -63,7 +63,7 @@
* This seems to be a sane lower limit as Pipewire
* uses it in several of it's own modules.
*/
#define PW_MIN_SAMPLES 32 /* About 0.67ms at 48kHz */
#define PW_MIN_SAMPLES 32 // About 0.67ms at 48kHz
#define PW_BASE_CLOCK_RATE 48000
#define PW_POD_BUFFER_LENGTH 1024
@ -82,7 +82,7 @@ enum PW_READY_FLAGS
static SDL_bool pipewire_initialized = SDL_FALSE;
/* Pipewire entry points */
// Pipewire entry points
static const char *(*PIPEWIRE_pw_get_library_version)(void);
static void (*PIPEWIRE_pw_init)(int *, char ***);
static void (*PIPEWIRE_pw_deinit)(void);
@ -126,8 +126,8 @@ static void *pipewire_handle = NULL;
static int pipewire_dlsym(const char *fn, void **addr)
{
*addr = SDL_LoadFunction(pipewire_handle, fn);
if (*addr == NULL) {
/* Don't call SDL_SetError(): SDL_LoadFunction already did. */
if (!*addr) {
// Don't call SDL_SetError(): SDL_LoadFunction already did.
return 0;
}
@ -142,7 +142,7 @@ static int pipewire_dlsym(const char *fn, void **addr)
static int load_pipewire_library(void)
{
pipewire_handle = SDL_LoadObject(pipewire_library);
return pipewire_handle != NULL ? 0 : -1;
return pipewire_handle ? 0 : -1;
}
static void unload_pipewire_library(void)
@ -163,10 +163,11 @@ static int load_pipewire_library(void)
}
static void unload_pipewire_library(void)
{ /* Nothing to do */
{
// Nothing to do
}
#endif /* SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC */
#endif // SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC
static int load_pipewire_syms(void)
{
@ -220,7 +221,7 @@ static int init_pipewire_library(void)
return -1;
}
/* SDL can build against 0.3.20, but requires 0.3.24 */
// SDL can build against 0.3.20, but requires 0.3.24
if (pipewire_version_at_least(0, 3, 24)) {
PIPEWIRE_pw_init(NULL, NULL);
return 0;
@ -237,7 +238,7 @@ static void deinit_pipewire_library(void)
unload_pipewire_library();
}
/* A generic Pipewire node object used for enumeration. */
// A generic Pipewire node object used for enumeration.
struct node_object
{
struct spa_list link;
@ -260,7 +261,7 @@ struct node_object
struct spa_hook core_listener;
};
/* A sink/source node used for stream I/O. */
// A sink/source node used for stream I/O.
struct io_node
{
struct spa_list link;
@ -269,13 +270,13 @@ struct io_node
SDL_bool is_capture;
SDL_AudioSpec spec;
const char *name; /* Friendly name */
const char *path; /* OS identifier (i.e. ALSA endpoint) */
const char *name; // Friendly name
const char *path; // OS identifier (i.e. ALSA endpoint)
char buf[]; /* Buffer to hold the name and path strings. */
char buf[]; // Buffer to hold the name and path strings.
};
/* The global hotplug thread and associated objects. */
// The global hotplug thread and associated objects.
static struct pw_thread_loop *hotplug_loop;
static struct pw_core *hotplug_core;
static struct pw_context *hotplug_context;
@ -291,13 +292,13 @@ static SDL_bool hotplug_events_enabled;
static char *pipewire_default_sink_id = NULL;
static char *pipewire_default_source_id = NULL;
/* The active node list */
// The active node list
static SDL_bool io_list_check_add(struct io_node *node)
{
struct io_node *n;
SDL_bool ret = SDL_TRUE;
/* See if the node is already in the list */
// See if the node is already in the list
spa_list_for_each (n, &hotplug_io_list, link) {
if (n->id == node->id) {
ret = SDL_FALSE;
@ -305,7 +306,7 @@ static SDL_bool io_list_check_add(struct io_node *node)
}
}
/* Add to the list if the node doesn't already exist */
// Add to the list if the node doesn't already exist
spa_list_append(&hotplug_io_list, &node->link);
if (hotplug_events_enabled) {
@ -321,7 +322,7 @@ static void io_list_remove(Uint32 id)
{
struct io_node *n, *temp;
/* Find and remove the node from the list */
// Find and remove the node from the list
spa_list_for_each_safe (n, temp, &hotplug_io_list, link) {
if (n->id == id) {
spa_list_remove(&n->link);
@ -360,7 +361,7 @@ static struct io_node *io_list_get_by_id(Uint32 id)
static void node_object_destroy(struct node_object *node)
{
SDL_assert(node);
SDL_assert(node != NULL);
spa_list_remove(&node->link);
spa_hook_remove(&node->node_listener);
@ -369,10 +370,10 @@ static void node_object_destroy(struct node_object *node)
PIPEWIRE_pw_proxy_destroy(node->proxy);
}
/* The pending node list */
// The pending node list
static void pending_list_add(struct node_object *node)
{
SDL_assert(node);
SDL_assert(node != NULL);
spa_list_append(&hotplug_pending_list, &node->link);
}
@ -401,9 +402,9 @@ static void *node_object_new(Uint32 id, const char *type, Uint32 version, const
struct pw_proxy *proxy;
struct node_object *node;
/* Create the proxy object */
// Create the proxy object
proxy = pw_registry_bind(hotplug_registry, id, type, version, sizeof(struct node_object));
if (proxy == NULL) {
if (!proxy) {
SDL_SetError("Pipewire: Failed to create proxy object (%i)", errno);
return NULL;
}
@ -414,24 +415,24 @@ static void *node_object_new(Uint32 id, const char *type, Uint32 version, const
node->id = id;
node->proxy = proxy;
/* Add the callbacks */
// Add the callbacks
pw_core_add_listener(hotplug_core, &node->core_listener, core_events, node);
PIPEWIRE_pw_proxy_add_object_listener(node->proxy, &node->node_listener, funcs, node);
/* Add the node to the active list */
// Add the node to the active list
pending_list_add(node);
return node;
}
/* Core sync points */
// Core sync points
static void core_events_hotplug_init_callback(void *object, uint32_t id, int seq)
{
if (id == PW_ID_CORE && seq == hotplug_init_seq_val) {
/* This core listener is no longer needed. */
// This core listener is no longer needed.
spa_hook_remove(&hotplug_core_listener);
/* Signal that the initial I/O list is populated */
// Signal that the initial I/O list is populated
hotplug_init_complete = SDL_TRUE;
PIPEWIRE_pw_thread_loop_signal(hotplug_loop, false);
}
@ -483,7 +484,7 @@ static void hotplug_core_sync(struct node_object *node)
}
}
/* Helpers for retrieving values from params */
// Helpers for retrieving values from params
static SDL_bool get_range_param(const struct spa_pod *param, Uint32 key, int *def, int *min, int *max)
{
const struct spa_pod_prop *prop;
@ -535,7 +536,7 @@ static SDL_bool get_int_param(const struct spa_pod *param, Uint32 key, int *val)
return SDL_FALSE;
}
/* Interface node callbacks */
// Interface node callbacks
static void node_event_info(void *object, const struct pw_node_info *info)
{
struct node_object *node = object;
@ -549,7 +550,7 @@ static void node_event_info(void *object, const struct pw_node_info *info)
io->spec.channels = (Uint8)SDL_atoi(prop_val);
}
/* Need to parse the parameters to get the sample rate */
// Need to parse the parameters to get the sample rate
for (i = 0; i < info->n_params; ++i) {
pw_node_enum_params(node->proxy, 0, info->params[i].id, 0, 0, NULL);
}
@ -563,7 +564,7 @@ static void node_event_param(void *object, int seq, uint32_t id, uint32_t index,
struct node_object *node = object;
struct io_node *io = node->userdata;
/* Get the default frequency */
// Get the default frequency
if (io->spec.freq == 0) {
get_range_param(param, SPA_FORMAT_AUDIO_rate, &io->spec.freq, NULL, NULL);
}
@ -586,19 +587,19 @@ static const struct pw_node_events interface_node_events = { PW_VERSION_NODE_EVE
static char *get_name_from_json(const char *json)
{
struct spa_json parser[2];
char key[7]; /* "name" */
char key[7]; // "name"
char value[PW_MAX_IDENTIFIER_LENGTH];
spa_json_init(&parser[0], json, SDL_strlen(json));
if (spa_json_enter_object(&parser[0], &parser[1]) <= 0) {
/* Not actually JSON */
// Not actually JSON
return NULL;
}
if (spa_json_get_string(&parser[1], key, sizeof(key)) <= 0) {
/* Not actually a key/value pair */
// Not actually a key/value pair
return NULL;
}
if (spa_json_get_string(&parser[1], value, sizeof(value)) <= 0) {
/* Somehow had a key with no value? */
// Somehow had a key with no value?
return NULL;
}
return SDL_strdup(value);
@ -617,21 +618,21 @@ static void change_default_device(const char *path)
}
}
/* Metadata node callback */
// Metadata node callback
static int metadata_property(void *object, Uint32 subject, const char *key, const char *type, const char *value)
{
struct node_object *node = object;
if (subject == PW_ID_CORE && key != NULL && value != NULL) {
if (subject == PW_ID_CORE && key && value) {
if (!SDL_strcmp(key, "default.audio.sink")) {
if (pipewire_default_sink_id != NULL) {
if (pipewire_default_sink_id) {
SDL_free(pipewire_default_sink_id);
}
pipewire_default_sink_id = get_name_from_json(value);
node->persist = SDL_TRUE;
change_default_device(pipewire_default_sink_id);
} else if (!SDL_strcmp(key, "default.audio.source")) {
if (pipewire_default_source_id != NULL) {
if (pipewire_default_source_id) {
SDL_free(pipewire_default_source_id);
}
pipewire_default_source_id = get_name_from_json(value);
@ -645,13 +646,13 @@ static int metadata_property(void *object, Uint32 subject, const char *key, cons
static const struct pw_metadata_events metadata_node_events = { PW_VERSION_METADATA_EVENTS, .property = metadata_property };
/* Global registry callbacks */
// Global registry callbacks
static void registry_event_global_callback(void *object, uint32_t id, uint32_t permissions, const char *type, uint32_t version,
const struct spa_dict *props)
{
struct node_object *node;
/* We're only interested in interface and metadata nodes. */
// We're only interested in interface and metadata nodes.
if (!SDL_strcmp(type, PW_TYPE_INTERFACE_Node)) {
const char *media_class = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS);
@ -663,7 +664,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p
int desc_buffer_len;
int path_buffer_len;
/* Just want sink and capture */
// Just want sink and capture
if (!SDL_strcasecmp(media_class, "Audio/Sink")) {
is_capture = SDL_FALSE;
} else if (!SDL_strcasecmp(media_class, "Audio/Source")) {
@ -677,42 +678,41 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p
if (node_desc && node_path) {
node = node_object_new(id, type, version, &interface_node_events, &interface_core_events);
if (node == NULL) {
if (!node) {
SDL_SetError("Pipewire: Failed to allocate interface node");
return;
}
/* Allocate and initialize the I/O node information struct */
// Allocate and initialize the I/O node information struct
desc_buffer_len = SDL_strlen(node_desc) + 1;
path_buffer_len = SDL_strlen(node_path) + 1;
node->userdata = io = SDL_calloc(1, sizeof(struct io_node) + desc_buffer_len + path_buffer_len);
if (io == NULL) {
if (!io) {
node_object_destroy(node);
SDL_OutOfMemory();
return;
}
/* Begin setting the node properties */
// Begin setting the node properties
io->id = id;
io->is_capture = is_capture;
io->spec.format = SDL_AUDIO_F32; /* Pipewire uses floats internally, other formats require conversion. */
io->spec.format = SDL_AUDIO_F32; // Pipewire uses floats internally, other formats require conversion.
io->name = io->buf;
io->path = io->buf + desc_buffer_len;
SDL_strlcpy(io->buf, node_desc, desc_buffer_len);
SDL_strlcpy(io->buf + desc_buffer_len, node_path, path_buffer_len);
/* Update sync points */
// Update sync points
hotplug_core_sync(node);
}
}
} else if (!SDL_strcmp(type, PW_TYPE_INTERFACE_Metadata)) {
node = node_object_new(id, type, version, &metadata_node_events, &metadata_core_events);
if (node == NULL) {
if (!node) {
SDL_SetError("Pipewire: Failed to allocate metadata node");
return;
}
/* Update sync points */
// Update sync points
hotplug_core_sync(node);
}
}
@ -726,7 +726,7 @@ static void registry_event_remove_callback(void *object, uint32_t id)
static const struct pw_registry_events registry_events = { PW_VERSION_REGISTRY_EVENTS, .global = registry_event_global_callback,
.global_remove = registry_event_remove_callback };
/* The hotplug thread */
// The hotplug thread
static int hotplug_loop_init(void)
{
int res;
@ -735,22 +735,22 @@ static int hotplug_loop_init(void)
spa_list_init(&hotplug_io_list);
hotplug_loop = PIPEWIRE_pw_thread_loop_new("SDLAudioHotplug", NULL);
if (hotplug_loop == NULL) {
if (!hotplug_loop) {
return SDL_SetError("Pipewire: Failed to create hotplug detection loop (%i)", errno);
}
hotplug_context = PIPEWIRE_pw_context_new(PIPEWIRE_pw_thread_loop_get_loop(hotplug_loop), NULL, 0);
if (hotplug_context == NULL) {
if (!hotplug_context) {
return SDL_SetError("Pipewire: Failed to create hotplug detection context (%i)", errno);
}
hotplug_core = PIPEWIRE_pw_context_connect(hotplug_context, NULL, 0);
if (hotplug_core == NULL) {
if (!hotplug_core) {
return SDL_SetError("Pipewire: Failed to connect hotplug detection context (%i)", errno);
}
hotplug_registry = pw_core_get_registry(hotplug_core, PW_VERSION_REGISTRY, 0);
if (hotplug_registry == NULL) {
if (!hotplug_registry) {
return SDL_SetError("Pipewire: Failed to acquire hotplug detection registry (%i)", errno);
}
@ -782,11 +782,11 @@ static void hotplug_loop_destroy(void)
hotplug_init_complete = SDL_FALSE;
hotplug_events_enabled = SDL_FALSE;
if (pipewire_default_sink_id != NULL) {
if (pipewire_default_sink_id) {
SDL_free(pipewire_default_sink_id);
pipewire_default_sink_id = NULL;
}
if (pipewire_default_source_id != NULL) {
if (pipewire_default_source_id) {
SDL_free(pipewire_default_source_id);
pipewire_default_source_id = NULL;
}
@ -818,17 +818,17 @@ static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDe
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
/* Wait until the initial registry enumeration is complete */
// Wait until the initial registry enumeration is complete
if (!hotplug_init_complete) {
PIPEWIRE_pw_thread_loop_wait(hotplug_loop);
}
spa_list_for_each (io, &hotplug_io_list, link) {
SDL_AudioDevice *device = SDL_AddAudioDevice(io->is_capture, io->name, &io->spec, PW_ID_TO_HANDLE(io->id));
if (pipewire_default_sink_id != NULL && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) {
if (pipewire_default_sink_id && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) {
SDL_assert(!io->is_capture);
*default_output = device;
} else if (pipewire_default_source_id != NULL && SDL_strcmp(io->path, pipewire_default_source_id) == 0) {
} else if (pipewire_default_source_id && SDL_strcmp(io->path, pipewire_default_source_id) == 0) {
SDL_assert(io->is_capture);
*default_capture = device;
}
@ -839,7 +839,7 @@ static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDe
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
}
/* Channel maps that match the order in SDL_Audio.h */
// Channel maps that match the order in SDL_Audio.h
static const enum spa_audio_channel PIPEWIRE_channel_map_1[] = { SPA_AUDIO_CHANNEL_MONO };
static const enum spa_audio_channel PIPEWIRE_channel_map_2[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR };
static const enum spa_audio_channel PIPEWIRE_channel_map_3[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_LFE };
@ -890,7 +890,7 @@ static void initialize_spa_info(const SDL_AudioSpec *spec, struct spa_audio_info
break;
}
/* Pipewire natively supports all of SDL's sample formats */
// Pipewire natively supports all of SDL's sample formats
switch (spec->format) {
case SDL_AUDIO_U8:
info->format = SPA_AUDIO_FORMAT_U8;
@ -964,7 +964,7 @@ static void PIPEWIRE_FlushCapture(SDL_AudioDevice *device)
{
struct pw_stream *stream = device->hidden->stream;
struct pw_buffer *pw_buf = PIPEWIRE_pw_stream_dequeue_buffer(stream);
if (pw_buf != NULL) { // just requeue it without any further thought.
if (pw_buf) { // just requeue it without any further thought.
PIPEWIRE_pw_stream_queue_buffer(stream, pw_buf);
}
}
@ -1061,27 +1061,27 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
struct SDL_PrivateAudioData *priv;
struct pw_properties *props;
const char *app_name, *app_id, *stream_name, *stream_role, *error;
Uint32 node_id = device->handle == NULL ? PW_ID_ANY : PW_HANDLE_TO_ID(device->handle);
Uint32 node_id = !device->handle ? PW_ID_ANY : PW_HANDLE_TO_ID(device->handle);
const SDL_bool iscapture = device->iscapture;
int res;
/* Clamp the period size to sane values */
// Clamp the period size to sane values
const int min_period = PW_MIN_SAMPLES * SPA_MAX(device->spec.freq / PW_BASE_CLOCK_RATE, 1);
/* Get the hints for the application name, stream name and role */
// Get the hints for the application name, stream name and role
app_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME);
if (app_name == NULL || *app_name == '\0') {
if (!app_name || *app_name == '\0') {
app_name = SDL_GetHint(SDL_HINT_APP_NAME);
if (app_name == NULL || *app_name == '\0') {
if (!app_name || *app_name == '\0') {
app_name = "SDL Application";
}
}
/* App ID. Default to NULL if not available. */
// App ID. Default to NULL if not available.
app_id = SDL_GetHint(SDL_HINT_APP_ID);
stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
if (stream_name == NULL || *stream_name == '\0') {
if (!stream_name || *stream_name == '\0') {
stream_name = "Audio Stream";
}
@ -1090,24 +1090,24 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
* but 'Game' seems more appropriate for the majority of SDL applications.
*/
stream_role = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_ROLE);
if (stream_role == NULL || *stream_role == '\0') {
if (!stream_role || *stream_role == '\0') {
stream_role = "Game";
}
/* Initialize the Pipewire stream info from the SDL audio spec */
// Initialize the Pipewire stream info from the SDL audio spec
initialize_spa_info(&device->spec, &spa_info);
params = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &spa_info);
if (params == NULL) {
if (!params) {
return SDL_SetError("Pipewire: Failed to set audio format parameters");
}
priv = SDL_calloc(1, sizeof(struct SDL_PrivateAudioData));
device->hidden = priv;
if (priv == NULL) {
return SDL_OutOfMemory();
if (!priv) {
return -1;
}
/* Size of a single audio frame in bytes */
// Size of a single audio frame in bytes
priv->stride = SDL_AUDIO_FRAMESIZE(device->spec);
if (device->sample_frames < min_period) {
@ -1118,23 +1118,23 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
SDL_GetAudioThreadName(device, thread_name, sizeof(thread_name));
priv->loop = PIPEWIRE_pw_thread_loop_new(thread_name, NULL);
if (priv->loop == NULL) {
if (!priv->loop) {
return SDL_SetError("Pipewire: Failed to create stream loop (%i)", errno);
}
/* Load the realtime module so Pipewire can set the loop thread to the appropriate priority. */
// Load the realtime module so Pipewire can set the loop thread to the appropriate priority.
props = PIPEWIRE_pw_properties_new(PW_KEY_CONFIG_NAME, "client-rt.conf", NULL);
if (props == NULL) {
if (!props) {
return SDL_SetError("Pipewire: Failed to create stream context properties (%i)", errno);
}
priv->context = PIPEWIRE_pw_context_new(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), props, 0);
if (priv->context == NULL) {
if (!priv->context) {
return SDL_SetError("Pipewire: Failed to create stream context (%i)", errno);
}
props = PIPEWIRE_pw_properties_new(NULL, NULL);
if (props == NULL) {
if (!props) {
return SDL_SetError("Pipewire: Failed to create stream properties (%i)", errno);
}
@ -1142,7 +1142,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_CATEGORY, iscapture ? "Capture" : "Playback");
PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_ROLE, stream_role);
PIPEWIRE_pw_properties_set(props, PW_KEY_APP_NAME, app_name);
if (app_id != NULL) {
if (app_id) {
PIPEWIRE_pw_properties_set(props, PW_KEY_APP_ID, app_id);
}
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_NAME, stream_name);
@ -1164,7 +1164,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
node = io_list_get_by_id(node_id);
if (node != NULL) {
if (node) {
PIPEWIRE_pw_properties_set(props, PW_KEY_TARGET_OBJECT, node->path);
}
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
@ -1173,10 +1173,10 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
}
}
/* Create the new stream */
// Create the new stream
priv->stream = PIPEWIRE_pw_stream_new_simple(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), stream_name, props,
iscapture ? &stream_input_events : &stream_output_events, device);
if (priv->stream == NULL) {
if (!priv->stream) {
return SDL_SetError("Pipewire: Failed to create stream (%i)", errno);
}
@ -1191,7 +1191,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
return SDL_SetError("Pipewire: Failed to start stream loop");
}
/* Wait until all init flags are set or the stream has failed. */
// Wait until all init flags are set or the stream has failed.
PIPEWIRE_pw_thread_loop_lock(priv->loop);
while (priv->stream_init_status != PW_READY_FLAG_ALL_BITS &&
PIPEWIRE_pw_stream_get_state(priv->stream, NULL) != PW_STREAM_STATE_ERROR) {
@ -1234,10 +1234,16 @@ static void PIPEWIRE_CloseDevice(SDL_AudioDevice *device)
SDL_AudioThreadFinalize(device);
}
static void PIPEWIRE_Deinitialize(void)
static void PIPEWIRE_DeinitializeStart(void)
{
if (pipewire_initialized) {
hotplug_loop_destroy();
}
}
static void PIPEWIRE_Deinitialize(void)
{
if (pipewire_initialized) {
deinit_pipewire_library();
pipewire_initialized = SDL_FALSE;
}
@ -1258,9 +1264,9 @@ static SDL_bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl)
}
}
/* Set the function pointers */
impl->DetectDevices = PIPEWIRE_DetectDevices;
impl->OpenDevice = PIPEWIRE_OpenDevice;
impl->DeinitializeStart = PIPEWIRE_DeinitializeStart;
impl->Deinitialize = PIPEWIRE_Deinitialize;
impl->PlayDevice = PIPEWIRE_PlayDevice;
impl->GetDeviceBuf = PIPEWIRE_GetDeviceBuf;
@ -1276,4 +1282,4 @@ static SDL_bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl)
AudioBootStrap PIPEWIRE_bootstrap = { "pipewire", "Pipewire", PIPEWIRE_Init, SDL_FALSE };
#endif /* SDL_AUDIO_DRIVER_PIPEWIRE */
#endif // SDL_AUDIO_DRIVER_PIPEWIRE