audio: Added SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED
This fires if an opened device changes formats (which it can on Windows, if the user changes this in the system control panel, and WASAPI can report), or if a default device migrates to new hardware and the format doesn't match. This will fire for all logical devices on a physical device (and if it's a format change and not a default device change, it'll fire for the physical device too, but that's honestly not that useful and might change). Fixes #8267.
This commit is contained in:
@@ -187,6 +187,7 @@ typedef enum
|
|||||||
/* Audio hotplug events */
|
/* Audio hotplug events */
|
||||||
SDL_EVENT_AUDIO_DEVICE_ADDED = 0x1100, /**< A new audio device is available */
|
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_REMOVED, /**< An audio device has been removed. */
|
||||||
|
SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED, /**< An audio device's format has been changed by the system. */
|
||||||
|
|
||||||
/* Sensor events */
|
/* Sensor events */
|
||||||
SDL_EVENT_SENSOR_UPDATE = 0x1200, /**< A sensor was updated */
|
SDL_EVENT_SENSOR_UPDATE = 0x1200, /**< A sensor was updated */
|
||||||
@@ -491,9 +492,9 @@ typedef struct SDL_GamepadSensorEvent
|
|||||||
*/
|
*/
|
||||||
typedef struct SDL_AudioDeviceEvent
|
typedef struct SDL_AudioDeviceEvent
|
||||||
{
|
{
|
||||||
Uint32 type; /**< ::SDL_EVENT_AUDIO_DEVICE_ADDED, or ::SDL_EVENT_AUDIO_DEVICE_REMOVED */
|
Uint32 type; /**< ::SDL_EVENT_AUDIO_DEVICE_ADDED, or ::SDL_EVENT_AUDIO_DEVICE_REMOVED, or ::SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED */
|
||||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||||
SDL_AudioDeviceID which; /**< SDL_AudioDeviceID for the device being added or removed */
|
SDL_AudioDeviceID which; /**< SDL_AudioDeviceID for the device being added or removed or changing */
|
||||||
Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */
|
Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */
|
||||||
Uint8 padding1;
|
Uint8 padding1;
|
||||||
Uint8 padding2;
|
Uint8 padding2;
|
||||||
|
|||||||
@@ -1797,6 +1797,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device)
|
|||||||
SDL_AudioSpec spec;
|
SDL_AudioSpec spec;
|
||||||
SDL_bool needs_migration = SDL_FALSE;
|
SDL_bool needs_migration = SDL_FALSE;
|
||||||
SDL_zero(spec);
|
SDL_zero(spec);
|
||||||
|
|
||||||
for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev != NULL; logdev = logdev->next) {
|
for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev != NULL; logdev = logdev->next) {
|
||||||
if (logdev->opened_as_default) {
|
if (logdev->opened_as_default) {
|
||||||
needs_migration = SDL_TRUE;
|
needs_migration = SDL_TRUE;
|
||||||
@@ -1824,6 +1825,8 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needs_migration) {
|
if (needs_migration) {
|
||||||
|
const SDL_bool spec_changed = !AUDIO_SPECS_EQUAL(current_default_device->spec, new_default_device->spec);
|
||||||
|
const SDL_bool post_fmt_event = (spec_changed && SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED)) ? SDL_TRUE : SDL_FALSE;
|
||||||
SDL_LogicalAudioDevice *next = NULL;
|
SDL_LogicalAudioDevice *next = NULL;
|
||||||
for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev != NULL; logdev = next) {
|
for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev != NULL; logdev = next) {
|
||||||
next = logdev->next;
|
next = logdev->next;
|
||||||
@@ -1852,6 +1855,17 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device)
|
|||||||
logdev->prev = NULL;
|
logdev->prev = NULL;
|
||||||
logdev->next = new_default_device->logical_devices;
|
logdev->next = new_default_device->logical_devices;
|
||||||
new_default_device->logical_devices = logdev;
|
new_default_device->logical_devices = logdev;
|
||||||
|
|
||||||
|
// Post an event for each logical device we moved.
|
||||||
|
if (post_fmt_event) {
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_zero(event);
|
||||||
|
event.type = SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED;
|
||||||
|
event.common.timestamp = 0;
|
||||||
|
event.adevice.iscapture = iscapture ? 1 : 0;
|
||||||
|
event.adevice.which = logdev->instance_id;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_default_device->simple_copy = AudioDeviceCanUseSimpleCopy(current_default_device);
|
current_default_device->simple_copy = AudioDeviceCanUseSimpleCopy(current_default_device);
|
||||||
@@ -1883,7 +1897,10 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL
|
|||||||
const int orig_work_buffer_size = device->work_buffer_size;
|
const int orig_work_buffer_size = device->work_buffer_size;
|
||||||
const SDL_bool iscapture = device->iscapture;
|
const SDL_bool iscapture = device->iscapture;
|
||||||
|
|
||||||
if ((device->spec.format != newspec->format) || (device->spec.channels != newspec->channels) || (device->spec.freq != newspec->freq)) {
|
if (AUDIO_SPECS_EQUAL(device->spec, *newspec)) {
|
||||||
|
return 0; // we're already in that format.
|
||||||
|
}
|
||||||
|
|
||||||
SDL_memcpy(&device->spec, newspec, sizeof (*newspec));
|
SDL_memcpy(&device->spec, newspec, sizeof (*newspec));
|
||||||
for (SDL_LogicalAudioDevice *logdev = device->logical_devices; !kill_device && (logdev != NULL); logdev = logdev->next) {
|
for (SDL_LogicalAudioDevice *logdev = device->logical_devices; !kill_device && (logdev != NULL); logdev = logdev->next) {
|
||||||
for (SDL_AudioStream *stream = logdev->bound_streams; !kill_device && (stream != NULL); stream = stream->next_binding) {
|
for (SDL_AudioStream *stream = logdev->bound_streams; !kill_device && (stream != NULL); stream = stream->next_binding) {
|
||||||
@@ -1892,7 +1909,6 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!kill_device) {
|
if (!kill_device) {
|
||||||
device->sample_frames = new_sample_frames;
|
device->sample_frames = new_sample_frames;
|
||||||
@@ -1923,6 +1939,21 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Post an event for the physical device, and each logical device on this physical device.
|
||||||
|
if (!kill_device && SDL_EventEnabled(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED)) {
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_zero(event);
|
||||||
|
event.type = SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED;
|
||||||
|
event.common.timestamp = 0;
|
||||||
|
event.adevice.iscapture = device->iscapture ? 1 : 0;
|
||||||
|
event.adevice.which = device->instance_id;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) {
|
||||||
|
event.adevice.which = logdev->instance_id;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return kill_device ? -1 : 0;
|
return kill_device ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,6 @@
|
|||||||
#define SDL_INT_MAX ((int)(~0u>>1))
|
#define SDL_INT_MAX ((int)(~0u>>1))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define AUDIO_SPECS_EQUAL(x, y) (((x).format == (y).format) && ((x).channels == (y).channels) && ((x).freq == (y).freq))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CHANNEL LAYOUTS AS SDL EXPECTS THEM:
|
* CHANNEL LAYOUTS AS SDL EXPECTS THEM:
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ extern void (*SDL_Convert_F32_to_S32)(Sint32 *dst, const float *src, int num_sam
|
|||||||
#define DEFAULT_AUDIO_CAPTURE_CHANNELS 1
|
#define DEFAULT_AUDIO_CAPTURE_CHANNELS 1
|
||||||
#define DEFAULT_AUDIO_CAPTURE_FREQUENCY 44100
|
#define DEFAULT_AUDIO_CAPTURE_FREQUENCY 44100
|
||||||
|
|
||||||
|
#define AUDIO_SPECS_EQUAL(x, y) (((x).format == (y).format) && ((x).channels == (y).channels) && ((x).freq == (y).freq))
|
||||||
|
|
||||||
typedef struct SDL_AudioDevice SDL_AudioDevice;
|
typedef struct SDL_AudioDevice SDL_AudioDevice;
|
||||||
typedef struct SDL_LogicalAudioDevice SDL_LogicalAudioDevice;
|
typedef struct SDL_LogicalAudioDevice SDL_LogicalAudioDevice;
|
||||||
|
|
||||||
|
|||||||
@@ -440,6 +440,9 @@ static void SDL_LogEvent(const SDL_Event *event)
|
|||||||
SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_REMOVED)
|
SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_REMOVED)
|
||||||
PRINT_AUDIODEV_EVENT(event);
|
PRINT_AUDIODEV_EVENT(event);
|
||||||
break;
|
break;
|
||||||
|
SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED)
|
||||||
|
PRINT_AUDIODEV_EVENT(event);
|
||||||
|
break;
|
||||||
#undef PRINT_AUDIODEV_EVENT
|
#undef PRINT_AUDIODEV_EVENT
|
||||||
|
|
||||||
SDL_EVENT_CASE(SDL_EVENT_SENSOR_UPDATE)
|
SDL_EVENT_CASE(SDL_EVENT_SENSOR_UPDATE)
|
||||||
|
|||||||
Reference in New Issue
Block a user