mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-06-05 22:30:29 +00:00
Merge 6cba25187f into fa2a726cc3
This commit is contained in:
commit
1852f6eb92
10 changed files with 219 additions and 35 deletions
|
|
@ -759,6 +759,21 @@ extern SDL_DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(SDL_AudioDevic
|
|||
*/
|
||||
extern SDL_DECLSPEC bool SDLCALL SDL_IsAudioDevicePhysical(SDL_AudioDeviceID devid);
|
||||
|
||||
/**
|
||||
* Get the physical audio device associated with a logical audio device.
|
||||
*
|
||||
* If `devid` is already a physical device, this function returns `devid`.
|
||||
* If `devid` is an invalid device, it returns 0.
|
||||
*
|
||||
* \param devid the device ID to query.
|
||||
* \returns the physical device ID, or 0 on error.
|
||||
*
|
||||
* \threadsafety It is safe to call this function from any thread.
|
||||
*
|
||||
* \since This function is available since SDL 3.5.0.
|
||||
*/
|
||||
extern SDL_DECLSPEC SDL_AudioDeviceID SDLCALL SDL_GetPhysicalAudioDevice(SDL_AudioDeviceID devid);
|
||||
|
||||
/**
|
||||
* Determine if an audio device is a playback device (instead of recording).
|
||||
*
|
||||
|
|
@ -862,8 +877,8 @@ extern SDL_DECLSPEC bool SDLCALL SDL_AudioDevicePaused(SDL_AudioDeviceID devid);
|
|||
*
|
||||
* Audio devices default to a gain of 1.0f (no change in output).
|
||||
*
|
||||
* Physical devices may not have their gain changed, only logical devices, and
|
||||
* this function will always return -1.0f when used on physical devices.
|
||||
* Physical device gain support depends on the backend. -1.0f will be returned
|
||||
* if it is not supported.
|
||||
*
|
||||
* \param devid the audio device to query.
|
||||
* \returns the gain of the device or -1.0f on failure; call SDL_GetError()
|
||||
|
|
@ -885,18 +900,16 @@ extern SDL_DECLSPEC float SDLCALL SDL_GetAudioDeviceGain(SDL_AudioDeviceID devid
|
|||
*
|
||||
* Audio devices default to a gain of 1.0f (no change in output).
|
||||
*
|
||||
* Physical devices may not have their gain changed, only logical devices, and
|
||||
* this function will always return false when used on physical devices. While
|
||||
* it might seem attractive to adjust several logical devices at once in this
|
||||
* way, it would allow an app or library to interfere with another portion of
|
||||
* the program's otherwise-isolated devices.
|
||||
* Support for gain changes of physical devices depends on the backend. It will
|
||||
* return false if it is not supported; likely you should fall back to changing
|
||||
* the logical device gain in that case.
|
||||
*
|
||||
* This is applied, along with any per-audiostream gain, during playback to
|
||||
* the hardware, and can be continuously changed to create various effects. On
|
||||
* recording devices, this will adjust the gain before passing the data into
|
||||
* an audiostream; that recording audiostream can then adjust its gain further
|
||||
* when outputting the data elsewhere, if it likes, but that second gain is
|
||||
* not applied until the data leaves the audiostream again.
|
||||
* For logical devices this is applied, along with any per-audiostream gain,
|
||||
* during playback to the hardware, and can be continuously changed to create
|
||||
* various effects. On recording devices, this will adjust the gain before
|
||||
* passing the data into an audiostream; that recording audiostream can then
|
||||
* adjust its gain further when outputting the data elsewhere, if it likes, but
|
||||
* that second gain is not applied until the data leaves the audiostream again.
|
||||
*
|
||||
* \param devid the audio device on which to change gain.
|
||||
* \param gain the gain. 1.0f is no change, 0.0f is silence.
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ typedef enum SDL_EventType
|
|||
SDL_EVENT_AUDIO_DEVICE_ADDED = 0x1100, /**< A new audio device is available */
|
||||
SDL_EVENT_AUDIO_DEVICE_REMOVED, /**< An audio device has been removed. */
|
||||
SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED, /**< An audio device's format has been changed by the system. */
|
||||
SDL_EVENT_AUDIO_DEVICE_GAIN_CHANGED, /**< An audio device's gain has been changed by the system. */
|
||||
|
||||
/* Sensor events */
|
||||
SDL_EVENT_SENSOR_UPDATE = 0x1200, /**< A sensor was updated */
|
||||
|
|
@ -741,7 +742,7 @@ typedef struct SDL_GamepadCapSenseEvent
|
|||
*/
|
||||
typedef struct SDL_AudioDeviceEvent
|
||||
{
|
||||
SDL_EventType type; /**< SDL_EVENT_AUDIO_DEVICE_ADDED, or SDL_EVENT_AUDIO_DEVICE_REMOVED, or SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED */
|
||||
SDL_EventType type; /**< SDL_EVENT_AUDIO_DEVICE_ADDED, or SDL_EVENT_AUDIO_DEVICE_REMOVED, or SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED, or SDL_EVENT_AUDIO_DEVICE_GAIN_CHANGED */
|
||||
Uint32 reserved;
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
SDL_AudioDeviceID which; /**< SDL_AudioDeviceID for the device being added or removed or changing */
|
||||
|
|
|
|||
|
|
@ -538,6 +538,20 @@ static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceI
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SDL_AudioDeviceID SDL_GetPhysicalAudioDevice(SDL_AudioDeviceID devid)
|
||||
{
|
||||
if (SDL_IsAudioDevicePhysical(devid)) {
|
||||
return devid;
|
||||
}
|
||||
|
||||
SDL_AudioDeviceID result = 0;
|
||||
SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid);
|
||||
if (device) {
|
||||
result = device->instance_id;
|
||||
ReleaseAudioDevice(device);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// this assumes you hold the _physical_ device lock for this logical device! This will not unlock the lock or close the physical device!
|
||||
// It also will not unref the physical device, since we might be shutting down; SDL_CloseAudioDevice handles the unref.
|
||||
static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev)
|
||||
|
|
@ -820,6 +834,56 @@ static void SDLCALL SDL_AudioDeviceDisconnected_OnMainThread(void *userdata)
|
|||
UnrefPhysicalAudioDevice(device);
|
||||
}
|
||||
|
||||
|
||||
static void SDLCALL SDL_AudioDeviceGainChanged_OnMainThread(void *userdata)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
|
||||
SDL_assert(device != NULL);
|
||||
|
||||
SDL_PendingAudioDeviceEvent pending;
|
||||
pending.next = NULL;
|
||||
SDL_PendingAudioDeviceEvent *pending_tail = &pending;
|
||||
|
||||
ObtainPhysicalAudioDeviceObj(device);
|
||||
|
||||
const SDL_AudioDeviceID devid = device->instance_id;
|
||||
|
||||
if (!devid) {
|
||||
ReleaseAudioDevice(device);
|
||||
UnrefPhysicalAudioDevice(device);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_PendingAudioDeviceEvent *p = (SDL_PendingAudioDeviceEvent *)SDL_malloc(sizeof(SDL_PendingAudioDeviceEvent));
|
||||
if (p) {
|
||||
p->type = SDL_EVENT_AUDIO_DEVICE_GAIN_CHANGED;
|
||||
p->devid = devid;
|
||||
p->next = NULL;
|
||||
pending_tail->next = p;
|
||||
pending_tail = p;
|
||||
}
|
||||
|
||||
ReleaseAudioDevice(device);
|
||||
|
||||
if (pending.next) {
|
||||
SDL_LockRWLockForWriting(current_audio.subsystem_rwlock);
|
||||
SDL_PendingAudioDeviceEvent *tail = current_audio.pending_events_tail;
|
||||
SDL_assert(tail->next == NULL);
|
||||
tail->next = pending.next;
|
||||
current_audio.pending_events_tail = pending_tail;
|
||||
SDL_UnlockRWLock(current_audio.subsystem_rwlock);
|
||||
}
|
||||
UnrefPhysicalAudioDevice(device);
|
||||
}
|
||||
|
||||
void SDL_AudioDeviceGainChanged(SDL_AudioDevice *device)
|
||||
{
|
||||
if (device) {
|
||||
RefPhysicalAudioDevice(device);
|
||||
SDL_RunOnMainThread(SDL_AudioDeviceGainChanged_OnMainThread, device, false);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
|
||||
{
|
||||
// lots of risk of various audio backends deadlocking because they're calling
|
||||
|
|
@ -844,6 +908,8 @@ static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */
|
|||
static void SDL_AudioDeinitializeStart_Default(void) { /* no-op. */ }
|
||||
static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ }
|
||||
static void SDL_AudioFreeDeviceHandle_Default(SDL_AudioDevice *device) { /* no-op. */ }
|
||||
static bool SDL_AudioSetDeviceGain_Default(SDL_AudioDevice *device, float gain) { return false; /* no-op. */ }
|
||||
static float SDL_AudioGetDeviceGain_Default(SDL_AudioDevice *device) { return -1.0f; /* no-op. */ }
|
||||
|
||||
static void SDL_AudioThreadInit_Default(SDL_AudioDevice *device)
|
||||
{
|
||||
|
|
@ -897,6 +963,8 @@ static void CompleteAudioEntryPoints(void)
|
|||
FILL_STUB(FreeDeviceHandle);
|
||||
FILL_STUB(DeinitializeStart);
|
||||
FILL_STUB(Deinitialize);
|
||||
FILL_STUB(SetDeviceGain);
|
||||
FILL_STUB(GetDeviceGain);
|
||||
#undef FILL_STUB
|
||||
}
|
||||
|
||||
|
|
@ -1960,9 +2028,27 @@ bool SDL_AudioDevicePaused(SDL_AudioDeviceID devid)
|
|||
|
||||
float SDL_GetAudioDeviceGain(SDL_AudioDeviceID devid)
|
||||
{
|
||||
float result = -1.0f;
|
||||
SDL_AudioDevice *device = NULL;
|
||||
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
|
||||
const float result = logdev ? logdev->gain : -1.0f;
|
||||
|
||||
if (!SDL_IsAudioDeviceLogical(devid)) {
|
||||
if (!current_audio.impl.HasBackendVolumeControl) {
|
||||
return result;
|
||||
}
|
||||
device = ObtainPhysicalAudioDeviceDefaultAllowed(devid);
|
||||
if (!device) {
|
||||
return result;
|
||||
}
|
||||
float backend_gain = current_audio.impl.GetDeviceGain(device);
|
||||
if (backend_gain >= 0.0f) {
|
||||
result = backend_gain;
|
||||
}
|
||||
} else {
|
||||
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
|
||||
if (logdev) {
|
||||
result = logdev->gain;
|
||||
}
|
||||
}
|
||||
ReleaseAudioDevice(device);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1972,14 +2058,25 @@ bool SDL_SetAudioDeviceGain(SDL_AudioDeviceID devid, float gain)
|
|||
CHECK_PARAM(gain < 0.0f) {
|
||||
return SDL_InvalidParamError("gain");
|
||||
}
|
||||
|
||||
SDL_AudioDevice *device = NULL;
|
||||
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
|
||||
bool result = false;
|
||||
if (logdev) {
|
||||
logdev->gain = gain;
|
||||
UpdateAudioStreamFormatsPhysical(device);
|
||||
result = true;
|
||||
SDL_AudioDevice *device = NULL;
|
||||
|
||||
if (!SDL_IsAudioDeviceLogical(devid)) {
|
||||
if (!current_audio.impl.HasBackendVolumeControl) {
|
||||
return result;
|
||||
}
|
||||
device = ObtainPhysicalAudioDeviceDefaultAllowed(devid);
|
||||
if (!device) {
|
||||
return result;
|
||||
}
|
||||
result = current_audio.impl.SetDeviceGain(device, gain);
|
||||
} else {
|
||||
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
|
||||
if (logdev) {
|
||||
logdev->gain = gain;
|
||||
result = true;
|
||||
UpdateAudioStreamFormatsPhysical(device);
|
||||
}
|
||||
}
|
||||
ReleaseAudioDevice(device);
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ extern SDL_AudioDevice *SDL_AddAudioDevice(bool recording, const char *name, con
|
|||
This can happen due to i/o errors, or a device being unplugged, etc. */
|
||||
extern void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device);
|
||||
|
||||
// Backends can notify applications of physical device gain changes
|
||||
extern void SDL_AudioDeviceGainChanged(SDL_AudioDevice *device);
|
||||
|
||||
// Backends should call this if the system default device changes.
|
||||
extern void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device);
|
||||
|
||||
|
|
@ -162,12 +165,15 @@ typedef struct SDL_AudioDriverImpl
|
|||
void (*FreeDeviceHandle)(SDL_AudioDevice *device); // SDL is done with this device; free the handle from SDL_AddAudioDevice()
|
||||
void (*DeinitializeStart)(void); // SDL calls this, then starts destroying objects, then calls Deinitialize. This is a good place to stop hotplug detection.
|
||||
void (*Deinitialize)(void);
|
||||
bool (*SetDeviceGain)(SDL_AudioDevice *device, float gain); // Tell the backend that a device's gain has changed
|
||||
float (*GetDeviceGain)(SDL_AudioDevice *device); // Retrieve the current hardware/server gain
|
||||
|
||||
// Some flags to push duplicate code into the core and reduce #ifdefs.
|
||||
bool ProvidesOwnCallbackThread; // !!! FIXME: rename this, it's not a callback thread anymore.
|
||||
bool HasRecordingSupport;
|
||||
bool OnlyHasDefaultPlaybackDevice;
|
||||
bool OnlyHasDefaultRecordingDevice; // !!! FIXME: is there ever a time where you'd have a default playback and not a default recording (or vice versa)?
|
||||
bool HasBackendVolumeControl;
|
||||
} SDL_AudioDriverImpl;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <pipewire/extensions/metadata.h>
|
||||
#include <spa/param/audio/format-utils.h>
|
||||
#include <spa/param/props.h>
|
||||
#include <spa/utils/json.h>
|
||||
|
||||
/*
|
||||
|
|
@ -91,6 +92,8 @@ static struct pw_properties *(*PIPEWIRE_pw_properties_new)(const char *, ...)SPA
|
|||
static int (*PIPEWIRE_pw_properties_set)(struct pw_properties *, const char *, const char *);
|
||||
static int (*PIPEWIRE_pw_properties_setf)(struct pw_properties *, const char *, const char *, ...) SPA_PRINTF_FUNC(3, 4);
|
||||
static int (*PIPEWIRE_pw_stream_update_properties)(struct pw_stream *, const struct spa_dict *);
|
||||
static int (*PIPEWIRE_pw_stream_set_control)(struct pw_stream *, uint32_t, uint32_t, float *, ...);
|
||||
static const struct pw_stream_control *(*PIPEWIRE_pw_stream_get_control)(struct pw_stream *, uint32_t);
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC
|
||||
|
||||
|
|
@ -185,6 +188,8 @@ static bool load_pipewire_syms(void)
|
|||
SDL_PIPEWIRE_SYM(pw_properties_set);
|
||||
SDL_PIPEWIRE_SYM(pw_properties_setf);
|
||||
SDL_PIPEWIRE_SYM(pw_stream_update_properties);
|
||||
SDL_PIPEWIRE_SYM(pw_stream_set_control);
|
||||
SDL_PIPEWIRE_SYM(pw_stream_get_control);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -991,6 +996,13 @@ static Uint8 *PIPEWIRE_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const int maxsize = (int) spa_buf->datas[0].maxsize;
|
||||
if (maxsize < *buffer_size) {
|
||||
*buffer_size = maxsize;
|
||||
device->buffer_size = maxsize;
|
||||
device->sample_frames = maxsize / device->hidden->stride;
|
||||
}
|
||||
|
||||
device->hidden->pw_buf = pw_buf;
|
||||
return (Uint8 *) spa_buf->datas[0].data;
|
||||
}
|
||||
|
|
@ -1082,22 +1094,25 @@ static void input_callback(void *data)
|
|||
static void stream_add_buffer_callback(void *data, struct pw_buffer *buffer)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) data;
|
||||
|
||||
if (device->recording == false) {
|
||||
/* Clamp the output spec samples and size to the max size of the Pipewire buffer.
|
||||
If they exceed the maximum size of the Pipewire buffer, double buffering will be used. */
|
||||
if (device->buffer_size > buffer->buffer->datas[0].maxsize) {
|
||||
SDL_LockMutex(device->lock);
|
||||
device->sample_frames = buffer->buffer->datas[0].maxsize / device->hidden->stride;
|
||||
device->buffer_size = buffer->buffer->datas[0].maxsize;
|
||||
SDL_UnlockMutex(device->lock);
|
||||
}
|
||||
}
|
||||
|
||||
device->hidden->stream_init_status |= PW_READY_FLAG_BUFFER_ADDED;
|
||||
PIPEWIRE_pw_thread_loop_signal(device->hidden->loop, false);
|
||||
}
|
||||
|
||||
static void stream_control_info_callback(void *data, uint32_t id, const struct pw_stream_control *control)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) data;
|
||||
if (id == SPA_PROP_channelVolumes && control && control->n_values > 0 && control->values) {
|
||||
const float gain = control->values[0];
|
||||
const float old_gain = device->hidden->current_gain;
|
||||
if (old_gain != gain) {
|
||||
device->hidden->current_gain = gain;
|
||||
if (old_gain >= 0) {
|
||||
SDL_AudioDeviceGainChanged(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void stream_state_changed_callback(void *data, enum pw_stream_state old, enum pw_stream_state state, const char *error)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) data;
|
||||
|
|
@ -1113,10 +1128,12 @@ static void stream_state_changed_callback(void *data, enum pw_stream_state old,
|
|||
|
||||
static const struct pw_stream_events stream_output_events = { PW_VERSION_STREAM_EVENTS,
|
||||
.state_changed = stream_state_changed_callback,
|
||||
.control_info = stream_control_info_callback,
|
||||
.add_buffer = stream_add_buffer_callback,
|
||||
.process = output_callback };
|
||||
static const struct pw_stream_events stream_input_events = { PW_VERSION_STREAM_EVENTS,
|
||||
.state_changed = stream_state_changed_callback,
|
||||
.control_info = stream_control_info_callback,
|
||||
.add_buffer = stream_add_buffer_callback,
|
||||
.process = input_callback };
|
||||
|
||||
|
|
@ -1202,6 +1219,7 @@ static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
|
|||
}
|
||||
|
||||
priv = SDL_calloc(1, sizeof(struct SDL_PrivateAudioData));
|
||||
priv->current_gain = -1.0f;
|
||||
device->hidden = priv;
|
||||
if (!priv) {
|
||||
return false;
|
||||
|
|
@ -1355,6 +1373,46 @@ static void PIPEWIRE_Deinitialize(void)
|
|||
}
|
||||
}
|
||||
|
||||
static bool PIPEWIRE_SetDeviceGain(SDL_AudioDevice *device, float gain)
|
||||
{
|
||||
if (!device || !device->hidden || !device->hidden->stream || !device->hidden->loop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float values[SPA_AUDIO_MAX_CHANNELS];
|
||||
int channels = device->spec.channels;
|
||||
if (channels > SPA_AUDIO_MAX_CHANNELS) {
|
||||
channels = SPA_AUDIO_MAX_CHANNELS;
|
||||
}
|
||||
for (int i = 0; i < channels; i++) {
|
||||
values[i] = gain;
|
||||
}
|
||||
PIPEWIRE_pw_thread_loop_lock(device->hidden->loop);
|
||||
PIPEWIRE_pw_stream_set_control(device->hidden->stream, SPA_PROP_channelVolumes, channels, values, 0);
|
||||
PIPEWIRE_pw_thread_loop_unlock(device->hidden->loop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static float PIPEWIRE_GetDeviceGain(SDL_AudioDevice *device)
|
||||
{
|
||||
float gain = -1.0f;
|
||||
|
||||
if (!device || !device->hidden || !device->hidden->stream || !device->hidden->loop) {
|
||||
return gain;
|
||||
}
|
||||
|
||||
PIPEWIRE_pw_thread_loop_lock(device->hidden->loop);
|
||||
const struct pw_stream_control *control = PIPEWIRE_pw_stream_get_control(device->hidden->stream, SPA_PROP_channelVolumes);
|
||||
if (control && control->n_values > 0 && control->values) {
|
||||
gain = control->values[0];
|
||||
}
|
||||
PIPEWIRE_pw_thread_loop_unlock(device->hidden->loop);
|
||||
|
||||
return gain;
|
||||
}
|
||||
|
||||
|
||||
static bool PipewireInitialize(SDL_AudioDriverImpl *impl)
|
||||
{
|
||||
if (!pipewire_initialized) {
|
||||
|
|
@ -1379,9 +1437,12 @@ static bool PipewireInitialize(SDL_AudioDriverImpl *impl)
|
|||
impl->RecordDevice = PIPEWIRE_RecordDevice;
|
||||
impl->FlushRecording = PIPEWIRE_FlushRecording;
|
||||
impl->CloseDevice = PIPEWIRE_CloseDevice;
|
||||
impl->GetDeviceGain = PIPEWIRE_GetDeviceGain;
|
||||
|
||||
impl->HasRecordingSupport = true;
|
||||
impl->ProvidesOwnCallbackThread = true;
|
||||
impl->HasBackendVolumeControl = true;
|
||||
impl->SetDeviceGain = PIPEWIRE_SetDeviceGain;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ struct SDL_PrivateAudioData
|
|||
|
||||
// Set in GetDeviceBuf, filled in AudioThreadIterate, queued in PlayDevice
|
||||
struct pw_buffer *pw_buf;
|
||||
|
||||
float current_gain;
|
||||
};
|
||||
|
||||
#endif // SDL_pipewire_h_
|
||||
|
|
|
|||
|
|
@ -1290,3 +1290,4 @@ _SDL_LoadJPG
|
|||
_SDL_HasSVE2
|
||||
_SDL_GamepadHasCapSense
|
||||
_SDL_GetGamepadCapSense
|
||||
_SDL_GetPhysicalAudioDevice
|
||||
|
|
|
|||
|
|
@ -1291,6 +1291,7 @@ SDL3_0.0.0 {
|
|||
SDL_HasSVE2;
|
||||
SDL_GamepadHasCapSense;
|
||||
SDL_GetGamepadCapSense;
|
||||
SDL_GetPhysicalAudioDevice;
|
||||
# extra symbols go here (don't modify this line)
|
||||
local: *;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1317,3 +1317,4 @@
|
|||
#define SDL_HasSVE2 SDL_HasSVE2_REAL
|
||||
#define SDL_GamepadHasCapSense SDL_GamepadHasCapSense_REAL
|
||||
#define SDL_GetGamepadCapSense SDL_GetGamepadCapSense_REAL
|
||||
#define SDL_GetPhysicalAudioDevice SDL_GetPhysicalAudioDevice_REAL
|
||||
|
|
|
|||
|
|
@ -1325,3 +1325,4 @@ SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadJPG,(const char *a),(a),return)
|
|||
SDL_DYNAPI_PROC(bool,SDL_HasSVE2,(void),(),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_GamepadHasCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_GetGamepadCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_GetPhysicalAudioDevice,(SDL_AudioDeviceID a),(a),return)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue