Merge commit '852f2a6343518919e5ca8d3c1bbcab9f493e3cd8'
This commit is contained in:
113
external/sdl/SDL/src/SDL.c
vendored
113
external/sdl/SDL/src/SDL.c
vendored
@ -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
|
||||
@ -38,7 +38,8 @@
|
||||
|
||||
#include "SDL_assert_c.h"
|
||||
#include "SDL_log_c.h"
|
||||
#include "audio/SDL_audio_c.h"
|
||||
#include "SDL_properties_c.h"
|
||||
#include "audio/SDL_sysaudio.h"
|
||||
#include "video/SDL_video_c.h"
|
||||
#include "events/SDL_events_c.h"
|
||||
#include "haptic/SDL_haptic_c.h"
|
||||
@ -47,9 +48,7 @@
|
||||
#include "sensor/SDL_sensor_c.h"
|
||||
|
||||
/* Initialization/Cleanup routines */
|
||||
#ifndef SDL_TIMERS_DISABLED
|
||||
#include "timer/SDL_timer_c.h"
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
extern int SDL_HelperWindowCreate(void);
|
||||
extern int SDL_HelperWindowDestroy(void);
|
||||
@ -136,7 +135,7 @@ static SDL_bool SDL_ShouldInitSubsystem(Uint32 subsystem)
|
||||
{
|
||||
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
|
||||
return ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)) ? SDL_TRUE : SDL_FALSE;
|
||||
return ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0));
|
||||
}
|
||||
|
||||
/* Private helper to check if a system needs to be quit. */
|
||||
@ -150,7 +149,23 @@ static SDL_bool SDL_ShouldQuitSubsystem(Uint32 subsystem)
|
||||
/* If we're in SDL_Quit, we shut down every subsystem, even if refcount
|
||||
* isn't zero.
|
||||
*/
|
||||
return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit) ? SDL_TRUE : SDL_FALSE;
|
||||
return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit);
|
||||
}
|
||||
|
||||
/* Private helper to either increment's existing ref counter,
|
||||
* or fully init a new subsystem. */
|
||||
static SDL_bool SDL_InitOrIncrementSubsystem(Uint32 subsystem)
|
||||
{
|
||||
int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
|
||||
if (subsystem_index < 0) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
if (SDL_SubsystemRefCount[subsystem_index] > 0) {
|
||||
++SDL_SubsystemRefCount[subsystem_index];
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_InitSubSystem(subsystem) == 0;
|
||||
}
|
||||
|
||||
void SDL_SetMainReady(void)
|
||||
@ -167,6 +182,8 @@ int SDL_InitSubSystem(Uint32 flags)
|
||||
}
|
||||
|
||||
SDL_InitLog();
|
||||
SDL_InitProperties();
|
||||
SDL_GetGlobalProperties();
|
||||
|
||||
/* Clear the error message */
|
||||
SDL_ClearError();
|
||||
@ -175,16 +192,6 @@ int SDL_InitSubSystem(Uint32 flags)
|
||||
SDL_DBus_Init();
|
||||
#endif
|
||||
|
||||
if (flags & SDL_INIT_GAMEPAD) {
|
||||
/* game controller implies joystick */
|
||||
flags |= SDL_INIT_JOYSTICK;
|
||||
}
|
||||
|
||||
if (flags & (SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO)) {
|
||||
/* video or joystick or audio implies events */
|
||||
flags |= SDL_INIT_EVENTS;
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) {
|
||||
if (SDL_HelperWindowCreate() < 0) {
|
||||
@ -193,9 +200,7 @@ int SDL_InitSubSystem(Uint32 flags)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SDL_TIMERS_DISABLED
|
||||
SDL_InitTicks();
|
||||
#endif
|
||||
|
||||
/* Initialize the event subsystem */
|
||||
if (flags & SDL_INIT_EVENTS) {
|
||||
@ -218,7 +223,6 @@ int SDL_InitSubSystem(Uint32 flags)
|
||||
|
||||
/* Initialize the timer subsystem */
|
||||
if (flags & SDL_INIT_TIMER) {
|
||||
#if !defined(SDL_TIMERS_DISABLED) && !defined(SDL_TIMER_DUMMY)
|
||||
if (SDL_ShouldInitSubsystem(SDL_INIT_TIMER)) {
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_TIMER);
|
||||
if (SDL_InitTimers() < 0) {
|
||||
@ -229,16 +233,17 @@ int SDL_InitSubSystem(Uint32 flags)
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_TIMER);
|
||||
}
|
||||
flags_initialized |= SDL_INIT_TIMER;
|
||||
#else
|
||||
SDL_SetError("SDL not built with timer support");
|
||||
goto quit_and_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Initialize the video subsystem */
|
||||
if (flags & SDL_INIT_VIDEO) {
|
||||
#ifndef SDL_VIDEO_DISABLED
|
||||
if (SDL_ShouldInitSubsystem(SDL_INIT_VIDEO)) {
|
||||
/* video implies events */
|
||||
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
|
||||
goto quit_and_error;
|
||||
}
|
||||
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO);
|
||||
if (SDL_VideoInit(NULL) < 0) {
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
|
||||
@ -258,6 +263,11 @@ int SDL_InitSubSystem(Uint32 flags)
|
||||
if (flags & SDL_INIT_AUDIO) {
|
||||
#ifndef SDL_AUDIO_DISABLED
|
||||
if (SDL_ShouldInitSubsystem(SDL_INIT_AUDIO)) {
|
||||
/* audio implies events */
|
||||
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
|
||||
goto quit_and_error;
|
||||
}
|
||||
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO);
|
||||
if (SDL_InitAudio(NULL) < 0) {
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
|
||||
@ -277,6 +287,11 @@ int SDL_InitSubSystem(Uint32 flags)
|
||||
if (flags & SDL_INIT_JOYSTICK) {
|
||||
#ifndef SDL_JOYSTICK_DISABLED
|
||||
if (SDL_ShouldInitSubsystem(SDL_INIT_JOYSTICK)) {
|
||||
/* joystick implies events */
|
||||
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) {
|
||||
goto quit_and_error;
|
||||
}
|
||||
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK);
|
||||
if (SDL_InitJoysticks() < 0) {
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
|
||||
@ -295,6 +310,11 @@ int SDL_InitSubSystem(Uint32 flags)
|
||||
if (flags & SDL_INIT_GAMEPAD) {
|
||||
#ifndef SDL_JOYSTICK_DISABLED
|
||||
if (SDL_ShouldInitSubsystem(SDL_INIT_GAMEPAD)) {
|
||||
/* game controller implies joystick */
|
||||
if (!SDL_InitOrIncrementSubsystem(SDL_INIT_JOYSTICK)) {
|
||||
goto quit_and_error;
|
||||
}
|
||||
|
||||
SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD);
|
||||
if (SDL_InitGamepads() < 0) {
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
|
||||
@ -376,21 +396,19 @@ void SDL_QuitSubSystem(Uint32 flags)
|
||||
|
||||
#ifndef SDL_JOYSTICK_DISABLED
|
||||
if (flags & SDL_INIT_GAMEPAD) {
|
||||
/* game controller implies joystick */
|
||||
flags |= SDL_INIT_JOYSTICK;
|
||||
|
||||
if (SDL_ShouldQuitSubsystem(SDL_INIT_GAMEPAD)) {
|
||||
SDL_QuitGamepads();
|
||||
/* game controller implies joystick */
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
}
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD);
|
||||
}
|
||||
|
||||
if (flags & SDL_INIT_JOYSTICK) {
|
||||
/* joystick implies events */
|
||||
flags |= SDL_INIT_EVENTS;
|
||||
|
||||
if (SDL_ShouldQuitSubsystem(SDL_INIT_JOYSTICK)) {
|
||||
SDL_QuitJoysticks();
|
||||
/* joystick implies events */
|
||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||
}
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK);
|
||||
}
|
||||
@ -407,11 +425,10 @@ void SDL_QuitSubSystem(Uint32 flags)
|
||||
|
||||
#ifndef SDL_AUDIO_DISABLED
|
||||
if (flags & SDL_INIT_AUDIO) {
|
||||
/* audio implies events */
|
||||
flags |= SDL_INIT_EVENTS;
|
||||
|
||||
if (SDL_ShouldQuitSubsystem(SDL_INIT_AUDIO)) {
|
||||
SDL_QuitAudio();
|
||||
/* audio implies events */
|
||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||
}
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO);
|
||||
}
|
||||
@ -419,24 +436,21 @@ void SDL_QuitSubSystem(Uint32 flags)
|
||||
|
||||
#ifndef SDL_VIDEO_DISABLED
|
||||
if (flags & SDL_INIT_VIDEO) {
|
||||
/* video implies events */
|
||||
flags |= SDL_INIT_EVENTS;
|
||||
|
||||
if (SDL_ShouldQuitSubsystem(SDL_INIT_VIDEO)) {
|
||||
SDL_VideoQuit();
|
||||
/* video implies events */
|
||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||
}
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(SDL_TIMERS_DISABLED) && !defined(SDL_TIMER_DUMMY)
|
||||
if (flags & SDL_INIT_TIMER) {
|
||||
if (SDL_ShouldQuitSubsystem(SDL_INIT_TIMER)) {
|
||||
SDL_QuitTimers();
|
||||
}
|
||||
SDL_DecrementSubsystemRefCount(SDL_INIT_TIMER);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SDL_EVENTS_DISABLED
|
||||
if (flags & SDL_INIT_EVENTS) {
|
||||
@ -488,17 +502,16 @@ void SDL_Quit(void)
|
||||
#endif
|
||||
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
|
||||
|
||||
#ifndef SDL_TIMERS_DISABLED
|
||||
SDL_QuitTicks();
|
||||
#endif
|
||||
|
||||
SDL_ClearHints();
|
||||
SDL_AssertionsQuit();
|
||||
|
||||
#ifdef SDL_USE_LIBDBUS
|
||||
SDL_DBus_Quit();
|
||||
#endif
|
||||
|
||||
SDL_ClearHints();
|
||||
SDL_AssertionsQuit();
|
||||
|
||||
SDL_QuitProperties();
|
||||
SDL_QuitLog();
|
||||
|
||||
/* Now that every subsystem has been quit, we reset the subsystem refcount
|
||||
@ -511,13 +524,27 @@ void SDL_Quit(void)
|
||||
SDL_bInMainQuit = SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Assume we can wrap SDL_AtomicInt values and cast to Uint32 */
|
||||
SDL_COMPILE_TIME_ASSERT(sizeof_object_id, sizeof(int) == sizeof(Uint32));
|
||||
|
||||
Uint32 SDL_GetNextObjectID(void)
|
||||
{
|
||||
static SDL_AtomicInt last_id;
|
||||
|
||||
Uint32 id = (Uint32)SDL_AtomicIncRef(&last_id) + 1;
|
||||
if (id == 0) {
|
||||
id = (Uint32)SDL_AtomicIncRef(&last_id) + 1;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/* Get the library version number */
|
||||
int SDL_GetVersion(SDL_version *ver)
|
||||
{
|
||||
static SDL_bool check_hint = SDL_TRUE;
|
||||
static SDL_bool legacy_version = SDL_FALSE;
|
||||
|
||||
if (ver == NULL) {
|
||||
if (!ver) {
|
||||
return SDL_InvalidParamError("ver");
|
||||
}
|
||||
|
||||
|
18
external/sdl/SDL/src/SDL_assert.c
vendored
18
external/sdl/SDL/src/SDL_assert.c
vendored
@ -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
|
||||
@ -106,11 +106,11 @@ static void SDL_GenerateAssertionReport(void)
|
||||
const SDL_AssertData *item = triggered_assertions;
|
||||
|
||||
/* only do this if the app hasn't assigned an assertion handler. */
|
||||
if ((item != NULL) && (assertion_handler != SDL_PromptAssertion)) {
|
||||
if ((item) && (assertion_handler != SDL_PromptAssertion)) {
|
||||
debug_print("\n\nSDL assertion report.\n");
|
||||
debug_print("All SDL assertions between last init/quit:\n\n");
|
||||
|
||||
while (item != NULL) {
|
||||
while (item) {
|
||||
debug_print(
|
||||
"'%s'\n"
|
||||
" * %s (%s:%d)\n"
|
||||
@ -198,7 +198,7 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v
|
||||
|
||||
/* let env. variable override, so unit tests won't block in a GUI. */
|
||||
envr = SDL_getenv("SDL_ASSERT");
|
||||
if (envr != NULL) {
|
||||
if (envr) {
|
||||
if (message != stack_buf) {
|
||||
SDL_free(message);
|
||||
}
|
||||
@ -334,9 +334,9 @@ SDL_AssertState SDL_ReportAssertion(SDL_AssertData *data, const char *func, cons
|
||||
#ifndef SDL_THREADS_DISABLED
|
||||
static SDL_SpinLock spinlock = 0;
|
||||
SDL_AtomicLock(&spinlock);
|
||||
if (assertion_mutex == NULL) { /* never called SDL_Init()? */
|
||||
if (!assertion_mutex) { /* never called SDL_Init()? */
|
||||
assertion_mutex = SDL_CreateMutex();
|
||||
if (assertion_mutex == NULL) {
|
||||
if (!assertion_mutex) {
|
||||
SDL_AtomicUnlock(&spinlock);
|
||||
return SDL_ASSERTION_IGNORE; /* oh well, I guess. */
|
||||
}
|
||||
@ -401,7 +401,7 @@ void SDL_AssertionsQuit(void)
|
||||
#if SDL_ASSERT_LEVEL > 0
|
||||
SDL_GenerateAssertionReport();
|
||||
#ifndef SDL_THREADS_DISABLED
|
||||
if (assertion_mutex != NULL) {
|
||||
if (assertion_mutex) {
|
||||
SDL_DestroyMutex(assertion_mutex);
|
||||
assertion_mutex = NULL;
|
||||
}
|
||||
@ -429,7 +429,7 @@ void SDL_ResetAssertionReport(void)
|
||||
{
|
||||
SDL_AssertData *next = NULL;
|
||||
SDL_AssertData *item;
|
||||
for (item = triggered_assertions; item != NULL; item = next) {
|
||||
for (item = triggered_assertions; item; item = next) {
|
||||
next = (SDL_AssertData *)item->next;
|
||||
item->always_ignore = SDL_FALSE;
|
||||
item->trigger_count = 0;
|
||||
@ -446,7 +446,7 @@ SDL_AssertionHandler SDL_GetDefaultAssertionHandler(void)
|
||||
|
||||
SDL_AssertionHandler SDL_GetAssertionHandler(void **userdata)
|
||||
{
|
||||
if (userdata != NULL) {
|
||||
if (userdata) {
|
||||
*userdata = assertion_userdata;
|
||||
}
|
||||
return assertion_handler;
|
||||
|
2
external/sdl/SDL/src/SDL_assert_c.h
vendored
2
external/sdl/SDL/src/SDL_assert_c.h
vendored
@ -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
|
||||
|
46
external/sdl/SDL/src/SDL_error.c
vendored
46
external/sdl/SDL/src/SDL_error.c
vendored
@ -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
|
||||
@ -27,12 +27,12 @@
|
||||
int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
/* Ignore call if invalid format pointer was passed */
|
||||
if (fmt != NULL) {
|
||||
if (fmt) {
|
||||
va_list ap;
|
||||
int result;
|
||||
SDL_error *error = SDL_GetErrBuf();
|
||||
SDL_error *error = SDL_GetErrBuf(SDL_TRUE);
|
||||
|
||||
error->error = 1; /* mark error as valid */
|
||||
error->error = SDL_ErrorCodeGeneric;
|
||||
|
||||
va_start(ap, fmt);
|
||||
result = SDL_vsnprintf(error->str, error->len, fmt, ap);
|
||||
@ -62,13 +62,29 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
/* Available for backwards compatibility */
|
||||
const char *SDL_GetError(void)
|
||||
{
|
||||
const SDL_error *error = SDL_GetErrBuf();
|
||||
return error->error ? error->str : "";
|
||||
const SDL_error *error = SDL_GetErrBuf(SDL_FALSE);
|
||||
|
||||
if (!error) {
|
||||
return "";
|
||||
}
|
||||
|
||||
switch (error->error) {
|
||||
case SDL_ErrorCodeGeneric:
|
||||
return error->str;
|
||||
case SDL_ErrorCodeOutOfMemory:
|
||||
return "Out of memory";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_ClearError(void)
|
||||
{
|
||||
SDL_GetErrBuf()->error = 0;
|
||||
SDL_error *error = SDL_GetErrBuf(SDL_FALSE);
|
||||
|
||||
if (error) {
|
||||
error->error = SDL_ErrorCodeNone;
|
||||
}
|
||||
}
|
||||
|
||||
/* Very common errors go here */
|
||||
@ -76,7 +92,8 @@ int SDL_Error(SDL_errorcode code)
|
||||
{
|
||||
switch (code) {
|
||||
case SDL_ENOMEM:
|
||||
return SDL_SetError("Out of memory");
|
||||
SDL_GetErrBuf(SDL_TRUE)->error = SDL_ErrorCodeOutOfMemory;
|
||||
return -1;
|
||||
case SDL_EFREAD:
|
||||
return SDL_SetError("Error reading from datastream");
|
||||
case SDL_EFWRITE:
|
||||
@ -89,16 +106,3 @@ int SDL_Error(SDL_errorcode code)
|
||||
return SDL_SetError("Unknown SDL error");
|
||||
}
|
||||
}
|
||||
|
||||
char *SDL_GetErrorMsg(char *errstr, int maxlen)
|
||||
{
|
||||
const SDL_error *error = SDL_GetErrBuf();
|
||||
|
||||
if (error->error) {
|
||||
SDL_strlcpy(errstr, error->str, maxlen);
|
||||
} else {
|
||||
*errstr = '\0';
|
||||
}
|
||||
|
||||
return errstr;
|
||||
}
|
||||
|
13
external/sdl/SDL/src/SDL_error_c.h
vendored
13
external/sdl/SDL/src/SDL_error_c.h
vendored
@ -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
|
||||
@ -27,9 +27,16 @@
|
||||
#ifndef SDL_error_c_h_
|
||||
#define SDL_error_c_h_
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_ErrorCodeNone,
|
||||
SDL_ErrorCodeGeneric,
|
||||
SDL_ErrorCodeOutOfMemory,
|
||||
} SDL_ErrorCode;
|
||||
|
||||
typedef struct SDL_error
|
||||
{
|
||||
int error; /* This is a numeric value corresponding to the current error */
|
||||
SDL_ErrorCode error;
|
||||
char *str;
|
||||
size_t len;
|
||||
SDL_realloc_func realloc_func;
|
||||
@ -37,6 +44,6 @@ typedef struct SDL_error
|
||||
} SDL_error;
|
||||
|
||||
/* Defined in SDL_thread.c */
|
||||
extern SDL_error *SDL_GetErrBuf(void);
|
||||
extern SDL_error *SDL_GetErrBuf(SDL_bool create);
|
||||
|
||||
#endif /* SDL_error_c_h_ */
|
||||
|
4
external/sdl/SDL/src/SDL_guid.c
vendored
4
external/sdl/SDL/src/SDL_guid.c
vendored
@ -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
|
||||
@ -26,7 +26,7 @@ int SDL_GUIDToString(SDL_GUID guid, char *pszGUID, int cbGUID)
|
||||
static const char k_rgchHexToASCII[] = "0123456789abcdef";
|
||||
int i;
|
||||
|
||||
if (pszGUID == NULL) {
|
||||
if (!pszGUID) {
|
||||
return SDL_InvalidParamError("pszGUID");
|
||||
}
|
||||
if (cbGUID <= 0) {
|
||||
|
273
external/sdl/SDL/src/SDL_hashtable.c
vendored
Normal file
273
external/sdl/SDL/src/SDL_hashtable.c
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
#include "SDL_hashtable.h"
|
||||
|
||||
typedef struct SDL_HashItem
|
||||
{
|
||||
const void *key;
|
||||
const void *value;
|
||||
struct SDL_HashItem *next;
|
||||
} SDL_HashItem;
|
||||
|
||||
struct SDL_HashTable
|
||||
{
|
||||
SDL_HashItem **table;
|
||||
Uint32 table_len;
|
||||
SDL_bool stackable;
|
||||
void *data;
|
||||
SDL_HashTable_HashFn hash;
|
||||
SDL_HashTable_KeyMatchFn keymatch;
|
||||
SDL_HashTable_NukeFn nuke;
|
||||
};
|
||||
|
||||
SDL_HashTable *SDL_CreateHashTable(void *data, const Uint32 num_buckets, const SDL_HashTable_HashFn hashfn,
|
||||
const SDL_HashTable_KeyMatchFn keymatchfn,
|
||||
const SDL_HashTable_NukeFn nukefn,
|
||||
const SDL_bool stackable)
|
||||
{
|
||||
SDL_HashTable *table;
|
||||
|
||||
// num_buckets must be a power of two so we get a solid block of bits to mask hash values against.
|
||||
if ((num_buckets == 0) || ((num_buckets & (num_buckets - 1)) != 0)) {
|
||||
SDL_SetError("num_buckets must be a power of two");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table = (SDL_HashTable *) SDL_calloc(1, sizeof (SDL_HashTable));
|
||||
if (!table) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table->table = (SDL_HashItem **) SDL_calloc(num_buckets, sizeof (SDL_HashItem *));
|
||||
if (!table->table) {
|
||||
SDL_free(table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table->table_len = num_buckets;
|
||||
table->stackable = stackable;
|
||||
table->data = data;
|
||||
table->hash = hashfn;
|
||||
table->keymatch = keymatchfn;
|
||||
table->nuke = nukefn;
|
||||
return table;
|
||||
}
|
||||
|
||||
static SDL_INLINE Uint32 calc_hash(const SDL_HashTable *table, const void *key)
|
||||
{
|
||||
return table->hash(key, table->data) & (table->table_len - 1);
|
||||
}
|
||||
|
||||
|
||||
SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value)
|
||||
{
|
||||
SDL_HashItem *item;
|
||||
const Uint32 hash = calc_hash(table, key);
|
||||
|
||||
if ( (!table->stackable) && (SDL_FindInHashTable(table, key, NULL)) ) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
// !!! FIXME: grow and rehash table if it gets too saturated.
|
||||
item = (SDL_HashItem *) SDL_malloc(sizeof (SDL_HashItem));
|
||||
if (!item) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
item->key = key;
|
||||
item->value = value;
|
||||
item->next = table->table[hash];
|
||||
table->table[hash] = item;
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value)
|
||||
{
|
||||
const Uint32 hash = calc_hash(table, key);
|
||||
void *data = table->data;
|
||||
SDL_HashItem *i;
|
||||
|
||||
for (i = table->table[hash]; i; i = i->next) {
|
||||
if (table->keymatch(key, i->key, data)) {
|
||||
if (_value) {
|
||||
*_value = i->value;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key)
|
||||
{
|
||||
const Uint32 hash = calc_hash(table, key);
|
||||
SDL_HashItem *item = NULL;
|
||||
SDL_HashItem *prev = NULL;
|
||||
void *data = table->data;
|
||||
|
||||
for (item = table->table[hash]; item; item = item->next) {
|
||||
if (table->keymatch(key, item->key, data)) {
|
||||
if (prev) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
table->table[hash] = item->next;
|
||||
}
|
||||
|
||||
table->nuke(item->key, item->value, data);
|
||||
SDL_free(item);
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
prev = item;
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, const void **_value, void **iter)
|
||||
{
|
||||
SDL_HashItem *item = *iter ? ((SDL_HashItem *) *iter)->next : table->table[calc_hash(table, key)];
|
||||
|
||||
while (item) {
|
||||
if (table->keymatch(key, item->key, table->data)) {
|
||||
*_value = item->value;
|
||||
*iter = item;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
// no more matches.
|
||||
*_value = NULL;
|
||||
*iter = NULL;
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, const void **_value, void **iter)
|
||||
{
|
||||
SDL_HashItem *item = (SDL_HashItem *) *iter;
|
||||
Uint32 idx = 0;
|
||||
|
||||
if (item) {
|
||||
const SDL_HashItem *orig = item;
|
||||
item = item->next;
|
||||
if (!item) {
|
||||
idx = calc_hash(table, orig->key) + 1; // !!! FIXME: we probably shouldn't rehash each time.
|
||||
}
|
||||
}
|
||||
|
||||
while (!item && (idx < table->table_len)) {
|
||||
item = table->table[idx++]; // skip empty buckets...
|
||||
}
|
||||
|
||||
if (!item) { // no more matches?
|
||||
*_key = NULL;
|
||||
*iter = NULL;
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
*_key = item->key;
|
||||
*_value = item->value;
|
||||
*iter = item;
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_HashTableEmpty(SDL_HashTable *table)
|
||||
{
|
||||
if (table) {
|
||||
Uint32 i;
|
||||
|
||||
for (i = 0; i < table->table_len; i++) {
|
||||
SDL_HashItem *item = table->table[i];
|
||||
if (item) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void SDL_DestroyHashTable(SDL_HashTable *table)
|
||||
{
|
||||
if (table) {
|
||||
void *data = table->data;
|
||||
Uint32 i;
|
||||
|
||||
for (i = 0; i < table->table_len; i++) {
|
||||
SDL_HashItem *item = table->table[i];
|
||||
while (item) {
|
||||
SDL_HashItem *next = item->next;
|
||||
table->nuke(item->key, item->value, data);
|
||||
SDL_free(item);
|
||||
item = next;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(table->table);
|
||||
SDL_free(table);
|
||||
}
|
||||
}
|
||||
|
||||
// this is djb's xor hashing function.
|
||||
static SDL_INLINE Uint32 hash_string_djbxor(const char *str, size_t len)
|
||||
{
|
||||
Uint32 hash = 5381;
|
||||
while (len--) {
|
||||
hash = ((hash << 5) + hash) ^ *(str++);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
Uint32 SDL_HashString(const void *key, void *data)
|
||||
{
|
||||
const char *str = (const char *)key;
|
||||
return hash_string_djbxor(str, SDL_strlen(str));
|
||||
}
|
||||
|
||||
SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *data)
|
||||
{
|
||||
if (a == b) {
|
||||
return SDL_TRUE; // same pointer, must match.
|
||||
} else if (!a || !b) {
|
||||
return SDL_FALSE; // one pointer is NULL (and first test shows they aren't the same pointer), must not match.
|
||||
}
|
||||
return (SDL_strcmp((const char *)a, (const char *)b) == 0); // Check against actual string contents.
|
||||
}
|
||||
|
||||
// We assume we can fit the ID in the key directly
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_HashID_KeySize, sizeof(Uint32) <= sizeof(const void *));
|
||||
|
||||
Uint32 SDL_HashID(const void *key, void *unused)
|
||||
{
|
||||
return (Uint32)(uintptr_t)key;
|
||||
}
|
||||
|
||||
SDL_bool SDL_KeyMatchID(const void *a, const void *b, void *unused)
|
||||
{
|
||||
if (a == b) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
57
external/sdl/SDL/src/SDL_hashtable.h
vendored
Normal file
57
external/sdl/SDL/src/SDL_hashtable.h
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#ifndef SDL_hashtable_h_
|
||||
#define SDL_hashtable_h_
|
||||
|
||||
/* this is not (currently) a public API. But maybe it should be! */
|
||||
|
||||
struct SDL_HashTable;
|
||||
typedef struct SDL_HashTable SDL_HashTable;
|
||||
typedef Uint32 (*SDL_HashTable_HashFn)(const void *key, void *data);
|
||||
typedef SDL_bool (*SDL_HashTable_KeyMatchFn)(const void *a, const void *b, void *data);
|
||||
typedef void (*SDL_HashTable_NukeFn)(const void *key, const void *value, void *data);
|
||||
|
||||
SDL_HashTable *SDL_CreateHashTable(void *data,
|
||||
const Uint32 num_buckets,
|
||||
const SDL_HashTable_HashFn hashfn,
|
||||
const SDL_HashTable_KeyMatchFn keymatchfn,
|
||||
const SDL_HashTable_NukeFn nukefn,
|
||||
const SDL_bool stackable);
|
||||
|
||||
void SDL_DestroyHashTable(SDL_HashTable *table);
|
||||
SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value);
|
||||
SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key);
|
||||
SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value);
|
||||
SDL_bool SDL_HashTableEmpty(SDL_HashTable *table);
|
||||
|
||||
// iterate all values for a specific key. This only makes sense if the hash is stackable. If not-stackable, just use SDL_FindInHashTable().
|
||||
SDL_bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, const void **_value, void **iter);
|
||||
|
||||
// iterate all key/value pairs in a hash (stackable hashes can have duplicate keys with multiple values).
|
||||
SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, const void **_value, void **iter);
|
||||
|
||||
Uint32 SDL_HashString(const void *key, void *unused);
|
||||
SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *unused);
|
||||
|
||||
Uint32 SDL_HashID(const void *key, void *unused);
|
||||
SDL_bool SDL_KeyMatchID(const void *a, const void *b, void *unused);
|
||||
|
||||
#endif /* SDL_hashtable_h_ */
|
42
external/sdl/SDL/src/SDL_hints.c
vendored
42
external/sdl/SDL/src/SDL_hints.c
vendored
@ -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
|
||||
@ -49,7 +49,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr
|
||||
SDL_Hint *hint;
|
||||
SDL_HintWatch *entry;
|
||||
|
||||
if (name == NULL) {
|
||||
if (!name) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr
|
||||
return SDL_FALSE;
|
||||
}
|
||||
if (hint->value != value &&
|
||||
(value == NULL || !hint->value || SDL_strcmp(hint->value, value) != 0)) {
|
||||
(!value || !hint->value || SDL_strcmp(hint->value, value) != 0)) {
|
||||
char *old_value = hint->value;
|
||||
|
||||
hint->value = value ? SDL_strdup(value) : NULL;
|
||||
@ -85,7 +85,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr
|
||||
|
||||
/* Couldn't find the hint, add a new one */
|
||||
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
|
||||
if (hint == NULL) {
|
||||
if (!hint) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
hint->name = SDL_strdup(name);
|
||||
@ -103,16 +103,16 @@ SDL_bool SDL_ResetHint(const char *name)
|
||||
SDL_Hint *hint;
|
||||
SDL_HintWatch *entry;
|
||||
|
||||
if (name == NULL) {
|
||||
if (!name) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
env = SDL_getenv(name);
|
||||
for (hint = SDL_hints; hint; hint = hint->next) {
|
||||
if (SDL_strcmp(name, hint->name) == 0) {
|
||||
if ((env == NULL && hint->value != NULL) ||
|
||||
(env != NULL && hint->value == NULL) ||
|
||||
(env != NULL && SDL_strcmp(env, hint->value) != 0)) {
|
||||
if ((!env && hint->value) ||
|
||||
(env && !hint->value) ||
|
||||
(env && SDL_strcmp(env, hint->value) != 0)) {
|
||||
for (entry = hint->callbacks; entry;) {
|
||||
/* Save the next entry in case this one is deleted */
|
||||
SDL_HintWatch *next = entry->next;
|
||||
@ -137,9 +137,9 @@ void SDL_ResetHints(void)
|
||||
|
||||
for (hint = SDL_hints; hint; hint = hint->next) {
|
||||
env = SDL_getenv(hint->name);
|
||||
if ((env == NULL && hint->value != NULL) ||
|
||||
(env != NULL && hint->value == NULL) ||
|
||||
(env != NULL && SDL_strcmp(env, hint->value) != 0)) {
|
||||
if ((!env && hint->value) ||
|
||||
(env && !hint->value) ||
|
||||
(env && SDL_strcmp(env, hint->value) != 0)) {
|
||||
for (entry = hint->callbacks; entry;) {
|
||||
/* Save the next entry in case this one is deleted */
|
||||
SDL_HintWatch *next = entry->next;
|
||||
@ -166,7 +166,7 @@ const char *SDL_GetHint(const char *name)
|
||||
env = SDL_getenv(name);
|
||||
for (hint = SDL_hints; hint; hint = hint->next) {
|
||||
if (SDL_strcmp(name, hint->name) == 0) {
|
||||
if (env == NULL || hint->priority == SDL_HINT_OVERRIDE) {
|
||||
if (!env || hint->priority == SDL_HINT_OVERRIDE) {
|
||||
return hint->value;
|
||||
}
|
||||
break;
|
||||
@ -177,7 +177,7 @@ const char *SDL_GetHint(const char *name)
|
||||
|
||||
int SDL_GetStringInteger(const char *value, int default_value)
|
||||
{
|
||||
if (value == NULL || !*value) {
|
||||
if (!value || !*value) {
|
||||
return default_value;
|
||||
}
|
||||
if (*value == '0' || SDL_strcasecmp(value, "false") == 0) {
|
||||
@ -194,7 +194,7 @@ int SDL_GetStringInteger(const char *value, int default_value)
|
||||
|
||||
SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value)
|
||||
{
|
||||
if (value == NULL || !*value) {
|
||||
if (!value || !*value) {
|
||||
return default_value;
|
||||
}
|
||||
if (*value == '0' || SDL_strcasecmp(value, "false") == 0) {
|
||||
@ -215,7 +215,7 @@ int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userd
|
||||
SDL_HintWatch *entry;
|
||||
const char *value;
|
||||
|
||||
if (name == NULL || !*name) {
|
||||
if (!name || !*name) {
|
||||
return SDL_InvalidParamError("name");
|
||||
}
|
||||
if (!callback) {
|
||||
@ -225,8 +225,8 @@ int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userd
|
||||
SDL_DelHintCallback(name, callback, userdata);
|
||||
|
||||
entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
|
||||
if (entry == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!entry) {
|
||||
return -1;
|
||||
}
|
||||
entry->callback = callback;
|
||||
entry->userdata = userdata;
|
||||
@ -236,18 +236,18 @@ int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userd
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hint == NULL) {
|
||||
if (!hint) {
|
||||
/* Need to add a hint entry for this watcher */
|
||||
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
|
||||
if (hint == NULL) {
|
||||
if (!hint) {
|
||||
SDL_free(entry);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
hint->name = SDL_strdup(name);
|
||||
if (!hint->name) {
|
||||
SDL_free(entry);
|
||||
SDL_free(hint);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
hint->value = NULL;
|
||||
hint->priority = SDL_HINT_DEFAULT;
|
||||
|
2
external/sdl/SDL/src/SDL_hints_c.h
vendored
2
external/sdl/SDL/src/SDL_hints_c.h
vendored
@ -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
|
||||
|
16
external/sdl/SDL/src/SDL_internal.h
vendored
16
external/sdl/SDL/src/SDL_internal.h
vendored
@ -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
|
||||
@ -40,6 +40,17 @@
|
||||
#define SDL_VARIABLE_LENGTH_ARRAY
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) || defined(__clang__)
|
||||
#define HAVE_GCC_DIAGNOSTIC_PRAGMA 1
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER /* We use constant comparison for generated code */
|
||||
#pragma warning(disable : 6326)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER /* SDL_MAX_SMALL_ALLOC_STACKSIZE is smaller than _ALLOCA_S_THRESHOLD and should be generally safe */
|
||||
#pragma warning(disable : 6255)
|
||||
#endif
|
||||
#define SDL_MAX_SMALL_ALLOC_STACKSIZE 128
|
||||
#define SDL_small_alloc(type, count, pisstack) ((*(pisstack) = ((sizeof(type) * (count)) < SDL_MAX_SMALL_ALLOC_STACKSIZE)), (*(pisstack) ? SDL_stack_alloc(type, count) : (type *)SDL_malloc(sizeof(type) * (count))))
|
||||
#define SDL_small_free(ptr, isstack) \
|
||||
@ -197,9 +208,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern DECLSPEC Uint32 SDLCALL SDL_GetNextObjectID(void);
|
||||
extern DECLSPEC int SDLCALL SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS);
|
||||
extern DECLSPEC int SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS);
|
||||
extern DECLSPEC int SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS);
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
|
8
external/sdl/SDL/src/SDL_list.c
vendored
8
external/sdl/SDL/src/SDL_list.c
vendored
@ -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
|
||||
@ -27,8 +27,8 @@ int SDL_ListAdd(SDL_ListNode **head, void *ent)
|
||||
{
|
||||
SDL_ListNode *node = SDL_malloc(sizeof(*node));
|
||||
|
||||
if (node == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!node) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
node->entry = ent;
|
||||
@ -43,7 +43,7 @@ void SDL_ListPop(SDL_ListNode **head, void **ent)
|
||||
SDL_ListNode **ptr = head;
|
||||
|
||||
/* Invalid or empty */
|
||||
if (head == NULL || *head == NULL) {
|
||||
if (!head || !*head) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
2
external/sdl/SDL/src/SDL_list.h
vendored
2
external/sdl/SDL/src/SDL_list.h
vendored
@ -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
|
||||
|
20
external/sdl/SDL/src/SDL_log.c
vendored
20
external/sdl/SDL/src/SDL_log.c
vendored
@ -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
|
||||
@ -65,7 +65,7 @@ static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput;
|
||||
static void *SDL_log_userdata = NULL;
|
||||
static SDL_Mutex *log_function_mutex = NULL;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
@ -80,7 +80,7 @@ static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {
|
||||
"CRITICAL"
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
@ -112,7 +112,7 @@ static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
|
||||
|
||||
void SDL_InitLog(void)
|
||||
{
|
||||
if (log_function_mutex == NULL) {
|
||||
if (!log_function_mutex) {
|
||||
/* if this fails we'll try to continue without it. */
|
||||
log_function_mutex = SDL_CreateMutex();
|
||||
}
|
||||
@ -282,7 +282,7 @@ static const char *GetCategoryPrefix(int category)
|
||||
}
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
|
||||
void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap)
|
||||
{
|
||||
char *message = NULL;
|
||||
char stack_buf[SDL_MAX_LOG_MESSAGE_STACK];
|
||||
@ -305,7 +305,7 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va
|
||||
return;
|
||||
}
|
||||
|
||||
if (log_function_mutex == NULL) {
|
||||
if (!log_function_mutex) {
|
||||
/* this mutex creation can race if you log from two threads at startup. You should have called SDL_Init first! */
|
||||
log_function_mutex = SDL_CreateMutex();
|
||||
}
|
||||
@ -323,7 +323,7 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va
|
||||
if (len >= sizeof(stack_buf) && SDL_size_add_overflow(len, 1, &len_plus_term) == 0) {
|
||||
/* Allocate exactly what we need, including the zero-terminator */
|
||||
message = (char *)SDL_malloc(len_plus_term);
|
||||
if (message == NULL) {
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
va_copy(aq, ap);
|
||||
@ -459,7 +459,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority
|
||||
{
|
||||
FILE *pFile;
|
||||
pFile = fopen("SDL_Log.txt", "a");
|
||||
if (pFile != NULL) {
|
||||
if (pFile) {
|
||||
(void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||
(void)fclose(pFile);
|
||||
}
|
||||
@ -468,7 +468,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority
|
||||
{
|
||||
FILE *pFile;
|
||||
pFile = fopen("ux0:/data/SDL_Log.txt", "a");
|
||||
if (pFile != NULL) {
|
||||
if (pFile) {
|
||||
(void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||
(void)fclose(pFile);
|
||||
}
|
||||
@ -477,7 +477,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority
|
||||
{
|
||||
FILE *pFile;
|
||||
pFile = fopen("sdmc:/3ds/SDL_Log.txt", "a");
|
||||
if (pFile != NULL) {
|
||||
if (pFile) {
|
||||
(void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||
(void)fclose(pFile);
|
||||
}
|
||||
|
2
external/sdl/SDL/src/SDL_log_c.h
vendored
2
external/sdl/SDL/src/SDL_log_c.h
vendored
@ -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
|
||||
|
722
external/sdl/SDL/src/SDL_properties.c
vendored
Normal file
722
external/sdl/SDL/src/SDL_properties.c
vendored
Normal file
@ -0,0 +1,722 @@
|
||||
/*
|
||||
Simple DiretMedia Layer
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
#include "SDL_hashtable.h"
|
||||
#include "SDL_hints_c.h"
|
||||
#include "SDL_properties_c.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_PropertyType type;
|
||||
|
||||
union {
|
||||
void *pointer_value;
|
||||
char *string_value;
|
||||
Sint64 number_value;
|
||||
float float_value;
|
||||
SDL_bool boolean_value;
|
||||
} value;
|
||||
|
||||
char *string_storage;
|
||||
|
||||
void (SDLCALL *cleanup)(void *userdata, void *value);
|
||||
void *userdata;
|
||||
} SDL_Property;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_HashTable *props;
|
||||
SDL_Mutex *lock;
|
||||
} SDL_Properties;
|
||||
|
||||
static SDL_HashTable *SDL_properties;
|
||||
static SDL_Mutex *SDL_properties_lock;
|
||||
static SDL_PropertiesID SDL_last_properties_id;
|
||||
static SDL_PropertiesID SDL_global_properties;
|
||||
|
||||
|
||||
static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void *data, SDL_bool cleanup)
|
||||
{
|
||||
SDL_Property *property = (SDL_Property *)value;
|
||||
if (property) {
|
||||
switch (property->type) {
|
||||
case SDL_PROPERTY_TYPE_POINTER:
|
||||
if (property->cleanup && cleanup) {
|
||||
property->cleanup(property->userdata, property->value.pointer_value);
|
||||
}
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_STRING:
|
||||
SDL_free(property->value.string_value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (property->string_storage) {
|
||||
SDL_free(property->string_storage);
|
||||
}
|
||||
}
|
||||
SDL_free((void *)key);
|
||||
SDL_free((void *)value);
|
||||
}
|
||||
|
||||
static void SDL_FreeProperty(const void *key, const void *value, void *data)
|
||||
{
|
||||
SDL_FreePropertyWithCleanup(key, value, data, SDL_TRUE);
|
||||
}
|
||||
|
||||
static void SDL_FreeProperties(const void *key, const void *value, void *data)
|
||||
{
|
||||
SDL_Properties *properties = (SDL_Properties *)value;
|
||||
if (properties) {
|
||||
if (properties->props) {
|
||||
SDL_DestroyHashTable(properties->props);
|
||||
properties->props = NULL;
|
||||
}
|
||||
if (properties->lock) {
|
||||
SDL_DestroyMutex(properties->lock);
|
||||
properties->lock = NULL;
|
||||
}
|
||||
SDL_free(properties);
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_InitProperties(void)
|
||||
{
|
||||
if (!SDL_properties_lock) {
|
||||
SDL_properties_lock = SDL_CreateMutex();
|
||||
if (!SDL_properties_lock) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!SDL_properties) {
|
||||
SDL_properties = SDL_CreateHashTable(NULL, 16, SDL_HashID, SDL_KeyMatchID, SDL_FreeProperties, SDL_FALSE);
|
||||
if (!SDL_properties) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_QuitProperties(void)
|
||||
{
|
||||
if (SDL_global_properties) {
|
||||
SDL_DestroyProperties(SDL_global_properties);
|
||||
SDL_global_properties = 0;
|
||||
}
|
||||
if (SDL_properties) {
|
||||
SDL_DestroyHashTable(SDL_properties);
|
||||
SDL_properties = NULL;
|
||||
}
|
||||
if (SDL_properties_lock) {
|
||||
SDL_DestroyMutex(SDL_properties_lock);
|
||||
SDL_properties_lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_PropertiesID SDL_GetGlobalProperties(void)
|
||||
{
|
||||
if (!SDL_global_properties) {
|
||||
SDL_global_properties = SDL_CreateProperties();
|
||||
}
|
||||
return SDL_global_properties;
|
||||
}
|
||||
|
||||
SDL_PropertiesID SDL_CreateProperties(void)
|
||||
{
|
||||
SDL_PropertiesID props = 0;
|
||||
SDL_Properties *properties = NULL;
|
||||
SDL_bool inserted = SDL_FALSE;
|
||||
|
||||
if (!SDL_properties && SDL_InitProperties() < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
properties = SDL_calloc(1, sizeof(*properties));
|
||||
if (!properties) {
|
||||
goto error;
|
||||
}
|
||||
properties->props = SDL_CreateHashTable(NULL, 4, SDL_HashString, SDL_KeyMatchString, SDL_FreeProperty, SDL_FALSE);
|
||||
if (!properties->props) {
|
||||
goto error;
|
||||
}
|
||||
properties->lock = SDL_CreateMutex();
|
||||
if (!properties->lock) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SDL_InitProperties() < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
++SDL_last_properties_id;
|
||||
if (SDL_last_properties_id == 0) {
|
||||
++SDL_last_properties_id;
|
||||
}
|
||||
props = SDL_last_properties_id;
|
||||
if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) {
|
||||
inserted = SDL_TRUE;
|
||||
}
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (inserted) {
|
||||
/* All done! */
|
||||
return props;
|
||||
}
|
||||
|
||||
error:
|
||||
SDL_FreeProperties(NULL, properties, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_LockProperties(SDL_PropertiesID props)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
|
||||
if (!props) {
|
||||
return SDL_InvalidParamError("props");
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
return SDL_InvalidParamError("props");
|
||||
}
|
||||
|
||||
SDL_LockMutex(properties->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_UnlockProperties(SDL_PropertiesID props)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
|
||||
if (!props) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
}
|
||||
|
||||
static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_Property *property)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
int result = 0;
|
||||
|
||||
if (!props) {
|
||||
SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE);
|
||||
return SDL_InvalidParamError("props");
|
||||
}
|
||||
if (!name || !*name) {
|
||||
SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE);
|
||||
return SDL_InvalidParamError("name");
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE);
|
||||
return SDL_InvalidParamError("props");
|
||||
}
|
||||
|
||||
SDL_LockMutex(properties->lock);
|
||||
{
|
||||
SDL_RemoveFromHashTable(properties->props, name);
|
||||
if (property) {
|
||||
char *key = SDL_strdup(name);
|
||||
if (!SDL_InsertIntoHashTable(properties->props, key, property)) {
|
||||
SDL_FreePropertyWithCleanup(key, property, NULL, SDL_FALSE);
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata)
|
||||
{
|
||||
SDL_Property *property;
|
||||
|
||||
if (!value) {
|
||||
return SDL_ClearProperty(props, name);
|
||||
}
|
||||
|
||||
property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
|
||||
if (!property) {
|
||||
return -1;
|
||||
}
|
||||
property->type = SDL_PROPERTY_TYPE_POINTER;
|
||||
property->value.pointer_value = value;
|
||||
property->cleanup = cleanup;
|
||||
property->userdata = userdata;
|
||||
return SDL_PrivateSetProperty(props, name, property);
|
||||
}
|
||||
|
||||
int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value)
|
||||
{
|
||||
SDL_Property *property;
|
||||
|
||||
if (!value) {
|
||||
return SDL_ClearProperty(props, name);
|
||||
}
|
||||
|
||||
property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
|
||||
if (!property) {
|
||||
return -1;
|
||||
}
|
||||
property->type = SDL_PROPERTY_TYPE_POINTER;
|
||||
property->value.pointer_value = value;
|
||||
return SDL_PrivateSetProperty(props, name, property);
|
||||
}
|
||||
|
||||
|
||||
int SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value)
|
||||
{
|
||||
SDL_Property *property;
|
||||
|
||||
if (!value) {
|
||||
return SDL_ClearProperty(props, name);
|
||||
}
|
||||
|
||||
property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
|
||||
if (!property) {
|
||||
return -1;
|
||||
}
|
||||
property->type = SDL_PROPERTY_TYPE_STRING;
|
||||
property->value.string_value = SDL_strdup(value);
|
||||
if (!property->value.string_value) {
|
||||
SDL_free(property);
|
||||
return -1;
|
||||
}
|
||||
return SDL_PrivateSetProperty(props, name, property);
|
||||
}
|
||||
|
||||
int SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value)
|
||||
{
|
||||
SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
|
||||
if (!property) {
|
||||
return -1;
|
||||
}
|
||||
property->type = SDL_PROPERTY_TYPE_NUMBER;
|
||||
property->value.number_value = value;
|
||||
return SDL_PrivateSetProperty(props, name, property);
|
||||
}
|
||||
|
||||
int SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value)
|
||||
{
|
||||
SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
|
||||
if (!property) {
|
||||
return -1;
|
||||
}
|
||||
property->type = SDL_PROPERTY_TYPE_FLOAT;
|
||||
property->value.float_value = value;
|
||||
return SDL_PrivateSetProperty(props, name, property);
|
||||
}
|
||||
|
||||
int SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool value)
|
||||
{
|
||||
SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
|
||||
if (!property) {
|
||||
return -1;
|
||||
}
|
||||
property->type = SDL_PROPERTY_TYPE_BOOLEAN;
|
||||
property->value.boolean_value = value ? SDL_TRUE : SDL_FALSE;
|
||||
return SDL_PrivateSetProperty(props, name, property);
|
||||
}
|
||||
|
||||
SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
SDL_PropertyType type = SDL_PROPERTY_TYPE_INVALID;
|
||||
|
||||
if (!props) {
|
||||
SDL_InvalidParamError("props");
|
||||
return SDL_PROPERTY_TYPE_INVALID;
|
||||
}
|
||||
if (!name || !*name) {
|
||||
SDL_InvalidParamError("name");
|
||||
return SDL_PROPERTY_TYPE_INVALID;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
SDL_InvalidParamError("props");
|
||||
return SDL_PROPERTY_TYPE_INVALID;
|
||||
}
|
||||
|
||||
SDL_LockMutex(properties->lock);
|
||||
{
|
||||
SDL_Property *property = NULL;
|
||||
if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
|
||||
type = property->type;
|
||||
} else {
|
||||
SDL_SetError("Couldn't find property named %s", name);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
void *value = default_value;
|
||||
|
||||
if (!props) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
if (!name || !*name) {
|
||||
SDL_InvalidParamError("name");
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Note that taking the lock here only guarantees that we won't read the
|
||||
* hashtable while it's being modified. The value itself can easily be
|
||||
* freed from another thread after it is returned here.
|
||||
*/
|
||||
SDL_LockMutex(properties->lock);
|
||||
{
|
||||
SDL_Property *property = NULL;
|
||||
if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
|
||||
if (property->type == SDL_PROPERTY_TYPE_POINTER) {
|
||||
value = property->value.pointer_value;
|
||||
} else {
|
||||
SDL_SetError("Property %s isn't a pointer value", name);
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Couldn't find property named %s", name);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
const char *value = default_value;
|
||||
|
||||
if (!props) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
if (!name || !*name) {
|
||||
SDL_InvalidParamError("name");
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Note that taking the lock here only guarantees that we won't read the
|
||||
* hashtable while it's being modified. The value itself can easily be
|
||||
* freed from another thread after it is returned here.
|
||||
*
|
||||
* FIXME: Should we SDL_strdup() the return value to avoid this?
|
||||
*/
|
||||
SDL_LockMutex(properties->lock);
|
||||
{
|
||||
SDL_Property *property = NULL;
|
||||
if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
|
||||
switch (property->type) {
|
||||
case SDL_PROPERTY_TYPE_STRING:
|
||||
value = property->value.string_value;
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_NUMBER:
|
||||
if (property->string_storage) {
|
||||
value = property->string_storage;
|
||||
} else {
|
||||
SDL_asprintf(&property->string_storage, "%" SDL_PRIs64 "", property->value.number_value);
|
||||
if (property->string_storage) {
|
||||
value = property->string_storage;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_FLOAT:
|
||||
if (property->string_storage) {
|
||||
value = property->string_storage;
|
||||
} else {
|
||||
SDL_asprintf(&property->string_storage, "%f", property->value.float_value);
|
||||
if (property->string_storage) {
|
||||
value = property->string_storage;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_BOOLEAN:
|
||||
value = property->value.boolean_value ? "true" : "false";
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Property %s isn't a string value", name);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Couldn't find property named %s", name);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
Sint64 value = default_value;
|
||||
|
||||
if (!props) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
if (!name || !*name) {
|
||||
SDL_InvalidParamError("name");
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_LockMutex(properties->lock);
|
||||
{
|
||||
SDL_Property *property = NULL;
|
||||
if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
|
||||
switch (property->type) {
|
||||
case SDL_PROPERTY_TYPE_STRING:
|
||||
value = SDL_strtoll(property->value.string_value, NULL, 0);
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_NUMBER:
|
||||
value = property->value.number_value;
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_FLOAT:
|
||||
value = (Sint64)SDL_round((double)property->value.float_value);
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_BOOLEAN:
|
||||
value = property->value.boolean_value;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Property %s isn't a number value", name);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Couldn't find property named %s", name);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
float value = default_value;
|
||||
|
||||
if (!props) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
if (!name || !*name) {
|
||||
SDL_InvalidParamError("name");
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_LockMutex(properties->lock);
|
||||
{
|
||||
SDL_Property *property = NULL;
|
||||
if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
|
||||
switch (property->type) {
|
||||
case SDL_PROPERTY_TYPE_STRING:
|
||||
value = (float)SDL_atof(property->value.string_value);
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_NUMBER:
|
||||
value = (float)property->value.number_value;
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_FLOAT:
|
||||
value = property->value.float_value;
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_BOOLEAN:
|
||||
value = (float)property->value.boolean_value;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Property %s isn't a float value", name);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Couldn't find property named %s", name);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool default_value)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
SDL_bool value = default_value;
|
||||
|
||||
if (!props) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
if (!name || !*name) {
|
||||
SDL_InvalidParamError("name");
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
SDL_InvalidParamError("props");
|
||||
return value;
|
||||
}
|
||||
|
||||
SDL_LockMutex(properties->lock);
|
||||
{
|
||||
SDL_Property *property = NULL;
|
||||
if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
|
||||
switch (property->type) {
|
||||
case SDL_PROPERTY_TYPE_STRING:
|
||||
value = SDL_GetStringBoolean(property->value.string_value, default_value);
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_NUMBER:
|
||||
value = (property->value.number_value != 0);
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_FLOAT:
|
||||
value = (property->value.float_value != 0.0f);
|
||||
break;
|
||||
case SDL_PROPERTY_TYPE_BOOLEAN:
|
||||
value = property->value.boolean_value;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Property %s isn't a boolean value", name);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Couldn't find property named %s", name);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int SDL_ClearProperty(SDL_PropertiesID props, const char *name)
|
||||
{
|
||||
return SDL_PrivateSetProperty(props, name, NULL);
|
||||
}
|
||||
|
||||
int SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata)
|
||||
{
|
||||
SDL_Properties *properties = NULL;
|
||||
|
||||
if (!props) {
|
||||
return SDL_InvalidParamError("props");
|
||||
}
|
||||
if (!callback) {
|
||||
return SDL_InvalidParamError("callback");
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
|
||||
if (!properties) {
|
||||
return SDL_InvalidParamError("props");
|
||||
}
|
||||
|
||||
SDL_LockMutex(properties->lock);
|
||||
{
|
||||
void *iter;
|
||||
const void *key, *value;
|
||||
|
||||
iter = NULL;
|
||||
while (SDL_IterateHashTable(properties->props, &key, &value, &iter)) {
|
||||
callback(userdata, props, (const char *)key);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(properties->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_DestroyProperties(SDL_PropertiesID props)
|
||||
{
|
||||
if (!props) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LockMutex(SDL_properties_lock);
|
||||
SDL_RemoveFromHashTable(SDL_properties, (const void *)(uintptr_t)props);
|
||||
SDL_UnlockMutex(SDL_properties_lock);
|
||||
}
|
23
external/sdl/SDL/src/SDL_properties_c.h
vendored
Normal file
23
external/sdl/SDL/src/SDL_properties_c.h
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
Simple DiretMedia Layer
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
extern int SDL_InitProperties(void);
|
||||
extern void SDL_QuitProperties(void);
|
2
external/sdl/SDL/src/SDL_utils.c
vendored
2
external/sdl/SDL/src/SDL_utils.c
vendored
@ -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
|
||||
|
2
external/sdl/SDL/src/SDL_utils_c.h
vendored
2
external/sdl/SDL/src/SDL_utils_c.h
vendored
@ -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
|
||||
|
18
external/sdl/SDL/src/atomic/SDL_atomic.c
vendored
18
external/sdl/SDL/src/atomic/SDL_atomic.c
vendored
@ -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
|
||||
@ -128,13 +128,13 @@ SDL_bool SDL_AtomicCAS(SDL_AtomicInt *a, int oldval, int newval)
|
||||
SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(long) == sizeof(a->value));
|
||||
return _InterlockedCompareExchange((long *)&a->value, (long)newval, (long)oldval) == (long)oldval;
|
||||
#elif defined(HAVE_WATCOM_ATOMICS)
|
||||
return (SDL_bool)_SDL_cmpxchg_watcom(&a->value, newval, oldval);
|
||||
return _SDL_cmpxchg_watcom(&a->value, newval, oldval);
|
||||
#elif defined(HAVE_GCC_ATOMICS)
|
||||
return (SDL_bool)__sync_bool_compare_and_swap(&a->value, oldval, newval);
|
||||
return __sync_bool_compare_and_swap(&a->value, oldval, newval);
|
||||
#elif defined(__MACOS__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */
|
||||
return (SDL_bool)OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value);
|
||||
return OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value);
|
||||
#elif defined(__SOLARIS__)
|
||||
return (SDL_bool)((int)atomic_cas_uint((volatile uint_t *)&a->value, (uint_t)oldval, (uint_t)newval) == oldval);
|
||||
return ((int)atomic_cas_uint((volatile uint_t *)&a->value, (uint_t)oldval, (uint_t)newval) == oldval);
|
||||
#elif defined(EMULATE_CAS)
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
@ -156,15 +156,15 @@ SDL_bool SDL_AtomicCASPtr(void **a, void *oldval, void *newval)
|
||||
#ifdef HAVE_MSC_ATOMICS
|
||||
return _InterlockedCompareExchangePointer(a, newval, oldval) == oldval;
|
||||
#elif defined(HAVE_WATCOM_ATOMICS)
|
||||
return (SDL_bool)_SDL_cmpxchg_watcom((int *)a, (long)newval, (long)oldval);
|
||||
return _SDL_cmpxchg_watcom((int *)a, (long)newval, (long)oldval);
|
||||
#elif defined(HAVE_GCC_ATOMICS)
|
||||
return __sync_bool_compare_and_swap(a, oldval, newval);
|
||||
#elif defined(__MACOS__) && defined(__LP64__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */
|
||||
return (SDL_bool)OSAtomicCompareAndSwap64Barrier((int64_t)oldval, (int64_t)newval, (int64_t *)a);
|
||||
return OSAtomicCompareAndSwap64Barrier((int64_t)oldval, (int64_t)newval, (int64_t *)a);
|
||||
#elif defined(__MACOS__) && !defined(__LP64__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */
|
||||
return (SDL_bool)OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t *)a);
|
||||
return OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t *)a);
|
||||
#elif defined(__SOLARIS__)
|
||||
return (SDL_bool)(atomic_cas_ptr(a, oldval, newval) == oldval);
|
||||
return (atomic_cas_ptr(a, oldval, newval) == oldval);
|
||||
#elif defined(EMULATE_CAS)
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
|
8
external/sdl/SDL/src/atomic/SDL_spinlock.c
vendored
8
external/sdl/SDL/src/atomic/SDL_spinlock.c
vendored
@ -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 @@ SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock)
|
||||
/* Terrible terrible damage */
|
||||
static SDL_Mutex *_spinlock_mutex;
|
||||
|
||||
if (_spinlock_mutex == NULL) {
|
||||
if (!_spinlock_mutex) {
|
||||
/* Race condition on first lock... */
|
||||
_spinlock_mutex = SDL_CreateMutex();
|
||||
}
|
||||
@ -139,11 +139,11 @@ SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock)
|
||||
|
||||
#elif defined(__SOLARIS__) && defined(_LP64)
|
||||
/* Used for Solaris with non-gcc compilers. */
|
||||
return (SDL_bool)((int)atomic_cas_64((volatile uint64_t *)lock, 0, 1) == 0);
|
||||
return ((int)atomic_cas_64((volatile uint64_t *)lock, 0, 1) == 0);
|
||||
|
||||
#elif defined(__SOLARIS__) && !defined(_LP64)
|
||||
/* Used for Solaris with non-gcc compilers. */
|
||||
return (SDL_bool)((int)atomic_cas_32((volatile uint32_t *)lock, 0, 1) == 0);
|
||||
return ((int)atomic_cas_32((volatile uint32_t *)lock, 0, 1) == 0);
|
||||
#elif defined(PS2)
|
||||
uint32_t oldintr;
|
||||
SDL_bool res = SDL_FALSE;
|
||||
|
1604
external/sdl/SDL/src/audio/SDL_audio.c
vendored
1604
external/sdl/SDL/src/audio/SDL_audio.c
vendored
File diff suppressed because it is too large
Load Diff
6
external/sdl/SDL/src/audio/SDL_audio_c.h
vendored
6
external/sdl/SDL/src/audio/SDL_audio_c.h
vendored
@ -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
|
||||
@ -22,8 +22,6 @@
|
||||
#ifndef SDL_audio_c_h_
|
||||
#define SDL_audio_c_h_
|
||||
|
||||
/* !!! FIXME: remove this header and have things just include SDL_sysaudio.h directly. */
|
||||
|
||||
#include "SDL_sysaudio.h"
|
||||
extern void SDL_UpdateAudio(void);
|
||||
|
||||
#endif /* SDL_audio_c_h_ */
|
||||
|
@ -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
|
||||
@ -19,7 +19,7 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_channel_conversion.c */
|
||||
// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_channel_conversion.c
|
||||
|
||||
|
||||
typedef void (*SDL_AudioChannelConverter)(float *dst, const float *src, int num_frames);
|
||||
@ -30,7 +30,7 @@ static void SDL_ConvertMonoToStereo(float *dst, const float *src, int num_frames
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("mono", "stereo");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1);
|
||||
dst += (num_frames-1) * 2;
|
||||
for (i = num_frames; i; i--, src--, dst -= 2) {
|
||||
@ -47,7 +47,7 @@ static void SDL_ConvertMonoTo21(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("mono", "2.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1);
|
||||
dst += (num_frames-1) * 3;
|
||||
for (i = num_frames; i; i--, src--, dst -= 3) {
|
||||
@ -65,7 +65,7 @@ static void SDL_ConvertMonoToQuad(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("mono", "quad");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1);
|
||||
dst += (num_frames-1) * 4;
|
||||
for (i = num_frames; i; i--, src--, dst -= 4) {
|
||||
@ -84,7 +84,7 @@ static void SDL_ConvertMonoTo41(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("mono", "4.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1);
|
||||
dst += (num_frames-1) * 5;
|
||||
for (i = num_frames; i; i--, src--, dst -= 5) {
|
||||
@ -104,7 +104,7 @@ static void SDL_ConvertMonoTo51(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("mono", "5.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1);
|
||||
dst += (num_frames-1) * 6;
|
||||
for (i = num_frames; i; i--, src--, dst -= 6) {
|
||||
@ -125,7 +125,7 @@ static void SDL_ConvertMonoTo61(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("mono", "6.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1);
|
||||
dst += (num_frames-1) * 7;
|
||||
for (i = num_frames; i; i--, src--, dst -= 7) {
|
||||
@ -147,7 +147,7 @@ static void SDL_ConvertMonoTo71(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("mono", "7.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1);
|
||||
dst += (num_frames-1) * 8;
|
||||
for (i = num_frames; i; i--, src--, dst -= 8) {
|
||||
@ -182,7 +182,7 @@ static void SDL_ConvertStereoTo21(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("stereo", "2.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 2;
|
||||
dst += (num_frames-1) * 3;
|
||||
for (i = num_frames; i; i--, src -= 2, dst -= 3) {
|
||||
@ -199,7 +199,7 @@ static void SDL_ConvertStereoToQuad(float *dst, const float *src, int num_frames
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("stereo", "quad");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 2;
|
||||
dst += (num_frames-1) * 4;
|
||||
for (i = num_frames; i; i--, src -= 2, dst -= 4) {
|
||||
@ -217,7 +217,7 @@ static void SDL_ConvertStereoTo41(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("stereo", "4.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 2;
|
||||
dst += (num_frames-1) * 5;
|
||||
for (i = num_frames; i; i--, src -= 2, dst -= 5) {
|
||||
@ -236,7 +236,7 @@ static void SDL_ConvertStereoTo51(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("stereo", "5.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 2;
|
||||
dst += (num_frames-1) * 6;
|
||||
for (i = num_frames; i; i--, src -= 2, dst -= 6) {
|
||||
@ -256,7 +256,7 @@ static void SDL_ConvertStereoTo61(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("stereo", "6.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 2;
|
||||
dst += (num_frames-1) * 7;
|
||||
for (i = num_frames; i; i--, src -= 2, dst -= 7) {
|
||||
@ -277,7 +277,7 @@ static void SDL_ConvertStereoTo71(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("stereo", "7.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 2;
|
||||
dst += (num_frames-1) * 8;
|
||||
for (i = num_frames; i; i--, src -= 2, dst -= 8) {
|
||||
@ -325,7 +325,7 @@ static void SDL_Convert21ToQuad(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("2.1", "quad");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 3;
|
||||
dst += (num_frames-1) * 4;
|
||||
for (i = num_frames; i; i--, src -= 3, dst -= 4) {
|
||||
@ -344,7 +344,7 @@ static void SDL_Convert21To41(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("2.1", "4.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 3;
|
||||
dst += (num_frames-1) * 5;
|
||||
for (i = num_frames; i; i--, src -= 3, dst -= 5) {
|
||||
@ -363,7 +363,7 @@ static void SDL_Convert21To51(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("2.1", "5.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 3;
|
||||
dst += (num_frames-1) * 6;
|
||||
for (i = num_frames; i; i--, src -= 3, dst -= 6) {
|
||||
@ -383,7 +383,7 @@ static void SDL_Convert21To61(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("2.1", "6.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 3;
|
||||
dst += (num_frames-1) * 7;
|
||||
for (i = num_frames; i; i--, src -= 3, dst -= 7) {
|
||||
@ -404,7 +404,7 @@ static void SDL_Convert21To71(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("2.1", "7.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 3;
|
||||
dst += (num_frames-1) * 8;
|
||||
for (i = num_frames; i; i--, src -= 3, dst -= 8) {
|
||||
@ -469,7 +469,7 @@ static void SDL_ConvertQuadTo41(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("quad", "4.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 4;
|
||||
dst += (num_frames-1) * 5;
|
||||
for (i = num_frames; i; i--, src -= 4, dst -= 5) {
|
||||
@ -488,7 +488,7 @@ static void SDL_ConvertQuadTo51(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("quad", "5.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 4;
|
||||
dst += (num_frames-1) * 6;
|
||||
for (i = num_frames; i; i--, src -= 4, dst -= 6) {
|
||||
@ -508,7 +508,7 @@ static void SDL_ConvertQuadTo61(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("quad", "6.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 4;
|
||||
dst += (num_frames-1) * 7;
|
||||
for (i = num_frames; i; i--, src -= 4, dst -= 7) {
|
||||
@ -531,7 +531,7 @@ static void SDL_ConvertQuadTo71(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("quad", "7.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 4;
|
||||
dst += (num_frames-1) * 8;
|
||||
for (i = num_frames; i; i--, src -= 4, dst -= 8) {
|
||||
@ -613,7 +613,7 @@ static void SDL_Convert41To51(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("4.1", "5.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 5;
|
||||
dst += (num_frames-1) * 6;
|
||||
for (i = num_frames; i; i--, src -= 5, dst -= 6) {
|
||||
@ -633,7 +633,7 @@ static void SDL_Convert41To61(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("4.1", "6.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 5;
|
||||
dst += (num_frames-1) * 7;
|
||||
for (i = num_frames; i; i--, src -= 5, dst -= 7) {
|
||||
@ -656,7 +656,7 @@ static void SDL_Convert41To71(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("4.1", "7.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 5;
|
||||
dst += (num_frames-1) * 8;
|
||||
for (i = num_frames; i; i--, src -= 5, dst -= 8) {
|
||||
@ -758,7 +758,7 @@ static void SDL_Convert51To61(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("5.1", "6.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 6;
|
||||
dst += (num_frames-1) * 7;
|
||||
for (i = num_frames; i; i--, src -= 6, dst -= 7) {
|
||||
@ -781,7 +781,7 @@ static void SDL_Convert51To71(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("5.1", "7.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 6;
|
||||
dst += (num_frames-1) * 8;
|
||||
for (i = num_frames; i; i--, src -= 6, dst -= 8) {
|
||||
@ -911,7 +911,7 @@ static void SDL_Convert61To71(float *dst, const float *src, int num_frames)
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("6.1", "7.1");
|
||||
|
||||
/* convert backwards, since output is growing in-place. */
|
||||
// convert backwards, since output is growing in-place.
|
||||
src += (num_frames-1) * 7;
|
||||
dst += (num_frames-1) * 8;
|
||||
for (i = num_frames; i; i--, src -= 7, dst -= 8) {
|
||||
|
@ -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
|
||||
@ -19,7 +19,7 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_resampler_filter.c */
|
||||
// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_resampler_filter.c
|
||||
|
||||
#define RESAMPLER_ZERO_CROSSINGS 5
|
||||
#define RESAMPLER_BITS_PER_SAMPLE 16
|
||||
|
98
external/sdl/SDL/src/audio/SDL_audiocvt.c
vendored
98
external/sdl/SDL/src/audio/SDL_audiocvt.c
vendored
@ -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
|
||||
@ -20,7 +20,7 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#include "SDL_audioqueue.h"
|
||||
#include "SDL_audioresample.h"
|
||||
@ -207,7 +207,7 @@ static SDL_bool SDL_IsSupportedAudioFormat(const SDL_AudioFormat fmt)
|
||||
|
||||
static SDL_bool SDL_IsSupportedChannelCount(const int channels)
|
||||
{
|
||||
return ((channels >= 1) && (channels <= 8)) ? SDL_TRUE : SDL_FALSE;
|
||||
return ((channels >= 1) && (channels <= 8));
|
||||
}
|
||||
|
||||
|
||||
@ -278,7 +278,7 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i
|
||||
}
|
||||
}
|
||||
|
||||
if (scratch == NULL) {
|
||||
if (!scratch) {
|
||||
scratch = dst;
|
||||
}
|
||||
|
||||
@ -389,7 +389,7 @@ static int UpdateAudioStreamInputSpec(SDL_AudioStream *stream, const SDL_AudioSp
|
||||
if (stream->history_buffer_allocation < history_buffer_allocation) {
|
||||
history_buffer = (Uint8 *) SDL_aligned_alloc(SDL_SIMDGetAlignment(), history_buffer_allocation);
|
||||
if (!history_buffer) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
SDL_aligned_free(stream->history_buffer);
|
||||
stream->history_buffer = history_buffer;
|
||||
@ -404,27 +404,24 @@ static int UpdateAudioStreamInputSpec(SDL_AudioStream *stream, const SDL_AudioSp
|
||||
|
||||
SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec)
|
||||
{
|
||||
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
|
||||
SDL_SetError("Audio subsystem is not initialized");
|
||||
return NULL;
|
||||
}
|
||||
SDL_ChooseAudioConverters();
|
||||
SDL_SetupAudioResampler();
|
||||
|
||||
SDL_AudioStream *retval = (SDL_AudioStream *)SDL_calloc(1, sizeof(SDL_AudioStream));
|
||||
if (retval == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
if (!retval) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval->freq_ratio = 1.0f;
|
||||
retval->queue = SDL_CreateAudioQueue(4096);
|
||||
|
||||
if (retval->queue == NULL) {
|
||||
if (!retval->queue) {
|
||||
SDL_free(retval);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval->lock = SDL_CreateMutex();
|
||||
if (retval->lock == NULL) {
|
||||
if (!retval->lock) {
|
||||
SDL_free(retval->queue);
|
||||
SDL_free(retval);
|
||||
return NULL;
|
||||
@ -440,6 +437,18 @@ SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_PropertiesID SDL_GetAudioStreamProperties(SDL_AudioStream *stream)
|
||||
{
|
||||
if (!stream) {
|
||||
SDL_InvalidParamError("stream");
|
||||
return 0;
|
||||
}
|
||||
if (stream->props == 0) {
|
||||
stream->props = SDL_CreateProperties();
|
||||
}
|
||||
return stream->props;
|
||||
}
|
||||
|
||||
int SDL_SetAudioStreamGetCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata)
|
||||
{
|
||||
if (!stream) {
|
||||
@ -466,12 +475,20 @@ int SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamCallba
|
||||
|
||||
int SDL_LockAudioStream(SDL_AudioStream *stream)
|
||||
{
|
||||
return stream ? SDL_LockMutex(stream->lock) : SDL_InvalidParamError("stream");
|
||||
if (!stream) {
|
||||
return SDL_InvalidParamError("stream");
|
||||
}
|
||||
SDL_LockMutex(stream->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_UnlockAudioStream(SDL_AudioStream *stream)
|
||||
{
|
||||
return stream ? SDL_UnlockMutex(stream->lock) : SDL_InvalidParamError("stream");
|
||||
if (!stream) {
|
||||
return SDL_InvalidParamError("stream");
|
||||
}
|
||||
SDL_UnlockMutex(stream->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec)
|
||||
@ -568,7 +585,7 @@ float SDL_GetAudioStreamFrequencyRatio(SDL_AudioStream *stream)
|
||||
}
|
||||
|
||||
SDL_LockMutex(stream->lock);
|
||||
float freq_ratio = stream->freq_ratio;
|
||||
const float freq_ratio = stream->freq_ratio;
|
||||
SDL_UnlockMutex(stream->lock);
|
||||
|
||||
return freq_ratio;
|
||||
@ -581,8 +598,8 @@ int SDL_SetAudioStreamFrequencyRatio(SDL_AudioStream *stream, float freq_ratio)
|
||||
}
|
||||
|
||||
// Picked mostly arbitrarily.
|
||||
static const float min_freq_ratio = 0.01f;
|
||||
static const float max_freq_ratio = 100.0f;
|
||||
const float min_freq_ratio = 0.01f;
|
||||
const float max_freq_ratio = 100.0f;
|
||||
|
||||
if (freq_ratio < min_freq_ratio) {
|
||||
return SDL_SetError("Frequency ratio is too low");
|
||||
@ -614,9 +631,9 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
|
||||
SDL_Log("AUDIOSTREAM: wants to put %d bytes", len);
|
||||
#endif
|
||||
|
||||
if (stream == NULL) {
|
||||
if (!stream) {
|
||||
return SDL_InvalidParamError("stream");
|
||||
} else if (buf == NULL) {
|
||||
} else if (!buf) {
|
||||
return SDL_InvalidParamError("buf");
|
||||
} else if (len < 0) {
|
||||
return SDL_InvalidParamError("len");
|
||||
@ -651,7 +668,7 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
|
||||
size_t chunk_size = SDL_GetAudioQueueChunkSize(stream->queue);
|
||||
track = SDL_CreateChunkedAudioTrack(&src_spec, buf, len, chunk_size);
|
||||
|
||||
if (track == NULL) {
|
||||
if (!track) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -662,7 +679,7 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
|
||||
|
||||
int retval = 0;
|
||||
|
||||
if (track != NULL) {
|
||||
if (track) {
|
||||
SDL_AddTrackToAudioQueue(stream->queue, track);
|
||||
} else {
|
||||
retval = SDL_WriteToAudioQueue(stream->queue, &stream->src_spec, buf, len);
|
||||
@ -683,7 +700,7 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
|
||||
|
||||
int SDL_FlushAudioStream(SDL_AudioStream *stream)
|
||||
{
|
||||
if (stream == NULL) {
|
||||
if (!stream) {
|
||||
return SDL_InvalidParamError("stream");
|
||||
}
|
||||
|
||||
@ -703,8 +720,7 @@ static Uint8 *EnsureAudioStreamWorkBufferSize(SDL_AudioStream *stream, size_t ne
|
||||
}
|
||||
|
||||
Uint8 *ptr = (Uint8 *) SDL_aligned_alloc(SDL_SIMDGetAlignment(), newlen);
|
||||
if (ptr == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
if (!ptr) {
|
||||
return NULL; // previous work buffer is still valid!
|
||||
}
|
||||
|
||||
@ -723,7 +739,7 @@ static void UpdateAudioStreamHistoryBuffer(SDL_AudioStream* stream,
|
||||
Uint8 *history_buffer = stream->history_buffer;
|
||||
int history_bytes = history_buffer_frames * SDL_AUDIO_FRAMESIZE(stream->input_spec);
|
||||
|
||||
if (left_padding != NULL) {
|
||||
if (left_padding) {
|
||||
// Fill in the left padding using the history buffer
|
||||
SDL_assert(padding_bytes <= history_bytes);
|
||||
SDL_memcpy(left_padding, history_buffer + history_bytes - padding_bytes, padding_bytes);
|
||||
@ -817,7 +833,7 @@ static Sint64 GetAudioStreamHead(SDL_AudioStream* stream, SDL_AudioSpec* out_spe
|
||||
{
|
||||
void* iter = SDL_BeginAudioQueueIter(stream->queue);
|
||||
|
||||
if (iter == NULL) {
|
||||
if (!iter) {
|
||||
SDL_zerop(out_spec);
|
||||
*out_flushed = SDL_FALSE;
|
||||
return 0;
|
||||
@ -1007,9 +1023,9 @@ int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len)
|
||||
SDL_Log("AUDIOSTREAM: want to get %d converted bytes", len);
|
||||
#endif
|
||||
|
||||
if (stream == NULL) {
|
||||
if (!stream) {
|
||||
return SDL_InvalidParamError("stream");
|
||||
} else if (buf == NULL) {
|
||||
} else if (!buf) {
|
||||
return SDL_InvalidParamError("buf");
|
||||
} else if (len < 0) {
|
||||
return SDL_InvalidParamError("len");
|
||||
@ -1142,7 +1158,7 @@ int SDL_GetAudioStreamQueued(SDL_AudioStream *stream)
|
||||
|
||||
int SDL_ClearAudioStream(SDL_AudioStream *stream)
|
||||
{
|
||||
if (stream == NULL) {
|
||||
if (!stream) {
|
||||
return SDL_InvalidParamError("stream");
|
||||
}
|
||||
|
||||
@ -1159,16 +1175,20 @@ int SDL_ClearAudioStream(SDL_AudioStream *stream)
|
||||
|
||||
void SDL_DestroyAudioStream(SDL_AudioStream *stream)
|
||||
{
|
||||
if (stream == NULL) {
|
||||
if (!stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_DestroyProperties(stream->props);
|
||||
|
||||
OnAudioStreamDestroy(stream);
|
||||
|
||||
const SDL_bool simplified = stream->simplified;
|
||||
if (simplified) {
|
||||
SDL_assert(stream->bound_device->simplified);
|
||||
SDL_CloseAudioDevice(stream->bound_device->instance_id); // this will unbind the stream.
|
||||
if (stream->bound_device) {
|
||||
SDL_assert(stream->bound_device->simplified);
|
||||
SDL_CloseAudioDevice(stream->bound_device->instance_id); // this will unbind the stream.
|
||||
}
|
||||
} else {
|
||||
SDL_UnbindAudioStream(stream);
|
||||
}
|
||||
@ -1192,13 +1212,13 @@ int SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data
|
||||
*dst_len = 0;
|
||||
}
|
||||
|
||||
if (src_data == NULL) {
|
||||
if (!src_data) {
|
||||
return SDL_InvalidParamError("src_data");
|
||||
} else if (src_len < 0) {
|
||||
return SDL_InvalidParamError("src_len");
|
||||
} else if (dst_data == NULL) {
|
||||
} else if (!dst_data) {
|
||||
return SDL_InvalidParamError("dst_data");
|
||||
} else if (dst_len == NULL) {
|
||||
} else if (!dst_len) {
|
||||
return SDL_InvalidParamError("dst_len");
|
||||
}
|
||||
|
||||
@ -1207,14 +1227,12 @@ int SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data
|
||||
int dstlen = 0;
|
||||
|
||||
SDL_AudioStream *stream = SDL_CreateAudioStream(src_spec, dst_spec);
|
||||
if (stream != NULL) {
|
||||
if (stream) {
|
||||
if ((SDL_PutAudioStreamData(stream, src_data, src_len) == 0) && (SDL_FlushAudioStream(stream) == 0)) {
|
||||
dstlen = SDL_GetAudioStreamAvailable(stream);
|
||||
if (dstlen >= 0) {
|
||||
dst = (Uint8 *)SDL_malloc(dstlen);
|
||||
if (!dst) {
|
||||
SDL_OutOfMemory();
|
||||
} else {
|
||||
if (dst) {
|
||||
retval = (SDL_GetAudioStreamData(stream, dst, dstlen) >= 0) ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
18
external/sdl/SDL/src/audio/SDL_audiodev.c
vendored
18
external/sdl/SDL/src/audio/SDL_audiodev.c
vendored
@ -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
|
||||
@ -20,14 +20,14 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/* Get the name of the audio device we use for output */
|
||||
// Get the name of the audio device we use for output
|
||||
|
||||
#if defined(SDL_AUDIO_DRIVER_NETBSD) || defined(SDL_AUDIO_DRIVER_OSS)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h> /* For close() */
|
||||
#include <unistd.h> // For close()
|
||||
|
||||
#include "SDL_audiodev_c.h"
|
||||
|
||||
@ -80,22 +80,22 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD
|
||||
const char *audiodev;
|
||||
char audiopath[1024];
|
||||
|
||||
if (test == NULL) {
|
||||
if (!test) {
|
||||
test = test_stub;
|
||||
}
|
||||
|
||||
/* Figure out what our audio device is */
|
||||
// Figure out what our audio device is
|
||||
audiodev = SDL_getenv("SDL_PATH_DSP");
|
||||
if (audiodev == NULL) {
|
||||
if (!audiodev) {
|
||||
audiodev = SDL_getenv("AUDIODEV");
|
||||
}
|
||||
if (audiodev == NULL) {
|
||||
if (!audiodev) {
|
||||
if (classic) {
|
||||
audiodev = SDL_PATH_DEV_AUDIO;
|
||||
} else {
|
||||
struct stat sb;
|
||||
|
||||
/* Added support for /dev/sound/\* in Linux 2.4 */
|
||||
// Added support for /dev/sound/\* in Linux 2.4
|
||||
if (((stat("/dev/sound", &sb) == 0) && S_ISDIR(sb.st_mode)) && ((stat(SDL_PATH_DEV_DSP24, &sb) == 0) && S_ISCHR(sb.st_mode))) {
|
||||
audiodev = SDL_PATH_DEV_DSP24;
|
||||
} else {
|
||||
@ -122,4 +122,4 @@ void SDL_EnumUnixAudioDevices(const SDL_bool classic, SDL_bool (*test)(int))
|
||||
SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test);
|
||||
}
|
||||
|
||||
#endif /* Audio driver selection */
|
||||
#endif // Audio device selection
|
||||
|
8
external/sdl/SDL/src/audio/SDL_audiodev_c.h
vendored
8
external/sdl/SDL/src/audio/SDL_audiodev_c.h
vendored
@ -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
|
||||
@ -25,8 +25,8 @@
|
||||
#include "SDL_internal.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
/* Open the audio device for playback, and don't block if busy */
|
||||
/* #define USE_BLOCKING_WRITES */
|
||||
// Open the audio device for playback, and don't block if busy
|
||||
//#define USE_BLOCKING_WRITES
|
||||
|
||||
#ifdef USE_BLOCKING_WRITES
|
||||
#define OPEN_FLAGS_OUTPUT O_WRONLY
|
||||
@ -38,4 +38,4 @@
|
||||
|
||||
extern void SDL_EnumUnixAudioDevices(const SDL_bool classic, SDL_bool (*test)(int));
|
||||
|
||||
#endif /* SDL_audiodev_c_h_ */
|
||||
#endif // SDL_audiodev_c_h_
|
||||
|
38
external/sdl/SDL/src/audio/SDL_audioqueue.c
vendored
38
external/sdl/SDL/src/audio/SDL_audioqueue.c
vendored
@ -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
|
||||
@ -92,7 +92,7 @@ static SDL_AudioChunk *CreateAudioChunk(size_t chunk_size)
|
||||
{
|
||||
SDL_AudioChunk *chunk = (SDL_AudioChunk *)SDL_malloc(sizeof(*chunk) + chunk_size);
|
||||
|
||||
if (chunk == NULL) {
|
||||
if (!chunk) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -146,11 +146,11 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len)
|
||||
SDL_AudioChunk *chunk = track->tail;
|
||||
|
||||
// Handle the first chunk
|
||||
if (chunk == NULL) {
|
||||
if (!chunk) {
|
||||
chunk = CreateAudioTrackChunk(track);
|
||||
|
||||
if (chunk == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!chunk) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_assert((track->head == NULL) && (track->tail == NULL) && (track->queued_bytes == 0));
|
||||
@ -180,7 +180,7 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len)
|
||||
}
|
||||
|
||||
// Roll back the changes if we couldn't write all the data
|
||||
if (chunk == NULL) {
|
||||
if (!chunk) {
|
||||
chunk = track->tail;
|
||||
|
||||
SDL_AudioChunk *next = chunk->next;
|
||||
@ -189,7 +189,7 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len)
|
||||
|
||||
DestroyAudioChunks(next);
|
||||
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
track->tail = chunk;
|
||||
@ -255,8 +255,7 @@ static SDL_AudioTrack *CreateChunkedAudioTrack(const SDL_AudioSpec *spec, size_t
|
||||
{
|
||||
SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)SDL_calloc(1, sizeof(*track));
|
||||
|
||||
if (track == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
if (!track) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -275,8 +274,7 @@ SDL_AudioQueue *SDL_CreateAudioQueue(size_t chunk_size)
|
||||
{
|
||||
SDL_AudioQueue *queue = (SDL_AudioQueue *)SDL_calloc(1, sizeof(*queue));
|
||||
|
||||
if (queue == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
if (!queue) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -338,7 +336,7 @@ void SDL_PopAudioQueueHead(SDL_AudioQueue *queue)
|
||||
|
||||
queue->head = track;
|
||||
|
||||
if (track == NULL) {
|
||||
if (!track) {
|
||||
queue->tail = NULL;
|
||||
}
|
||||
}
|
||||
@ -352,7 +350,7 @@ SDL_AudioTrack *SDL_CreateChunkedAudioTrack(const SDL_AudioSpec *spec, const Uin
|
||||
{
|
||||
SDL_AudioTrack *track = CreateChunkedAudioTrack(spec, chunk_size);
|
||||
|
||||
if (track == NULL) {
|
||||
if (!track) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -390,15 +388,15 @@ int SDL_WriteToAudioQueue(SDL_AudioQueue *queue, const SDL_AudioSpec *spec, cons
|
||||
|
||||
SDL_AudioTrack *track = queue->tail;
|
||||
|
||||
if ((track != NULL) && !AUDIO_SPECS_EQUAL(track->spec, *spec)) {
|
||||
if ((track) && !AUDIO_SPECS_EQUAL(track->spec, *spec)) {
|
||||
SDL_FlushAudioTrack(track);
|
||||
}
|
||||
|
||||
if ((track == NULL) || (track->write == NULL)) {
|
||||
if ((!track) || (!track->write)) {
|
||||
SDL_AudioTrack *new_track = CreateChunkedAudioTrack(spec, queue->chunk_size);
|
||||
|
||||
if (new_track == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!new_track) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (track) {
|
||||
@ -462,7 +460,7 @@ int SDL_ReadFromAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len)
|
||||
SDL_AudioTrack *track = queue->head;
|
||||
|
||||
for (;;) {
|
||||
if (track == NULL) {
|
||||
if (!track) {
|
||||
return SDL_SetError("Reading past end of queue");
|
||||
}
|
||||
|
||||
@ -478,7 +476,7 @@ int SDL_ReadFromAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len)
|
||||
|
||||
SDL_AudioTrack *next = track->next;
|
||||
|
||||
if (next == NULL) {
|
||||
if (!next) {
|
||||
return SDL_SetError("Reading past end of incomplete track");
|
||||
}
|
||||
|
||||
@ -495,7 +493,7 @@ int SDL_PeekIntoAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len)
|
||||
SDL_AudioTrack *track = queue->head;
|
||||
|
||||
for (;;) {
|
||||
if (track == NULL) {
|
||||
if (!track) {
|
||||
return SDL_SetError("Peeking past end of queue");
|
||||
}
|
||||
|
||||
|
2
external/sdl/SDL/src/audio/SDL_audioqueue.h
vendored
2
external/sdl/SDL/src/audio/SDL_audioqueue.h
vendored
@ -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
|
||||
|
10
external/sdl/SDL/src/audio/SDL_audioresample.c
vendored
10
external/sdl/SDL/src/audio/SDL_audioresample.c
vendored
@ -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
|
||||
@ -23,13 +23,13 @@
|
||||
#include "SDL_sysaudio.h"
|
||||
#include "SDL_audioresample.h"
|
||||
|
||||
/* SDL's resampler uses a "bandlimited interpolation" algorithm:
|
||||
https://ccrma.stanford.edu/~jos/resample/ */
|
||||
// SDL's resampler uses a "bandlimited interpolation" algorithm:
|
||||
// https://ccrma.stanford.edu/~jos/resample/
|
||||
|
||||
#include "SDL_audio_resampler_filter.h"
|
||||
|
||||
/* For a given srcpos, `srcpos + frame` are sampled, where `-RESAMPLER_ZERO_CROSSINGS < frame <= RESAMPLER_ZERO_CROSSINGS`.
|
||||
* Note, when upsampling, it is also possible to start sampling from `srcpos = -1`. */
|
||||
// For a given srcpos, `srcpos + frame` are sampled, where `-RESAMPLER_ZERO_CROSSINGS < frame <= RESAMPLER_ZERO_CROSSINGS`.
|
||||
// Note, when upsampling, it is also possible to start sampling from `srcpos = -1`.
|
||||
#define RESAMPLER_MAX_PADDING_FRAMES (RESAMPLER_ZERO_CROSSINGS + 1)
|
||||
|
||||
#define RESAMPLER_FILTER_INTERP_BITS (32 - RESAMPLER_BITS_PER_ZERO_CROSSING)
|
||||
|
@ -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
|
||||
@ -26,7 +26,7 @@
|
||||
// Internal functions used by SDL_AudioStream for resampling audio.
|
||||
// The resampler uses 32:32 fixed-point arithmetic to track its position.
|
||||
|
||||
Sint64 SDL_GetResampleRate(const int src_rate, const int dst_rate);
|
||||
Sint64 SDL_GetResampleRate(int src_rate, int dst_rate);
|
||||
|
||||
int SDL_GetResamplerHistoryFrames(void);
|
||||
int SDL_GetResamplerPaddingFrames(Sint64 resample_rate);
|
||||
|
181
external/sdl/SDL/src/audio/SDL_audiotypecvt.c
vendored
181
external/sdl/SDL/src/audio/SDL_audiotypecvt.c
vendored
@ -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
|
||||
@ -20,30 +20,33 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
// TODO: NEON is disabled until https://github.com/libsdl-org/SDL/issues/8352 can be fixed
|
||||
#undef SDL_NEON_INTRINSICS
|
||||
|
||||
#ifndef SDL_CPUINFO_DISABLED
|
||||
#if defined(__x86_64__) && defined(SDL_SSE2_INTRINSICS)
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* x86_64 guarantees SSE2. */
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // x86_64 guarantees SSE2.
|
||||
#elif defined(__MACOS__) && defined(SDL_SSE2_INTRINSICS)
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* macOS/Intel guarantees SSE2. */
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // macOS/Intel guarantees SSE2.
|
||||
#elif defined(__ARM_ARCH) && (__ARM_ARCH >= 8) && defined(SDL_NEON_INTRINSICS)
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* ARMv8+ promise NEON. */
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // ARMv8+ promise NEON.
|
||||
#elif defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7) && defined(SDL_NEON_INTRINSICS)
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* All Apple ARMv7 chips promise NEON support. */
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // All Apple ARMv7 chips promise NEON support.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Set to zero if platform is guaranteed to use a SIMD codepath here. */
|
||||
// Set to zero if platform is guaranteed to use a SIMD codepath here.
|
||||
#if !defined(NEED_SCALAR_CONVERTER_FALLBACKS) || defined(SDL_CPUINFO_DISABLED)
|
||||
#define NEED_SCALAR_CONVERTER_FALLBACKS 1
|
||||
#endif
|
||||
|
||||
#define DIVBY2147483648 0.0000000004656612873077392578125f /* 0x1p-31f */
|
||||
#define DIVBY2147483648 0.0000000004656612873077392578125f // 0x1p-31f
|
||||
|
||||
#if NEED_SCALAR_CONVERTER_FALLBACKS
|
||||
|
||||
/* This code requires that floats are in the IEEE-754 binary32 format */
|
||||
// This code requires that floats are in the IEEE-754 binary32 format
|
||||
SDL_COMPILE_TIME_ASSERT(float_bits, sizeof(float) == sizeof(Uint32));
|
||||
|
||||
union float_bits {
|
||||
@ -107,7 +110,7 @@ static void SDL_Convert_S32_to_F32_Scalar(float *dst, const Sint32 *src, int num
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a bit-mask based on the sign-bit. Should optimize to a single arithmetic-shift-right */
|
||||
// Create a bit-mask based on the sign-bit. Should optimize to a single arithmetic-shift-right
|
||||
#define SIGNMASK(x) (Uint32)(0u - ((Uint32)(x) >> 31))
|
||||
|
||||
static void SDL_Convert_F32_to_S8_Scalar(Sint8 *dst, const float *src, int num_samples)
|
||||
@ -198,7 +201,7 @@ static void SDL_Convert_F32_to_S32_Scalar(Sint32 *dst, const float *src, int num
|
||||
|
||||
#undef SIGNMASK
|
||||
|
||||
#endif /* NEED_SCALAR_CONVERTER_FALLBACKS */
|
||||
#endif // NEED_SCALAR_CONVERTER_FALLBACKS
|
||||
|
||||
#ifdef SDL_SSE2_INTRINSICS
|
||||
static void SDL_TARGETING("sse2") SDL_Convert_S8_to_F32_SSE2(float *dst, const Sint8 *src, int num_samples)
|
||||
@ -320,7 +323,7 @@ static void SDL_TARGETING("sse2") SDL_Convert_S32_to_F32_SSE2(float *dst, const
|
||||
{
|
||||
int i = num_samples;
|
||||
|
||||
/* dst[i] = f32(src[i]) / f32(0x80000000) */
|
||||
// dst[i] = f32(src[i]) / f32(0x80000000)
|
||||
const __m128 scaler = _mm_set1_ps(DIVBY2147483648);
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using SSE2)");
|
||||
@ -539,9 +542,9 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S32_SSE2(Sint32 *dst, const
|
||||
#endif
|
||||
|
||||
#ifdef SDL_NEON_INTRINSICS
|
||||
#define DIVBY128 0.0078125f /* 0x1p-7f */
|
||||
#define DIVBY32768 0.000030517578125f /* 0x1p-15f */
|
||||
#define DIVBY8388607 0.00000011920930376163766f /* 0x1.000002p-23f */
|
||||
#define DIVBY128 0.0078125f // 0x1p-7f
|
||||
#define DIVBY32768 0.000030517578125f // 0x1p-15f
|
||||
#define DIVBY8388607 0.00000011920930376163766f // 0x1.000002p-23f
|
||||
|
||||
static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_samples)
|
||||
{
|
||||
@ -552,25 +555,25 @@ static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_sam
|
||||
src += num_samples - 1;
|
||||
dst += num_samples - 1;
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
// Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src)
|
||||
for (i = num_samples; i && (((size_t)(dst - 15)) & 15); --i, --src, --dst) {
|
||||
*dst = ((float)*src) * DIVBY128;
|
||||
}
|
||||
|
||||
src -= 15;
|
||||
dst -= 15; /* adjust to read NEON blocks from the start. */
|
||||
dst -= 15; // adjust to read NEON blocks from the start.
|
||||
SDL_assert(!i || !(((size_t)dst) & 15));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
// Make sure src is aligned too.
|
||||
if (!(((size_t)src) & 15)) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
// Aligned! Do NEON blocks as long as we have 16 bytes available.
|
||||
const int8_t *mmsrc = (const int8_t *)src;
|
||||
const float32x4_t divby128 = vdupq_n_f32(DIVBY128);
|
||||
while (i >= 16) { /* 16 * 8-bit */
|
||||
const int8x16_t bytes = vld1q_s8(mmsrc); /* get 16 sint8 into a NEON register. */
|
||||
const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes)); /* convert top 8 bytes to 8 int16 */
|
||||
const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes)); /* convert bottom 8 bytes to 8 int16 */
|
||||
/* split int16 to two int32, then convert to float, then multiply to normalize, store. */
|
||||
while (i >= 16) { // 16 * 8-bit
|
||||
const int8x16_t bytes = vld1q_s8(mmsrc); // get 16 sint8 into a NEON register.
|
||||
const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes)); // convert top 8 bytes to 8 int16
|
||||
const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes)); // convert bottom 8 bytes to 8 int16
|
||||
// split int16 to two int32, then convert to float, then multiply to normalize, store.
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16lo))), divby128));
|
||||
vst1q_f32(dst + 4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16lo))), divby128));
|
||||
vst1q_f32(dst + 8, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16hi))), divby128));
|
||||
@ -584,9 +587,9 @@ static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_sam
|
||||
}
|
||||
|
||||
src += 15;
|
||||
dst += 15; /* adjust for any scalar finishing. */
|
||||
dst += 15; // adjust for any scalar finishing.
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
// Finish off any leftovers with scalar operations.
|
||||
while (i) {
|
||||
*dst = ((float)*src) * DIVBY128;
|
||||
i--;
|
||||
@ -604,26 +607,26 @@ static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_sam
|
||||
src += num_samples - 1;
|
||||
dst += num_samples - 1;
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
// Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src)
|
||||
for (i = num_samples; i && (((size_t)(dst - 15)) & 15); --i, --src, --dst) {
|
||||
*dst = (((float)*src) * DIVBY128) - 1.0f;
|
||||
}
|
||||
|
||||
src -= 15;
|
||||
dst -= 15; /* adjust to read NEON blocks from the start. */
|
||||
dst -= 15; // adjust to read NEON blocks from the start.
|
||||
SDL_assert(!i || !(((size_t)dst) & 15));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
// Make sure src is aligned too.
|
||||
if (!(((size_t)src) & 15)) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
// Aligned! Do NEON blocks as long as we have 16 bytes available.
|
||||
const uint8_t *mmsrc = (const uint8_t *)src;
|
||||
const float32x4_t divby128 = vdupq_n_f32(DIVBY128);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
while (i >= 16) { /* 16 * 8-bit */
|
||||
const uint8x16_t bytes = vld1q_u8(mmsrc); /* get 16 uint8 into a NEON register. */
|
||||
const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes)); /* convert top 8 bytes to 8 uint16 */
|
||||
const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes)); /* convert bottom 8 bytes to 8 uint16 */
|
||||
/* split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. */
|
||||
while (i >= 16) { // 16 * 8-bit
|
||||
const uint8x16_t bytes = vld1q_u8(mmsrc); // get 16 uint8 into a NEON register.
|
||||
const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes)); // convert top 8 bytes to 8 uint16
|
||||
const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes)); // convert bottom 8 bytes to 8 uint16
|
||||
// split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store.
|
||||
vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128));
|
||||
vst1q_f32(dst + 4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128));
|
||||
vst1q_f32(dst + 8, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128));
|
||||
@ -637,9 +640,9 @@ static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_sam
|
||||
}
|
||||
|
||||
src += 15;
|
||||
dst += 15; /* adjust for any scalar finishing. */
|
||||
dst += 15; // adjust for any scalar finishing.
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
// Finish off any leftovers with scalar operations.
|
||||
while (i) {
|
||||
*dst = (((float)*src) * DIVBY128) - 1.0f;
|
||||
i--;
|
||||
@ -657,22 +660,22 @@ static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_s
|
||||
src += num_samples - 1;
|
||||
dst += num_samples - 1;
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
// Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src)
|
||||
for (i = num_samples; i && (((size_t)(dst - 7)) & 15); --i, --src, --dst) {
|
||||
*dst = ((float)*src) * DIVBY32768;
|
||||
}
|
||||
|
||||
src -= 7;
|
||||
dst -= 7; /* adjust to read NEON blocks from the start. */
|
||||
dst -= 7; // adjust to read NEON blocks from the start.
|
||||
SDL_assert(!i || !(((size_t)dst) & 15));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
// Make sure src is aligned too.
|
||||
if (!(((size_t)src) & 15)) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
// Aligned! Do NEON blocks as long as we have 16 bytes available.
|
||||
const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768);
|
||||
while (i >= 8) { /* 8 * 16-bit */
|
||||
const int16x8_t ints = vld1q_s16((int16_t const *)src); /* get 8 sint16 into a NEON register. */
|
||||
/* split int16 to two int32, then convert to float, then multiply to normalize, store. */
|
||||
while (i >= 8) { // 8 * 16-bit
|
||||
const int16x8_t ints = vld1q_s16((int16_t const *)src); // get 8 sint16 into a NEON register.
|
||||
// split int16 to two int32, then convert to float, then multiply to normalize, store.
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(ints))), divby32768));
|
||||
vst1q_f32(dst + 4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(ints))), divby32768));
|
||||
i -= 8;
|
||||
@ -682,9 +685,9 @@ static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_s
|
||||
}
|
||||
|
||||
src += 7;
|
||||
dst += 7; /* adjust for any scalar finishing. */
|
||||
dst += 7; // adjust for any scalar finishing.
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
// Finish off any leftovers with scalar operations.
|
||||
while (i) {
|
||||
*dst = ((float)*src) * DIVBY32768;
|
||||
i--;
|
||||
@ -699,20 +702,20 @@ static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_s
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
// Get dst aligned to 16 bytes
|
||||
for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = ((float)(*src >> 8)) * DIVBY8388607;
|
||||
}
|
||||
|
||||
SDL_assert(!i || !(((size_t)dst) & 15));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
// Make sure src is aligned too.
|
||||
if (!(((size_t)src) & 15)) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
// Aligned! Do NEON blocks as long as we have 16 bytes available.
|
||||
const float32x4_t divby8388607 = vdupq_n_f32(DIVBY8388607);
|
||||
const int32_t *mmsrc = (const int32_t *)src;
|
||||
while (i >= 4) { /* 4 * sint32 */
|
||||
/* shift out lowest bits so int fits in a float32. Small precision loss, but much faster. */
|
||||
while (i >= 4) { // 4 * sint32
|
||||
// shift out lowest bits so int fits in a float32. Small precision loss, but much faster.
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vshrq_n_s32(vld1q_s32(mmsrc), 8)), divby8388607));
|
||||
i -= 4;
|
||||
mmsrc += 4;
|
||||
@ -721,7 +724,7 @@ static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_s
|
||||
src = (const Sint32 *)mmsrc;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
// Finish off any leftovers with scalar operations.
|
||||
while (i) {
|
||||
*dst = ((float)(*src >> 8)) * DIVBY8388607;
|
||||
i--;
|
||||
@ -736,7 +739,7 @@ static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_sam
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("F32", "S8 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
// Get dst aligned to 16 bytes
|
||||
for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
@ -750,21 +753,21 @@ static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_sam
|
||||
|
||||
SDL_assert(!i || !(((size_t)dst) & 15));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
// Make sure src is aligned too.
|
||||
if (!(((size_t)src) & 15)) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
// Aligned! Do NEON blocks as long as we have 16 bytes available.
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby127 = vdupq_n_f32(127.0f);
|
||||
int8_t *mmdst = (int8_t *)dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints3 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints4 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int8x8_t i8lo = vmovn_s16(vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); /* narrow to sint16, combine, narrow to sint8 */
|
||||
const int8x8_t i8hi = vmovn_s16(vcombine_s16(vmovn_s32(ints3), vmovn_s32(ints4))); /* narrow to sint16, combine, narrow to sint8 */
|
||||
vst1q_s8(mmdst, vcombine_s8(i8lo, i8hi)); /* combine to int8x16_t, store out */
|
||||
while (i >= 16) { // 16 * float32
|
||||
const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby127)); // load 4 floats, clamp, convert to sint32
|
||||
const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby127)); // load 4 floats, clamp, convert to sint32
|
||||
const int32x4_t ints3 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), mulby127)); // load 4 floats, clamp, convert to sint32
|
||||
const int32x4_t ints4 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), mulby127)); // load 4 floats, clamp, convert to sint32
|
||||
const int8x8_t i8lo = vmovn_s16(vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); // narrow to sint16, combine, narrow to sint8
|
||||
const int8x8_t i8hi = vmovn_s16(vcombine_s16(vmovn_s32(ints3), vmovn_s32(ints4))); // narrow to sint16, combine, narrow to sint8
|
||||
vst1q_s8(mmdst, vcombine_s8(i8lo, i8hi)); // combine to int8x16_t, store out
|
||||
i -= 16;
|
||||
src += 16;
|
||||
mmdst += 16;
|
||||
@ -772,7 +775,7 @@ static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_sam
|
||||
dst = (Sint8 *)mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
// Finish off any leftovers with scalar operations.
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
@ -794,7 +797,7 @@ static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_sam
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("F32", "U8 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
// Get dst aligned to 16 bytes
|
||||
for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
@ -808,21 +811,21 @@ static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_sam
|
||||
|
||||
SDL_assert(!i || !(((size_t)dst) & 15));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
// Make sure src is aligned too.
|
||||
if (!(((size_t)src) & 15)) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
// Aligned! Do NEON blocks as long as we have 16 bytes available.
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby127 = vdupq_n_f32(127.0f);
|
||||
uint8_t *mmdst = (uint8_t *)dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints3 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints4 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint8x8_t ui8lo = vmovn_u16(vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); /* narrow to uint16, combine, narrow to uint8 */
|
||||
const uint8x8_t ui8hi = vmovn_u16(vcombine_u16(vmovn_u32(uints3), vmovn_u32(uints4))); /* narrow to uint16, combine, narrow to uint8 */
|
||||
vst1q_u8(mmdst, vcombine_u8(ui8lo, ui8hi)); /* combine to uint8x16_t, store out */
|
||||
while (i >= 16) { // 16 * float32
|
||||
const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32
|
||||
const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32
|
||||
const uint32x4_t uints3 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32
|
||||
const uint32x4_t uints4 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32
|
||||
const uint8x8_t ui8lo = vmovn_u16(vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); // narrow to uint16, combine, narrow to uint8
|
||||
const uint8x8_t ui8hi = vmovn_u16(vcombine_u16(vmovn_u32(uints3), vmovn_u32(uints4))); // narrow to uint16, combine, narrow to uint8
|
||||
vst1q_u8(mmdst, vcombine_u8(ui8lo, ui8hi)); // combine to uint8x16_t, store out
|
||||
i -= 16;
|
||||
src += 16;
|
||||
mmdst += 16;
|
||||
@ -831,7 +834,7 @@ static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_sam
|
||||
dst = (Uint8 *)mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
// Finish off any leftovers with scalar operations.
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
@ -853,7 +856,7 @@ static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_s
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("F32", "S16 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
// Get dst aligned to 16 bytes
|
||||
for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
@ -867,17 +870,17 @@ static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_s
|
||||
|
||||
SDL_assert(!i || !(((size_t)dst) & 15));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
// Make sure src is aligned too.
|
||||
if (!(((size_t)src) & 15)) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
// Aligned! Do NEON blocks as long as we have 16 bytes available.
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby32767 = vdupq_n_f32(32767.0f);
|
||||
int16_t *mmdst = (int16_t *)dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
vst1q_s16(mmdst, vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); /* narrow to sint16, combine, store out. */
|
||||
while (i >= 8) { // 8 * float32
|
||||
const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby32767)); // load 4 floats, clamp, convert to sint32
|
||||
const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby32767)); // load 4 floats, clamp, convert to sint32
|
||||
vst1q_s16(mmdst, vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); // narrow to sint16, combine, store out.
|
||||
i -= 8;
|
||||
src += 8;
|
||||
mmdst += 8;
|
||||
@ -885,7 +888,7 @@ static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_s
|
||||
dst = (Sint16 *)mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
// Finish off any leftovers with scalar operations.
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
@ -907,7 +910,7 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s
|
||||
|
||||
LOG_DEBUG_AUDIO_CONVERT("F32", "S32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
// Get dst aligned to 16 bytes
|
||||
for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
@ -923,12 +926,12 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s
|
||||
SDL_assert(!i || !(((size_t)src) & 15));
|
||||
|
||||
{
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
// Aligned! Do NEON blocks as long as we have 16 bytes available.
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby8388607 = vdupq_n_f32(8388607.0f);
|
||||
int32_t *mmdst = (int32_t *)dst;
|
||||
while (i >= 4) { /* 4 * float32 */
|
||||
while (i >= 4) { // 4 * float32
|
||||
vst1q_s32(mmdst, vshlq_n_s32(vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby8388607)), 8));
|
||||
i -= 4;
|
||||
src += 4;
|
||||
@ -937,7 +940,7 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s
|
||||
dst = (Sint32 *)mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
// Finish off any leftovers with scalar operations.
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
@ -954,7 +957,7 @@ static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_s
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Function pointers set to a CPU-specific implementation. */
|
||||
// Function pointers set to a CPU-specific implementation.
|
||||
void (*SDL_Convert_S8_to_F32)(float *dst, const Sint8 *src, int num_samples) = NULL;
|
||||
void (*SDL_Convert_U8_to_F32)(float *dst, const Uint8 *src, int num_samples) = NULL;
|
||||
void (*SDL_Convert_S16_to_F32)(float *dst, const Sint16 *src, int num_samples) = NULL;
|
||||
|
14
external/sdl/SDL/src/audio/SDL_mixer.c
vendored
14
external/sdl/SDL/src/audio/SDL_mixer.c
vendored
@ -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
|
||||
@ -20,7 +20,7 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/* This provides the default mixing callback for the SDL audio routines */
|
||||
// This provides the default mixing callback for the SDL audio routines
|
||||
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
@ -77,12 +77,12 @@ static const Uint8 mix8[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
/* The volume ranges from 0 - 128 */
|
||||
// The volume ranges from 0 - 128
|
||||
#define ADJUST_VOLUME(type, s, v) ((s) = (type)(((s) * (v)) / SDL_MIX_MAXVOLUME))
|
||||
#define ADJUST_VOLUME_U8(s, v) ((s) = (Uint8)(((((s) - 128) * (v)) / SDL_MIX_MAXVOLUME) + 128))
|
||||
|
||||
|
||||
/* !!! FIXME: this needs some SIMD magic. */
|
||||
// !!! FIXME: this needs some SIMD magic.
|
||||
|
||||
int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format,
|
||||
Uint32 len, int volume)
|
||||
@ -237,7 +237,7 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format,
|
||||
float *dst32 = (float *)dst;
|
||||
float src1, src2;
|
||||
double dst_sample;
|
||||
/* !!! FIXME: are these right? */
|
||||
// !!! FIXME: are these right?
|
||||
const double max_audioval = 3.402823466e+38F;
|
||||
const double min_audioval = -3.402823466e+38F;
|
||||
|
||||
@ -265,7 +265,7 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format,
|
||||
float *dst32 = (float *)dst;
|
||||
float src1, src2;
|
||||
double dst_sample;
|
||||
/* !!! FIXME: are these right? */
|
||||
// !!! FIXME: are these right?
|
||||
const double max_audioval = 3.402823466e+38F;
|
||||
const double min_audioval = -3.402823466e+38F;
|
||||
|
||||
@ -285,7 +285,7 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format,
|
||||
}
|
||||
} break;
|
||||
|
||||
default: /* If this happens... FIXME! */
|
||||
default: // If this happens... FIXME!
|
||||
return SDL_SetError("SDL_MixAudioFormat(): unknown audio format");
|
||||
}
|
||||
|
||||
|
63
external/sdl/SDL/src/audio/SDL_sysaudio.h
vendored
63
external/sdl/SDL/src/audio/SDL_sysaudio.h
vendored
@ -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
|
||||
@ -24,6 +24,8 @@
|
||||
#ifndef SDL_sysaudio_h_
|
||||
#define SDL_sysaudio_h_
|
||||
|
||||
#include "../SDL_hashtable.h"
|
||||
|
||||
#define DEBUG_AUDIOSTREAM 0
|
||||
#define DEBUG_AUDIO_CONVERT 0
|
||||
|
||||
@ -104,6 +106,9 @@ extern void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device);
|
||||
// Backends can call this to get a standardized name for a thread to power a specific audio device.
|
||||
extern char *SDL_GetAudioThreadName(SDL_AudioDevice *device, char *buf, size_t buflen);
|
||||
|
||||
// Backends can call these to change a device's refcount.
|
||||
extern void RefPhysicalAudioDevice(SDL_AudioDevice *device);
|
||||
extern void UnrefPhysicalAudioDevice(SDL_AudioDevice *device);
|
||||
|
||||
// These functions are the heart of the audio threads. Backends can call them directly if they aren't using the SDL-provided thread.
|
||||
extern void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device);
|
||||
@ -128,38 +133,48 @@ typedef struct SDL_AudioDriverImpl
|
||||
int (*OpenDevice)(SDL_AudioDevice *device);
|
||||
void (*ThreadInit)(SDL_AudioDevice *device); // Called by audio thread at start
|
||||
void (*ThreadDeinit)(SDL_AudioDevice *device); // Called by audio thread at end
|
||||
void (*WaitDevice)(SDL_AudioDevice *device);
|
||||
int (*WaitDevice)(SDL_AudioDevice *device);
|
||||
int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); // buffer and buflen are always from GetDeviceBuf, passed here for convenience.
|
||||
Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size);
|
||||
void (*WaitCaptureDevice)(SDL_AudioDevice *device);
|
||||
int (*WaitCaptureDevice)(SDL_AudioDevice *device);
|
||||
int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen);
|
||||
void (*FlushCapture)(SDL_AudioDevice *device);
|
||||
void (*CloseDevice)(SDL_AudioDevice *device);
|
||||
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);
|
||||
|
||||
// Some flags to push duplicate code into the core and reduce #ifdefs.
|
||||
SDL_bool ProvidesOwnCallbackThread; // !!! FIXME: rename this, it's not a callback thread anymore.
|
||||
SDL_bool HasCaptureSupport;
|
||||
SDL_bool OnlyHasDefaultOutputDevice;
|
||||
SDL_bool OnlyHasDefaultCaptureDevice;
|
||||
SDL_bool AllowsArbitraryDeviceNames;
|
||||
SDL_bool OnlyHasDefaultCaptureDevice; // !!! FIXME: is there ever a time where you'd have a default output and not a default capture (or vice versa)?
|
||||
} SDL_AudioDriverImpl;
|
||||
|
||||
|
||||
typedef struct SDL_PendingAudioDeviceEvent
|
||||
{
|
||||
Uint32 type;
|
||||
SDL_AudioDeviceID devid;
|
||||
struct SDL_PendingAudioDeviceEvent *next;
|
||||
} SDL_PendingAudioDeviceEvent;
|
||||
|
||||
typedef struct SDL_AudioDriver
|
||||
{
|
||||
const char *name; // The name of this audio driver
|
||||
const char *desc; // The description of this audio driver
|
||||
SDL_AudioDriverImpl impl; // the backend's interface
|
||||
SDL_RWLock *device_list_lock; // A mutex for device detection
|
||||
SDL_AudioDevice *output_devices; // the list of currently-available audio output devices.
|
||||
SDL_AudioDevice *capture_devices; // the list of currently-available audio capture devices.
|
||||
SDL_RWLock *device_hash_lock; // A rwlock that protects `device_hash`
|
||||
SDL_HashTable *device_hash; // the collection of currently-available audio devices (capture, playback, logical and physical!)
|
||||
SDL_AudioStream *existing_streams; // a list of all existing SDL_AudioStreams.
|
||||
SDL_AudioDeviceID default_output_device_id;
|
||||
SDL_AudioDeviceID default_capture_device_id;
|
||||
SDL_PendingAudioDeviceEvent pending_events;
|
||||
SDL_PendingAudioDeviceEvent *pending_events_tail;
|
||||
|
||||
// !!! FIXME: most (all?) of these don't have to be atomic.
|
||||
SDL_AtomicInt output_device_count;
|
||||
SDL_AtomicInt capture_device_count;
|
||||
SDL_AtomicInt last_device_instance_id; // increments on each device add to provide unique instance IDs
|
||||
SDL_AtomicInt shutting_down; // non-zero during SDL_Quit, so we known not to accept any last-minute device hotplugs.
|
||||
} SDL_AudioDriver;
|
||||
|
||||
@ -169,6 +184,8 @@ struct SDL_AudioStream
|
||||
{
|
||||
SDL_Mutex* lock;
|
||||
|
||||
SDL_PropertiesID props;
|
||||
|
||||
SDL_AudioStreamCallback get_callback;
|
||||
void *get_callback_userdata;
|
||||
SDL_AudioStreamCallback put_callback;
|
||||
@ -240,6 +257,20 @@ struct SDL_AudioDevice
|
||||
// A mutex for locking access to this struct
|
||||
SDL_Mutex *lock;
|
||||
|
||||
// A condition variable to protect device close, where we can't hold the device lock forever.
|
||||
SDL_Condition *close_cond;
|
||||
|
||||
// Reference count of the device; logical devices, device threads, etc, add to this.
|
||||
SDL_AtomicInt refcount;
|
||||
|
||||
// These are, initially, set from current_audio, but we might swap them out with Zombie versions on disconnect/failure.
|
||||
int (*WaitDevice)(SDL_AudioDevice *device);
|
||||
int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen);
|
||||
Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size);
|
||||
int (*WaitCaptureDevice)(SDL_AudioDevice *device);
|
||||
int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen);
|
||||
void (*FlushCapture)(SDL_AudioDevice *device);
|
||||
|
||||
// human-readable name of the device. ("SoundBlaster Pro 16")
|
||||
char *name;
|
||||
|
||||
@ -265,15 +296,9 @@ struct SDL_AudioDevice
|
||||
// non-zero if we are signaling the audio thread to end.
|
||||
SDL_AtomicInt shutdown;
|
||||
|
||||
// non-zero if we want the device to be destroyed (so audio thread knows to do it on termination).
|
||||
SDL_AtomicInt condemned;
|
||||
|
||||
// non-zero if this was a disconnected default device and we're waiting for its replacement.
|
||||
// non-zero if this was a disconnected device and we're waiting for it to be decommissioned.
|
||||
SDL_AtomicInt zombie;
|
||||
|
||||
// non-zero if this has a thread running (which might be `thread` or something provided by the backend!)
|
||||
SDL_AtomicInt thread_alive;
|
||||
|
||||
// SDL_TRUE if this is a capture device instead of an output device
|
||||
SDL_bool iscapture;
|
||||
|
||||
@ -299,10 +324,6 @@ struct SDL_AudioDevice
|
||||
|
||||
// All logical devices associated with this physical device.
|
||||
SDL_LogicalAudioDevice *logical_devices;
|
||||
|
||||
// double-linked list of all physical devices.
|
||||
struct SDL_AudioDevice *prev;
|
||||
struct SDL_AudioDevice *next;
|
||||
};
|
||||
|
||||
typedef struct AudioBootStrap
|
||||
@ -329,7 +350,7 @@ extern AudioBootStrap COREAUDIO_bootstrap;
|
||||
extern AudioBootStrap DISKAUDIO_bootstrap;
|
||||
extern AudioBootStrap DUMMYAUDIO_bootstrap;
|
||||
extern AudioBootStrap AAUDIO_bootstrap;
|
||||
extern AudioBootStrap openslES_bootstrap; // !!! FIXME: capitalize this to match the others
|
||||
extern AudioBootStrap OPENSLES_bootstrap;
|
||||
extern AudioBootStrap ANDROIDAUDIO_bootstrap;
|
||||
extern AudioBootStrap PS2AUDIO_bootstrap;
|
||||
extern AudioBootStrap PSPAUDIO_bootstrap;
|
||||
|
72
external/sdl/SDL/src/audio/SDL_wave.c
vendored
72
external/sdl/SDL/src/audio/SDL_wave.c
vendored
@ -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
|
||||
@ -34,7 +34,7 @@
|
||||
/* Microsoft WAVE file loading routines */
|
||||
|
||||
#include "SDL_wave.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
/* Reads the value stored at the location of the f1 pointer, multiplies it
|
||||
* with the second argument and then stores the result to f1.
|
||||
@ -262,7 +262,7 @@ static void WaveDebugDumpFormat(WaveFile *file, Uint32 rifflen, Uint32 fmtlen, U
|
||||
int res;
|
||||
|
||||
dumpstr = SDL_malloc(bufsize);
|
||||
if (dumpstr == NULL) {
|
||||
if (!dumpstr) {
|
||||
return;
|
||||
}
|
||||
dumpstr[0] = 0;
|
||||
@ -439,8 +439,8 @@ static int MS_ADPCM_Init(WaveFile *file, size_t datalength)
|
||||
|
||||
coeffdata = (MS_ADPCM_CoeffData *)SDL_malloc(sizeof(MS_ADPCM_CoeffData) + coeffcount * 4);
|
||||
file->decoderdata = coeffdata; /* Freed in cleanup. */
|
||||
if (coeffdata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!coeffdata) {
|
||||
return -1;
|
||||
}
|
||||
coeffdata->coeff = &coeffdata->aligndummy;
|
||||
coeffdata->coeffcount = (Uint16)coeffcount;
|
||||
@ -674,7 +674,7 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
/* The output size in bytes. May get modified if data is truncated. */
|
||||
outputsize = (size_t)state.framestotal;
|
||||
if (SafeMult(&outputsize, state.framesize)) {
|
||||
return SDL_OutOfMemory();
|
||||
return SDL_SetError("WAVE file too big");
|
||||
} else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) {
|
||||
return SDL_SetError("WAVE file too big");
|
||||
}
|
||||
@ -682,8 +682,8 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
state.output.pos = 0;
|
||||
state.output.size = outputsize / sizeof(Sint16);
|
||||
state.output.data = (Sint16 *)SDL_calloc(1, outputsize);
|
||||
if (state.output.data == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!state.output.data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
state.cstate = cstate;
|
||||
@ -985,7 +985,7 @@ static int IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state)
|
||||
const size_t remainingbytes = blockleft % subblockframesize;
|
||||
blockframesleft = guaranteedframes;
|
||||
if (remainingbytes > subblockframesize - 4) {
|
||||
blockframesleft += (remainingbytes % 4) * 2;
|
||||
blockframesleft += (Sint64)(remainingbytes % 4) * 2;
|
||||
}
|
||||
/* Signal the truncation. */
|
||||
retval = -1;
|
||||
@ -1065,7 +1065,7 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len
|
||||
/* The output size in bytes. May get modified if data is truncated. */
|
||||
outputsize = (size_t)state.framestotal;
|
||||
if (SafeMult(&outputsize, state.framesize)) {
|
||||
return SDL_OutOfMemory();
|
||||
return SDL_SetError("WAVE file too big");
|
||||
} else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) {
|
||||
return SDL_SetError("WAVE file too big");
|
||||
}
|
||||
@ -1073,14 +1073,14 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len
|
||||
state.output.pos = 0;
|
||||
state.output.size = outputsize / sizeof(Sint16);
|
||||
state.output.data = (Sint16 *)SDL_malloc(outputsize);
|
||||
if (state.output.data == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!state.output.data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cstate = (Sint8 *)SDL_calloc(state.channels, sizeof(Sint8));
|
||||
if (cstate == NULL) {
|
||||
if (!cstate) {
|
||||
SDL_free(state.output.data);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
state.cstate = cstate;
|
||||
|
||||
@ -1221,20 +1221,20 @@ static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
|
||||
sample_count = (size_t)file->sampleframes;
|
||||
if (SafeMult(&sample_count, format->channels)) {
|
||||
return SDL_OutOfMemory();
|
||||
return SDL_SetError("WAVE file too big");
|
||||
}
|
||||
|
||||
expanded_len = sample_count;
|
||||
if (SafeMult(&expanded_len, sizeof(Sint16))) {
|
||||
return SDL_OutOfMemory();
|
||||
return SDL_SetError("WAVE file too big");
|
||||
} else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
|
||||
return SDL_SetError("WAVE file too big");
|
||||
}
|
||||
|
||||
/* 1 to avoid allocating zero bytes, to keep static analysis happy. */
|
||||
src = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1);
|
||||
if (src == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!src) {
|
||||
return -1;
|
||||
}
|
||||
chunk->data = NULL;
|
||||
chunk->size = 0;
|
||||
@ -1352,20 +1352,20 @@ static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 *
|
||||
|
||||
sample_count = (size_t)file->sampleframes;
|
||||
if (SafeMult(&sample_count, format->channels)) {
|
||||
return SDL_OutOfMemory();
|
||||
return SDL_SetError("WAVE file too big");
|
||||
}
|
||||
|
||||
expanded_len = sample_count;
|
||||
if (SafeMult(&expanded_len, sizeof(Sint32))) {
|
||||
return SDL_OutOfMemory();
|
||||
return SDL_SetError("WAVE file too big");
|
||||
} else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
|
||||
return SDL_SetError("WAVE file too big");
|
||||
}
|
||||
|
||||
/* 1 to avoid allocating zero bytes, to keep static analysis happy. */
|
||||
ptr = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1);
|
||||
if (ptr == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This pointer is now invalid. */
|
||||
@ -1421,7 +1421,7 @@ static int PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
|
||||
outputsize = (size_t)file->sampleframes;
|
||||
if (SafeMult(&outputsize, format->blockalign)) {
|
||||
return SDL_OutOfMemory();
|
||||
return SDL_SetError("WAVE file too big");
|
||||
} else if (outputsize > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
|
||||
return SDL_SetError("WAVE file too big");
|
||||
}
|
||||
@ -1440,7 +1440,7 @@ static WaveRiffSizeHint WaveGetRiffSizeHint(void)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_WAVE_RIFF_CHUNK_SIZE);
|
||||
|
||||
if (hint != NULL) {
|
||||
if (hint) {
|
||||
if (SDL_strcmp(hint, "force") == 0) {
|
||||
return RiffSizeForce;
|
||||
} else if (SDL_strcmp(hint, "ignore") == 0) {
|
||||
@ -1459,7 +1459,7 @@ static WaveTruncationHint WaveGetTruncationHint(void)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_WAVE_TRUNCATION);
|
||||
|
||||
if (hint != NULL) {
|
||||
if (hint) {
|
||||
if (SDL_strcmp(hint, "verystrict") == 0) {
|
||||
return TruncVeryStrict;
|
||||
} else if (SDL_strcmp(hint, "strict") == 0) {
|
||||
@ -1478,7 +1478,7 @@ static WaveFactChunkHint WaveGetFactChunkHint(void)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_WAVE_FACT_CHUNK);
|
||||
|
||||
if (hint != NULL) {
|
||||
if (hint) {
|
||||
if (SDL_strcmp(hint, "truncate") == 0) {
|
||||
return FactTruncate;
|
||||
} else if (SDL_strcmp(hint, "strict") == 0) {
|
||||
@ -1495,7 +1495,7 @@ static WaveFactChunkHint WaveGetFactChunkHint(void)
|
||||
|
||||
static void WaveFreeChunkData(WaveChunk *chunk)
|
||||
{
|
||||
if (chunk->data != NULL) {
|
||||
if (chunk->data) {
|
||||
SDL_free(chunk->data);
|
||||
chunk->data = NULL;
|
||||
}
|
||||
@ -1544,8 +1544,8 @@ static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t len
|
||||
|
||||
if (length > 0) {
|
||||
chunk->data = (Uint8 *)SDL_malloc(length);
|
||||
if (chunk->data == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!chunk->data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SDL_RWseek(src, chunk->position, SDL_RW_SEEK_SET) != chunk->position) {
|
||||
@ -1610,8 +1610,8 @@ static int WaveReadFormat(WaveFile *file)
|
||||
return SDL_SetError("Data of WAVE fmt chunk too big");
|
||||
}
|
||||
fmtsrc = SDL_RWFromConstMem(chunk->data, (int)chunk->size);
|
||||
if (fmtsrc == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!fmtsrc) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!SDL_ReadU16LE(fmtsrc, &format->formattag) ||
|
||||
@ -1788,7 +1788,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 *
|
||||
SDL_zero(datachunk);
|
||||
|
||||
envchunkcountlimit = SDL_getenv("SDL_WAVE_CHUNK_LIMIT");
|
||||
if (envchunkcountlimit != NULL) {
|
||||
if (envchunkcountlimit) {
|
||||
unsigned int count;
|
||||
if (SDL_sscanf(envchunkcountlimit, "%u", &count) == 1) {
|
||||
chunkcountlimit = count <= SDL_MAX_UINT32 ? count : SDL_MAX_UINT32;
|
||||
@ -2081,15 +2081,15 @@ int SDL_LoadWAV_RW(SDL_RWops *src, SDL_bool freesrc, SDL_AudioSpec *spec, Uint8
|
||||
WaveFile file;
|
||||
|
||||
/* Make sure we are passed a valid data source */
|
||||
if (src == NULL) {
|
||||
if (!src) {
|
||||
goto done; /* Error may come from RWops. */
|
||||
} else if (spec == NULL) {
|
||||
} else if (!spec) {
|
||||
SDL_InvalidParamError("spec");
|
||||
goto done;
|
||||
} else if (audio_buf == NULL) {
|
||||
} else if (!audio_buf) {
|
||||
SDL_InvalidParamError("audio_buf");
|
||||
goto done;
|
||||
} else if (audio_len == NULL) {
|
||||
} else if (!audio_len) {
|
||||
SDL_InvalidParamError("audio_len");
|
||||
goto done;
|
||||
}
|
||||
|
2
external/sdl/SDL/src/audio/SDL_wave.h
vendored
2
external/sdl/SDL/src/audio/SDL_wave.h
vendored
@ -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
|
||||
|
330
external/sdl/SDL/src/audio/aaudio/SDL_aaudio.c
vendored
330
external/sdl/SDL/src/audio/aaudio/SDL_aaudio.c
vendored
@ -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
|
||||
@ -23,7 +23,6 @@
|
||||
#ifdef SDL_AUDIO_DRIVER_AAUDIO
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_aaudio.h"
|
||||
|
||||
#include "../../core/android/SDL_android.h"
|
||||
@ -37,10 +36,14 @@
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
AAudioStream *stream;
|
||||
Uint8 *mixbuf; // Raw mixing buffer
|
||||
int num_buffers;
|
||||
Uint8 *mixbuf; // Raw mixing buffer
|
||||
size_t mixbuf_bytes; // num_buffers * device->buffer_size
|
||||
size_t callback_bytes;
|
||||
size_t processed_bytes;
|
||||
SDL_Semaphore *semaphore;
|
||||
SDL_AtomicInt error_callback_triggered;
|
||||
int resume; // Resume device if it was paused automatically
|
||||
SDL_bool resume; // Resume device if it was paused automatically
|
||||
};
|
||||
|
||||
// Debug
|
||||
@ -79,54 +82,168 @@ static void AAUDIO_errorCallback(AAudioStream *stream, void *userData, aaudio_re
|
||||
LOGI("SDL AAUDIO_errorCallback: %d - %s", error, ctx.AAudio_convertResultToText(error));
|
||||
|
||||
// You MUST NOT close the audio stream from this callback, so we cannot call SDL_AudioDeviceDisconnected here.
|
||||
// Just flag the device so we can kill it in WaitDevice/PlayDevice instead.
|
||||
// Just flag the device so we can kill it in PlayDevice instead.
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) userData;
|
||||
SDL_AtomicSet(&device->hidden->error_callback_triggered, 1);
|
||||
SDL_AtomicSet(&device->hidden->error_callback_triggered, (int) error); // AAUDIO_OK is zero, so !triggered means no error.
|
||||
SDL_PostSemaphore(device->hidden->semaphore); // in case we're blocking in WaitDevice.
|
||||
}
|
||||
|
||||
// due to the way the aaudio data callback works, PlayDevice is a no-op. The callback collects audio while SDL camps in WaitDevice and
|
||||
// fires a semaphore that will unblock WaitDevice and start a new iteration, so when the callback runs again, WaitDevice is ready
|
||||
// to hand it more data.
|
||||
static aaudio_data_callback_result_t AAUDIO_dataCallback(AAudioStream *stream, void *userData, void *audioData, int32_t numFrames)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) userData;
|
||||
SDL_assert(numFrames == device->sample_frames);
|
||||
struct SDL_PrivateAudioData *hidden = device->hidden;
|
||||
size_t framesize = SDL_AUDIO_FRAMESIZE(device->spec);
|
||||
size_t callback_bytes = numFrames * framesize;
|
||||
size_t old_buffer_index = hidden->callback_bytes / device->buffer_size;
|
||||
|
||||
if (device->iscapture) {
|
||||
SDL_memcpy(device->hidden->mixbuf, audioData, device->buffer_size);
|
||||
const Uint8 *input = (const Uint8 *)audioData;
|
||||
size_t available_bytes = hidden->mixbuf_bytes - (hidden->callback_bytes - hidden->processed_bytes);
|
||||
size_t size = SDL_min(available_bytes, callback_bytes);
|
||||
size_t offset = hidden->callback_bytes % hidden->mixbuf_bytes;
|
||||
size_t end = (offset + size) % hidden->mixbuf_bytes;
|
||||
SDL_assert(size <= hidden->mixbuf_bytes);
|
||||
|
||||
//LOGI("Recorded %zu frames, %zu available, %zu max (%zu written, %zu read)\n", callback_bytes / framesize, available_bytes / framesize, hidden->mixbuf_bytes / framesize, hidden->callback_bytes / framesize, hidden->processed_bytes / framesize);
|
||||
|
||||
if (offset <= end) {
|
||||
SDL_memcpy(&hidden->mixbuf[offset], input, size);
|
||||
} else {
|
||||
size_t partial = (hidden->mixbuf_bytes - offset);
|
||||
SDL_memcpy(&hidden->mixbuf[offset], &input[0], partial);
|
||||
SDL_memcpy(&hidden->mixbuf[0], &input[partial], end);
|
||||
}
|
||||
|
||||
SDL_MemoryBarrierRelease();
|
||||
hidden->callback_bytes += size;
|
||||
|
||||
if (size < callback_bytes) {
|
||||
LOGI("Audio recording overflow, dropped %zu frames\n", (callback_bytes - size) / framesize);
|
||||
}
|
||||
} else {
|
||||
SDL_memcpy(audioData, device->hidden->mixbuf, device->buffer_size);
|
||||
Uint8 *output = (Uint8 *)audioData;
|
||||
size_t available_bytes = (hidden->processed_bytes - hidden->callback_bytes);
|
||||
size_t size = SDL_min(available_bytes, callback_bytes);
|
||||
size_t offset = hidden->callback_bytes % hidden->mixbuf_bytes;
|
||||
size_t end = (offset + size) % hidden->mixbuf_bytes;
|
||||
SDL_assert(size <= hidden->mixbuf_bytes);
|
||||
|
||||
//LOGI("Playing %zu frames, %zu available, %zu max (%zu written, %zu read)\n", callback_bytes / framesize, available_bytes / framesize, hidden->mixbuf_bytes / framesize, hidden->processed_bytes / framesize, hidden->callback_bytes / framesize);
|
||||
|
||||
SDL_MemoryBarrierAcquire();
|
||||
if (offset <= end) {
|
||||
SDL_memcpy(output, &hidden->mixbuf[offset], size);
|
||||
} else {
|
||||
size_t partial = (hidden->mixbuf_bytes - offset);
|
||||
SDL_memcpy(&output[0], &hidden->mixbuf[offset], partial);
|
||||
SDL_memcpy(&output[partial], &hidden->mixbuf[0], end);
|
||||
}
|
||||
hidden->callback_bytes += size;
|
||||
|
||||
if (size < callback_bytes) {
|
||||
LOGI("Audio playback underflow, missed %zu frames\n", (callback_bytes - size) / framesize);
|
||||
SDL_memset(&output[size], device->silence_value, (callback_bytes - size));
|
||||
}
|
||||
}
|
||||
SDL_PostSemaphore(device->hidden->semaphore);
|
||||
|
||||
size_t new_buffer_index = hidden->callback_bytes / device->buffer_size;
|
||||
while (old_buffer_index < new_buffer_index) {
|
||||
// Trigger audio processing
|
||||
SDL_PostSemaphore(hidden->semaphore);
|
||||
++old_buffer_index;
|
||||
}
|
||||
|
||||
return AAUDIO_CALLBACK_RESULT_CONTINUE;
|
||||
}
|
||||
|
||||
static Uint8 *AAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize)
|
||||
{
|
||||
return device->hidden->mixbuf;
|
||||
struct SDL_PrivateAudioData *hidden = device->hidden;
|
||||
size_t offset = (hidden->processed_bytes % hidden->mixbuf_bytes);
|
||||
return &hidden->mixbuf[offset];
|
||||
}
|
||||
|
||||
static void AAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
static int AAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
SDL_WaitSemaphore(device->hidden->semaphore);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
static int BuildAAudioStream(SDL_AudioDevice *device);
|
||||
|
||||
static int RecoverAAudioDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// AAUDIO_dataCallback picks up our work and unblocks AAUDIO_WaitDevice. But make sure we didn't fail here.
|
||||
if (SDL_AtomicGet(&device->hidden->error_callback_triggered)) {
|
||||
SDL_AtomicSet(&device->hidden->error_callback_triggered, 0);
|
||||
return -1;
|
||||
struct SDL_PrivateAudioData *hidden = device->hidden;
|
||||
|
||||
// attempt to build a new stream, in case there's a new default device.
|
||||
ctx.AAudioStream_requestStop(hidden->stream);
|
||||
ctx.AAudioStream_close(hidden->stream);
|
||||
hidden->stream = NULL;
|
||||
|
||||
SDL_aligned_free(hidden->mixbuf);
|
||||
hidden->mixbuf = NULL;
|
||||
|
||||
SDL_DestroySemaphore(hidden->semaphore);
|
||||
hidden->semaphore = NULL;
|
||||
|
||||
const int prev_sample_frames = device->sample_frames;
|
||||
SDL_AudioSpec prevspec;
|
||||
SDL_copyp(&prevspec, &device->spec);
|
||||
|
||||
if (BuildAAudioStream(device) < 0) {
|
||||
return -1; // oh well, we tried.
|
||||
}
|
||||
|
||||
// we don't know the new device spec until we open the new device, so we saved off the old one and force it back
|
||||
// so SDL_AudioDeviceFormatChanged can set up all the important state if necessary and then set it back to the new spec.
|
||||
const int new_sample_frames = device->sample_frames;
|
||||
SDL_AudioSpec newspec;
|
||||
SDL_copyp(&newspec, &device->spec);
|
||||
|
||||
device->sample_frames = prev_sample_frames;
|
||||
SDL_copyp(&device->spec, &prevspec);
|
||||
if (SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames) < 0) {
|
||||
return -1; // ugh
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int AAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
{
|
||||
struct SDL_PrivateAudioData *hidden = device->hidden;
|
||||
|
||||
// AAUDIO_dataCallback picks up our work and unblocks AAUDIO_WaitDevice. But make sure we didn't fail here.
|
||||
const aaudio_result_t err = (aaudio_result_t) SDL_AtomicGet(&hidden->error_callback_triggered);
|
||||
if (err) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "aaudio: Audio device triggered error %d (%s)", (int) err, ctx.AAudio_convertResultToText(err));
|
||||
|
||||
if (RecoverAAudioDevice(device) < 0) {
|
||||
return -1; // oh well, we went down hard.
|
||||
}
|
||||
} else {
|
||||
SDL_MemoryBarrierRelease();
|
||||
hidden->processed_bytes += buflen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no need for a FlushCapture implementation, just don't read mixbuf until the next iteration.
|
||||
static int AAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
|
||||
{
|
||||
const int cpy = SDL_min(buflen, device->buffer_size);
|
||||
SDL_memcpy(buffer, device->hidden->mixbuf, cpy);
|
||||
return cpy;
|
||||
struct SDL_PrivateAudioData *hidden = device->hidden;
|
||||
|
||||
// AAUDIO_dataCallback picks up our work and unblocks AAUDIO_WaitDevice. But make sure we didn't fail here.
|
||||
if (SDL_AtomicGet(&hidden->error_callback_triggered)) {
|
||||
SDL_AtomicSet(&hidden->error_callback_triggered, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_assert(buflen == device->buffer_size); // If this isn't true, we need to change semaphore trigger logic and account for wrapping copies here
|
||||
size_t offset = (hidden->processed_bytes % hidden->mixbuf_bytes);
|
||||
SDL_MemoryBarrierAcquire();
|
||||
SDL_memcpy(buffer, &hidden->mixbuf[offset], buflen);
|
||||
hidden->processed_bytes += buflen;
|
||||
return buflen;
|
||||
}
|
||||
|
||||
static void AAUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
@ -146,34 +263,18 @@ static void AAUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
SDL_DestroySemaphore(hidden->semaphore);
|
||||
}
|
||||
|
||||
SDL_free(hidden->mixbuf);
|
||||
SDL_aligned_free(hidden->mixbuf);
|
||||
SDL_free(hidden);
|
||||
device->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
static int BuildAAudioStream(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *hidden;
|
||||
struct SDL_PrivateAudioData *hidden = device->hidden;
|
||||
const SDL_bool iscapture = device->iscapture;
|
||||
aaudio_result_t res;
|
||||
|
||||
SDL_assert(device->handle != NULL); // AAUDIO_UNSPECIFIED is zero, so legit devices should all be non-zero.
|
||||
|
||||
LOGI(__func__);
|
||||
|
||||
if (iscapture) {
|
||||
if (!Android_JNI_RequestPermission("android.permission.RECORD_AUDIO")) {
|
||||
LOGI("This app doesn't have RECORD_AUDIO permission");
|
||||
return SDL_SetError("This app doesn't have RECORD_AUDIO permission");
|
||||
}
|
||||
}
|
||||
|
||||
hidden = device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
SDL_AtomicSet(&hidden->error_callback_triggered, 0);
|
||||
|
||||
AAudioStreamBuilder *builder = NULL;
|
||||
@ -181,23 +282,19 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
if (res != AAUDIO_OK) {
|
||||
LOGI("SDL Failed AAudio_createStreamBuilder %d", res);
|
||||
return SDL_SetError("SDL Failed AAudio_createStreamBuilder %d", res);
|
||||
} else if (builder == NULL) {
|
||||
} else if (!builder) {
|
||||
LOGI("SDL Failed AAudio_createStreamBuilder - builder NULL");
|
||||
return SDL_SetError("SDL Failed AAudio_createStreamBuilder - builder NULL");
|
||||
}
|
||||
|
||||
// !!! FIXME: call AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); ?
|
||||
|
||||
ctx.AAudioStreamBuilder_setSampleRate(builder, device->spec.freq);
|
||||
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
|
||||
|
||||
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
|
||||
const int aaudio_device_id = (int) ((size_t) device->handle);
|
||||
LOGI("Opening device id %d", aaudio_device_id);
|
||||
ctx.AAudioStreamBuilder_setDeviceId(builder, aaudio_device_id);
|
||||
#endif
|
||||
|
||||
const aaudio_direction_t direction = (iscapture ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT);
|
||||
ctx.AAudioStreamBuilder_setDirection(builder, direction);
|
||||
aaudio_format_t format;
|
||||
#ifdef SET_AUDIO_FORMAT
|
||||
if ((device->spec.format == SDL_AUDIO_S32) && (SDL_GetAndroidSDKVersion() >= 31)) {
|
||||
format = AAUDIO_FORMAT_PCM_I32;
|
||||
} else if (device->spec.format == SDL_AUDIO_F32) {
|
||||
@ -205,41 +302,38 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
} else {
|
||||
format = AAUDIO_FORMAT_PCM_I16; // sint16 is a safe bet for everything else.
|
||||
}
|
||||
|
||||
ctx.AAudioStreamBuilder_setFormat(builder, format);
|
||||
ctx.AAudioStreamBuilder_setSampleRate(builder, device->spec.freq);
|
||||
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
|
||||
#endif
|
||||
|
||||
const aaudio_direction_t direction = (iscapture ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT);
|
||||
ctx.AAudioStreamBuilder_setDirection(builder, direction);
|
||||
ctx.AAudioStreamBuilder_setErrorCallback(builder, AAUDIO_errorCallback, device);
|
||||
ctx.AAudioStreamBuilder_setDataCallback(builder, AAUDIO_dataCallback, device);
|
||||
ctx.AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
|
||||
// Some devices have flat sounding audio when low latency mode is enabled, but this is a better experience for most people
|
||||
if (SDL_GetHintBoolean("SDL_ANDROID_LOW_LATENCY_AUDIO", SDL_TRUE)) {
|
||||
ctx.AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
|
||||
}
|
||||
|
||||
LOGI("AAudio Try to open %u hz %u bit chan %u %s samples %u",
|
||||
device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format),
|
||||
device->spec.channels, SDL_AUDIO_ISBIGENDIAN(device->spec.format) ? "BE" : "LE", device->sample_frames);
|
||||
|
||||
res = ctx.AAudioStreamBuilder_openStream(builder, &hidden->stream);
|
||||
|
||||
if (res != AAUDIO_OK) {
|
||||
LOGI("SDL Failed AAudioStreamBuilder_openStream %d", res);
|
||||
ctx.AAudioStreamBuilder_delete(builder);
|
||||
return SDL_SetError("%s : %s", __func__, ctx.AAudio_convertResultToText(res));
|
||||
}
|
||||
|
||||
device->sample_frames = (int) ctx.AAudioStream_getFramesPerDataCallback(hidden->stream);
|
||||
if (device->sample_frames == AAUDIO_UNSPECIFIED) {
|
||||
// if this happens, figure out a reasonable sample frame count, tear down this stream and force it in a new stream.
|
||||
device->sample_frames = (int) (ctx.AAudioStream_getBufferCapacityInFrames(hidden->stream) / 4);
|
||||
LOGI("AAUDIO: Got a stream with unspecified sample frames per data callback! Retrying with %d frames...", device->sample_frames);
|
||||
ctx.AAudioStream_close(hidden->stream);
|
||||
ctx.AAudioStreamBuilder_setFramesPerDataCallback(builder, device->sample_frames);
|
||||
res = ctx.AAudioStreamBuilder_openStream(builder, &hidden->stream);
|
||||
if (res != AAUDIO_OK) { // oh well, we tried.
|
||||
LOGI("SDL Failed AAudioStreamBuilder_openStream %d", res);
|
||||
ctx.AAudioStreamBuilder_delete(builder);
|
||||
return SDL_SetError("%s : %s", __func__, ctx.AAudio_convertResultToText(res));
|
||||
}
|
||||
}
|
||||
|
||||
ctx.AAudioStreamBuilder_delete(builder);
|
||||
|
||||
device->sample_frames = (int)ctx.AAudioStream_getFramesPerDataCallback(hidden->stream);
|
||||
if (device->sample_frames == AAUDIO_UNSPECIFIED) {
|
||||
// We'll get variable frames in the callback, make sure we have at least half a buffer available
|
||||
device->sample_frames = (int)ctx.AAudioStream_getBufferCapacityInFrames(hidden->stream) / 2;
|
||||
}
|
||||
|
||||
device->spec.freq = ctx.AAudioStream_getSampleRate(hidden->stream);
|
||||
device->spec.channels = ctx.AAudioStream_getChannelCount(hidden->stream);
|
||||
|
||||
@ -254,25 +348,28 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
return SDL_SetError("Got unexpected audio format %d from AAudioStream_getFormat", (int) format);
|
||||
}
|
||||
|
||||
LOGI("AAudio Actually opened %u hz %u bit chan %u %s samples %u",
|
||||
device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format),
|
||||
device->spec.channels, SDL_AUDIO_ISBIGENDIAN(device->spec.format) ? "BE" : "LE", device->sample_frames);
|
||||
|
||||
SDL_UpdatedAudioDeviceFormat(device);
|
||||
|
||||
// Allocate mixing buffer
|
||||
hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
|
||||
if (hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
// Allocate a double buffered mixing buffer
|
||||
hidden->num_buffers = 2;
|
||||
hidden->mixbuf_bytes = (hidden->num_buffers * device->buffer_size);
|
||||
hidden->mixbuf = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), hidden->mixbuf_bytes);
|
||||
if (!hidden->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(hidden->mixbuf, device->silence_value, device->buffer_size);
|
||||
hidden->processed_bytes = 0;
|
||||
hidden->callback_bytes = 0;
|
||||
|
||||
hidden->semaphore = SDL_CreateSemaphore(0);
|
||||
hidden->semaphore = SDL_CreateSemaphore(iscapture ? 0 : hidden->num_buffers);
|
||||
if (!hidden->semaphore) {
|
||||
LOGI("SDL Failed SDL_CreateSemaphore %s iscapture:%d", SDL_GetError(), iscapture);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGI("AAudio Actually opened %u hz %u bit chan %u %s samples %u, buffers %d",
|
||||
device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format),
|
||||
device->spec.channels, SDL_AUDIO_ISBIGENDIAN(device->spec.format) ? "BE" : "LE", device->sample_frames, hidden->num_buffers);
|
||||
|
||||
res = ctx.AAudioStream_requestStart(hidden->stream);
|
||||
if (res != AAUDIO_OK) {
|
||||
LOGI("SDL Failed AAudioStream_requestStart %d iscapture:%d", res, iscapture);
|
||||
@ -280,13 +377,37 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
|
||||
LOGI("SDL AAudioStream_requestStart OK");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
|
||||
SDL_assert(device->handle); // AAUDIO_UNSPECIFIED is zero, so legit devices should all be non-zero.
|
||||
#endif
|
||||
|
||||
LOGI(__func__);
|
||||
|
||||
if (device->iscapture) {
|
||||
if (!Android_JNI_RequestPermission("android.permission.RECORD_AUDIO")) {
|
||||
LOGI("This app doesn't have RECORD_AUDIO permission");
|
||||
return SDL_SetError("This app doesn't have RECORD_AUDIO permission");
|
||||
}
|
||||
}
|
||||
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return BuildAAudioStream(device);
|
||||
}
|
||||
|
||||
static SDL_bool PauseOneDevice(SDL_AudioDevice *device, void *userdata)
|
||||
{
|
||||
struct SDL_PrivateAudioData *hidden = (struct SDL_PrivateAudioData *)device->hidden;
|
||||
if (hidden != NULL) {
|
||||
if (hidden) {
|
||||
if (hidden->stream) {
|
||||
aaudio_result_t res;
|
||||
|
||||
@ -312,7 +433,7 @@ static SDL_bool PauseOneDevice(SDL_AudioDevice *device, void *userdata)
|
||||
// Pause (block) all non already paused audio devices by taking their mixer lock
|
||||
void AAUDIO_PauseDevices(void)
|
||||
{
|
||||
if (ctx.handle != NULL) { // AAUDIO driver is used?
|
||||
if (ctx.handle) { // AAUDIO driver is used?
|
||||
(void) SDL_FindPhysicalAudioDeviceByCallback(PauseOneDevice, NULL);
|
||||
}
|
||||
}
|
||||
@ -321,7 +442,7 @@ void AAUDIO_PauseDevices(void)
|
||||
static SDL_bool ResumeOneDevice(SDL_AudioDevice *device, void *userdata)
|
||||
{
|
||||
struct SDL_PrivateAudioData *hidden = device->hidden;
|
||||
if (hidden != NULL) {
|
||||
if (hidden) {
|
||||
if (hidden->resume) {
|
||||
hidden->resume = SDL_FALSE;
|
||||
SDL_UnlockMutex(device->lock);
|
||||
@ -340,42 +461,11 @@ static SDL_bool ResumeOneDevice(SDL_AudioDevice *device, void *userdata)
|
||||
|
||||
void AAUDIO_ResumeDevices(void)
|
||||
{
|
||||
if (ctx.handle != NULL) { // AAUDIO driver is used?
|
||||
if (ctx.handle) { // AAUDIO driver is used?
|
||||
(void) SDL_FindPhysicalAudioDeviceByCallback(ResumeOneDevice, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// !!! FIXME: do we need this now that we use the callback?
|
||||
/*
|
||||
We can sometimes get into a state where AAudioStream_write() will just block forever until we pause and unpause.
|
||||
None of the standard state queries indicate any problem in my testing. And the error callback doesn't actually get called.
|
||||
But, AAudioStream_getTimestamp() does return AAUDIO_ERROR_INVALID_STATE
|
||||
*/
|
||||
static SDL_bool DetectBrokenPlayStatePerDevice(SDL_AudioDevice *device, void *userdata)
|
||||
{
|
||||
SDL_assert(device != NULL);
|
||||
if (!device->iscapture && device->hidden != NULL) {
|
||||
struct SDL_PrivateAudioData *hidden = device->hidden;
|
||||
int64_t framePosition, timeNanoseconds;
|
||||
aaudio_result_t res = ctx.AAudioStream_getTimestamp(hidden->stream, CLOCK_MONOTONIC, &framePosition, &timeNanoseconds);
|
||||
if (res == AAUDIO_ERROR_INVALID_STATE) {
|
||||
aaudio_stream_state_t currentState = ctx.AAudioStream_getState(hidden->stream);
|
||||
// AAudioStream_getTimestamp() will also return AAUDIO_ERROR_INVALID_STATE while the stream is still initially starting. But we only care if it silently went invalid while playing.
|
||||
if (currentState == AAUDIO_STREAM_STATE_STARTED) {
|
||||
LOGI("SDL AAUDIO_DetectBrokenPlayState: detected invalid audio device state: AAudioStream_getTimestamp result=%d, framePosition=%lld, timeNanoseconds=%lld, getState=%d", (int)res, (long long)framePosition, (long long)timeNanoseconds, (int)currentState);
|
||||
return SDL_TRUE; // this guy.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_FALSE; // enumerate more devices.
|
||||
}
|
||||
|
||||
SDL_bool AAUDIO_DetectBrokenPlayState(void)
|
||||
{
|
||||
return (ctx.handle && SDL_FindPhysicalAudioDeviceByCallback(DetectBrokenPlayStatePerDevice, NULL) != NULL) ? SDL_TRUE : SDL_FALSE;
|
||||
}
|
||||
|
||||
static void AAUDIO_Deinitialize(void)
|
||||
{
|
||||
Android_StopAudioHotplug();
|
||||
@ -405,7 +495,7 @@ static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
SDL_zero(ctx);
|
||||
|
||||
ctx.handle = SDL_LoadObject(LIB_AAUDIO_SO);
|
||||
if (ctx.handle == NULL) {
|
||||
if (!ctx.handle) {
|
||||
LOGI("SDL couldn't find " LIB_AAUDIO_SO);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
@ -417,7 +507,6 @@ static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
}
|
||||
|
||||
impl->ThreadInit = Android_AudioThreadInit;
|
||||
impl->DetectDevices = Android_StartAudioHotplug;
|
||||
impl->Deinitialize = AAUDIO_Deinitialize;
|
||||
impl->OpenDevice = AAUDIO_OpenDevice;
|
||||
impl->CloseDevice = AAUDIO_CloseDevice;
|
||||
@ -429,6 +518,13 @@ static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
||||
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
|
||||
impl->DetectDevices = Android_StartAudioHotplug;
|
||||
#else
|
||||
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
|
||||
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
|
||||
#endif
|
||||
|
||||
LOGI("SDL AAUDIO_Init OK");
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
@ -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
|
||||
@ -27,14 +27,12 @@
|
||||
|
||||
void AAUDIO_ResumeDevices(void);
|
||||
void AAUDIO_PauseDevices(void);
|
||||
SDL_bool AAUDIO_DetectBrokenPlayState(void);
|
||||
|
||||
#else
|
||||
|
||||
#define AAUDIO_ResumeDevices()
|
||||
#define AAUDIO_PauseDevices()
|
||||
#define AAUDIO_DetectBrokenPlayState() (SDL_FALSE)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SDL_aaudio_h_ */
|
||||
#endif // SDL_aaudio_h_
|
||||
|
@ -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
|
||||
@ -33,18 +33,18 @@ SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSharingMode, (AAudioStreamBuilder *
|
||||
SDL_PROC(void, AAudioStreamBuilder_setDirection, (AAudioStreamBuilder * builder, aaudio_direction_t direction))
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setBufferCapacityInFrames, (AAudioStreamBuilder * builder, int32_t numFrames))
|
||||
SDL_PROC(void, AAudioStreamBuilder_setPerformanceMode, (AAudioStreamBuilder * builder, aaudio_performance_mode_t mode))
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setUsage, (AAudioStreamBuilder * builder, aaudio_usage_t usage)) /* API 28 */
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setContentType, (AAudioStreamBuilder * builder, aaudio_content_type_t contentType)) /* API 28 */
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setInputPreset, (AAudioStreamBuilder * builder, aaudio_input_preset_t inputPreset)) /* API 28 */
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setAllowedCapturePolicy, (AAudioStreamBuilder * builder, aaudio_allowed_capture_policy_t capturePolicy)) /* API 29 */
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSessionId, (AAudioStreamBuilder * builder, aaudio_session_id_t sessionId)) /* API 28 */
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setPrivacySensitive, (AAudioStreamBuilder * builder, bool privacySensitive)) /* API 30 */
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setUsage, (AAudioStreamBuilder * builder, aaudio_usage_t usage)) // API 28
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setContentType, (AAudioStreamBuilder * builder, aaudio_content_type_t contentType)) // API 28
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setInputPreset, (AAudioStreamBuilder * builder, aaudio_input_preset_t inputPreset)) // API 28
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setAllowedCapturePolicy, (AAudioStreamBuilder * builder, aaudio_allowed_capture_policy_t capturePolicy)) // API 29
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setSessionId, (AAudioStreamBuilder * builder, aaudio_session_id_t sessionId)) // API 28
|
||||
SDL_PROC_UNUSED(void, AAudioStreamBuilder_setPrivacySensitive, (AAudioStreamBuilder * builder, bool privacySensitive)) // API 30
|
||||
SDL_PROC(void, AAudioStreamBuilder_setDataCallback, (AAudioStreamBuilder * builder, AAudioStream_dataCallback callback, void *userData))
|
||||
SDL_PROC(void, AAudioStreamBuilder_setFramesPerDataCallback, (AAudioStreamBuilder * builder, int32_t numFrames))
|
||||
SDL_PROC(void, AAudioStreamBuilder_setErrorCallback, (AAudioStreamBuilder * builder, AAudioStream_errorCallback callback, void *userData))
|
||||
SDL_PROC(aaudio_result_t, AAudioStreamBuilder_openStream, (AAudioStreamBuilder * builder, AAudioStream **stream))
|
||||
SDL_PROC(aaudio_result_t, AAudioStreamBuilder_delete, (AAudioStreamBuilder * builder))
|
||||
SDL_PROC_UNUSED(aaudio_result_t, AAudioStream_release, (AAudioStream * stream)) /* API 30 */
|
||||
SDL_PROC_UNUSED(aaudio_result_t, AAudioStream_release, (AAudioStream * stream)) // API 30
|
||||
SDL_PROC(aaudio_result_t, AAudioStream_close, (AAudioStream * stream))
|
||||
SDL_PROC(aaudio_result_t, AAudioStream_requestStart, (AAudioStream * stream))
|
||||
SDL_PROC(aaudio_result_t, AAudioStream_requestPause, (AAudioStream * stream))
|
||||
@ -70,13 +70,13 @@ SDL_PROC_UNUSED(aaudio_performance_mode_t, AAudioStream_getPerformanceMode, (AAu
|
||||
SDL_PROC_UNUSED(aaudio_direction_t, AAudioStream_getDirection, (AAudioStream * stream))
|
||||
SDL_PROC_UNUSED(int64_t, AAudioStream_getFramesWritten, (AAudioStream * stream))
|
||||
SDL_PROC_UNUSED(int64_t, AAudioStream_getFramesRead, (AAudioStream * stream))
|
||||
SDL_PROC_UNUSED(aaudio_session_id_t, AAudioStream_getSessionId, (AAudioStream * stream)) /* API 28 */
|
||||
SDL_PROC_UNUSED(aaudio_session_id_t, AAudioStream_getSessionId, (AAudioStream * stream)) // API 28
|
||||
SDL_PROC(aaudio_result_t, AAudioStream_getTimestamp, (AAudioStream * stream, clockid_t clockid, int64_t *framePosition, int64_t *timeNanoseconds))
|
||||
SDL_PROC_UNUSED(aaudio_usage_t, AAudioStream_getUsage, (AAudioStream * stream)) /* API 28 */
|
||||
SDL_PROC_UNUSED(aaudio_content_type_t, AAudioStream_getContentType, (AAudioStream * stream)) /* API 28 */
|
||||
SDL_PROC_UNUSED(aaudio_input_preset_t, AAudioStream_getInputPreset, (AAudioStream * stream)) /* API 28 */
|
||||
SDL_PROC_UNUSED(aaudio_allowed_capture_policy_t, AAudioStream_getAllowedCapturePolicy, (AAudioStream * stream)) /* API 29 */
|
||||
SDL_PROC_UNUSED(bool, AAudioStream_isPrivacySensitive, (AAudioStream * stream)) /* API 30 */
|
||||
SDL_PROC_UNUSED(aaudio_usage_t, AAudioStream_getUsage, (AAudioStream * stream)) // API 28
|
||||
SDL_PROC_UNUSED(aaudio_content_type_t, AAudioStream_getContentType, (AAudioStream * stream)) // API 28
|
||||
SDL_PROC_UNUSED(aaudio_input_preset_t, AAudioStream_getInputPreset, (AAudioStream * stream)) // API 28
|
||||
SDL_PROC_UNUSED(aaudio_allowed_capture_policy_t, AAudioStream_getAllowedCapturePolicy, (AAudioStream * stream)) // API 29
|
||||
SDL_PROC_UNUSED(bool, AAudioStream_isPrivacySensitive, (AAudioStream * stream)) // API 30
|
||||
|
||||
#undef SDL_PROC
|
||||
#undef SDL_PROC_UNUSED
|
||||
|
397
external/sdl/SDL/src/audio/alsa/SDL_alsa_audio.c
vendored
397
external/sdl/SDL/src/audio/alsa/SDL_alsa_audio.c
vendored
@ -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
|
||||
@ -20,26 +20,24 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
// !!! FIXME: Clean out the fprintf and printf calls, replace with SDL_Log
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ALSA
|
||||
|
||||
#ifndef SDL_ALSA_NON_BLOCKING
|
||||
#define SDL_ALSA_NON_BLOCKING 0
|
||||
#endif
|
||||
|
||||
/* without the thread, you will detect devices on startup, but will not get further hotplug events. But that might be okay. */
|
||||
// without the thread, you will detect devices on startup, but will not get further hotplug events. But that might be okay.
|
||||
#ifndef SDL_ALSA_HOTPLUG_THREAD
|
||||
#define SDL_ALSA_HOTPLUG_THREAD 1
|
||||
#endif
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
// Allow access to a raw mixing buffer
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h> /* For kill() */
|
||||
#include <signal.h> // For kill()
|
||||
#include <string.h>
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_alsa_audio.h"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
|
||||
@ -98,15 +96,15 @@ static void *alsa_handle = NULL;
|
||||
static int load_alsa_sym(const char *fn, void **addr)
|
||||
{
|
||||
*addr = SDL_LoadFunction(alsa_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;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
|
||||
// cast funcs to char* first, to please GCC's strict aliasing rules.
|
||||
#define SDL_ALSA_SYM(x) \
|
||||
if (!load_alsa_sym(#x, (void **)(char *)&ALSA_##x)) \
|
||||
return -1
|
||||
@ -167,7 +165,7 @@ static int load_alsa_syms(void)
|
||||
|
||||
static void UnloadALSALibrary(void)
|
||||
{
|
||||
if (alsa_handle != NULL) {
|
||||
if (alsa_handle) {
|
||||
SDL_UnloadObject(alsa_handle);
|
||||
alsa_handle = NULL;
|
||||
}
|
||||
@ -176,11 +174,11 @@ static void UnloadALSALibrary(void)
|
||||
static int LoadALSALibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (alsa_handle == NULL) {
|
||||
if (!alsa_handle) {
|
||||
alsa_handle = SDL_LoadObject(alsa_library);
|
||||
if (alsa_handle == NULL) {
|
||||
if (!alsa_handle) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
// Don't call SDL_SetError(): SDL_LoadObject already did.
|
||||
} else {
|
||||
retval = load_alsa_syms();
|
||||
if (retval < 0) {
|
||||
@ -203,15 +201,35 @@ static int LoadALSALibrary(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_ALSA_DYNAMIC */
|
||||
#endif // SDL_AUDIO_DRIVER_ALSA_DYNAMIC
|
||||
|
||||
typedef struct ALSA_Device
|
||||
{
|
||||
char *name;
|
||||
SDL_bool iscapture;
|
||||
struct ALSA_Device *next;
|
||||
} ALSA_Device;
|
||||
|
||||
static const ALSA_Device default_output_handle = {
|
||||
"default",
|
||||
SDL_FALSE,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ALSA_Device default_capture_handle = {
|
||||
"default",
|
||||
SDL_TRUE,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *get_audio_device(void *handle, const int channels)
|
||||
{
|
||||
SDL_assert(handle != NULL); // SDL2 used NULL to mean "default" but that's not true in SDL3.
|
||||
|
||||
if (SDL_strcmp((const char *) handle, "default") == 0) {
|
||||
const char *device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */
|
||||
if (device != NULL) {
|
||||
ALSA_Device *dev = (ALSA_Device *)handle;
|
||||
if (SDL_strcmp(dev->name, "default") == 0) {
|
||||
const char *device = SDL_getenv("AUDIODEV"); // Is there a standard variable name?
|
||||
if (device) {
|
||||
return device;
|
||||
} else if (channels == 6) {
|
||||
return "plug:surround51";
|
||||
@ -221,15 +239,14 @@ static const char *get_audio_device(void *handle, const int channels)
|
||||
return "default";
|
||||
}
|
||||
|
||||
return (const char *)handle;
|
||||
return dev->name;
|
||||
}
|
||||
|
||||
/* !!! FIXME: is there a channel swizzler in alsalib instead? */
|
||||
/*
|
||||
* https://bugzilla.libsdl.org/show_bug.cgi?id=110
|
||||
* "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
|
||||
* and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
|
||||
*/
|
||||
// !!! FIXME: is there a channel swizzler in alsalib instead?
|
||||
|
||||
// https://bugzilla.libsdl.org/show_bug.cgi?id=110
|
||||
// "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
|
||||
// and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
|
||||
#define SWIZ6(T) \
|
||||
static void swizzle_alsa_channels_6_##T(void *buffer, const Uint32 bufferlen) \
|
||||
{ \
|
||||
@ -246,13 +263,13 @@ static const char *get_audio_device(void *handle, const int channels)
|
||||
} \
|
||||
}
|
||||
|
||||
/* !!! FIXME: is there a channel swizzler in alsalib instead? */
|
||||
/* !!! FIXME: this screams for a SIMD shuffle operation. */
|
||||
/*
|
||||
* https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/mapping-stream-formats-to-speaker-configurations
|
||||
* For Linux ALSA, this appears to be FL-FR-RL-RR-C-LFE-SL-SR
|
||||
* and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-SL-SR-RL-RR"
|
||||
*/
|
||||
|
||||
// !!! FIXME: is there a channel swizzler in alsalib instead?
|
||||
// !!! FIXME: this screams for a SIMD shuffle operation.
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/mapping-stream-formats-to-speaker-configurations
|
||||
// For Linux ALSA, this appears to be FL-FR-RL-RR-C-LFE-SL-SR
|
||||
// and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-SL-SR-RL-RR"
|
||||
#define SWIZ8(T) \
|
||||
static void swizzle_alsa_channels_8_##T(void *buffer, const Uint32 bufferlen) \
|
||||
{ \
|
||||
@ -287,10 +304,8 @@ CHANNEL_SWIZZLE(SWIZ8)
|
||||
#undef SWIZ6
|
||||
#undef SWIZ8
|
||||
|
||||
/*
|
||||
* Called right before feeding device->hidden->mixbuf to the hardware. Swizzle
|
||||
* channels from Windows/Mac order to the format alsalib will want.
|
||||
*/
|
||||
// Called right before feeding device->hidden->mixbuf to the hardware. Swizzle
|
||||
// channels from Windows/Mac order to the format alsalib will want.
|
||||
static void swizzle_alsa_channels(SDL_AudioDevice *device, void *buffer, Uint32 bufferlen)
|
||||
{
|
||||
switch (device->spec.channels) {
|
||||
@ -324,70 +339,66 @@ static void swizzle_alsa_channels(SDL_AudioDevice *device, void *buffer, Uint32
|
||||
}
|
||||
|
||||
#ifdef SND_CHMAP_API_VERSION
|
||||
/* Some devices have the right channel map, no swizzling necessary */
|
||||
// Some devices have the right channel map, no swizzling necessary
|
||||
static void no_swizzle(SDL_AudioDevice *device, void *buffer, Uint32 bufferlen)
|
||||
{
|
||||
}
|
||||
#endif /* SND_CHMAP_API_VERSION */
|
||||
#endif // SND_CHMAP_API_VERSION
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void ALSA_WaitDevice(SDL_AudioDevice *device)
|
||||
// This function waits until it is possible to write a full sound buffer
|
||||
static int ALSA_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
const snd_pcm_sframes_t needed = (snd_pcm_sframes_t)device->sample_frames;
|
||||
const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq);
|
||||
const int delay = SDL_max(fulldelay, 10);
|
||||
|
||||
while (!SDL_AtomicGet(&device->shutdown)) {
|
||||
const snd_pcm_sframes_t rc = ALSA_snd_pcm_avail(device->hidden->pcm_handle);
|
||||
if ((rc < 0) && (rc != -EAGAIN)) {
|
||||
/* Hmm, not much we can do - abort */
|
||||
fprintf(stderr, "ALSA snd_pcm_avail failed (unrecoverable): %s\n",
|
||||
ALSA_snd_strerror(rc));
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
return;
|
||||
} else if (rc < needed) {
|
||||
const Uint32 delay = ((needed - (SDL_max(rc, 0))) * 1000) / device->spec.freq;
|
||||
SDL_Delay(SDL_max(delay, 10));
|
||||
} else {
|
||||
break; /* ready to go! */
|
||||
const int rc = ALSA_snd_pcm_wait(device->hidden->pcm_handle, delay);
|
||||
if (rc < 0 && (rc != -EAGAIN)) {
|
||||
const int status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, rc, 0);
|
||||
if (status < 0) {
|
||||
// Hmm, not much we can do - abort
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_wait failed (unrecoverable): %s", ALSA_snd_strerror(rc));
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rc > 0) {
|
||||
break; // ready to go!
|
||||
}
|
||||
|
||||
// Timed out! Make sure we aren't shutting down and then wait again.
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
{
|
||||
SDL_assert(buffer == device->hidden->mixbuf);
|
||||
Uint8 *sample_buf = device->hidden->mixbuf;
|
||||
Uint8 *sample_buf = (Uint8 *) buffer; // !!! FIXME: deal with this without casting away constness
|
||||
const int frame_size = SDL_AUDIO_FRAMESIZE(device->spec);
|
||||
snd_pcm_uframes_t frames_left = (snd_pcm_uframes_t) (buflen / frame_size);
|
||||
|
||||
device->hidden->swizzle_func(device, sample_buf, frames_left);
|
||||
|
||||
while ((frames_left > 0) && !SDL_AtomicGet(&device->shutdown)) {
|
||||
int status = ALSA_snd_pcm_writei(device->hidden->pcm_handle,
|
||||
sample_buf, frames_left);
|
||||
|
||||
if (status < 0) {
|
||||
if (status == -EAGAIN) {
|
||||
/* Apparently snd_pcm_recover() doesn't handle this case -
|
||||
does it assume snd_pcm_wait() above? */
|
||||
SDL_Delay(1);
|
||||
continue;
|
||||
}
|
||||
status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, status, 0);
|
||||
const int rc = ALSA_snd_pcm_writei(device->hidden->pcm_handle, sample_buf, frames_left);
|
||||
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA PLAYDEVICE: WROTE %d of %d bytes", (rc >= 0) ? ((int) (rc * frame_size)) : rc, (int) (frames_left * frame_size));
|
||||
SDL_assert(rc != 0); // assuming this can't happen if we used snd_pcm_wait and queried for available space.
|
||||
if (rc < 0) {
|
||||
SDL_assert(rc != -EAGAIN); // assuming this can't happen if we used snd_pcm_wait and queried for available space. snd_pcm_recover won't handle it!
|
||||
const int status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, rc, 0);
|
||||
if (status < 0) {
|
||||
/* Hmm, not much we can do - abort */
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
|
||||
"ALSA write failed (unrecoverable): %s",
|
||||
ALSA_snd_strerror(status));
|
||||
// Hmm, not much we can do - abort
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA write failed (unrecoverable): %s", ALSA_snd_strerror(rc));
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
} else if (status == 0) {
|
||||
/* No frames were written (no available space in pcm device).
|
||||
Allow other threads to catch up. */
|
||||
SDL_Delay((frames_left / 2 * 1000) / device->spec.freq);
|
||||
}
|
||||
|
||||
sample_buf += status * frame_size;
|
||||
frames_left -= status;
|
||||
sample_buf += rc * frame_size;
|
||||
frames_left -= rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -395,45 +406,54 @@ static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buf
|
||||
|
||||
static Uint8 *ALSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
{
|
||||
snd_pcm_sframes_t rc = ALSA_snd_pcm_avail(device->hidden->pcm_handle);
|
||||
if (rc <= 0) {
|
||||
// Wait a bit and try again, maybe the hardware isn't quite ready yet?
|
||||
SDL_Delay(1);
|
||||
|
||||
rc = ALSA_snd_pcm_avail(device->hidden->pcm_handle);
|
||||
if (rc <= 0) {
|
||||
// We'll catch it next time
|
||||
*buffer_size = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const int requested_frames = SDL_min(device->sample_frames, rc);
|
||||
const int requested_bytes = requested_frames * SDL_AUDIO_FRAMESIZE(device->spec);
|
||||
SDL_assert(requested_bytes <= *buffer_size);
|
||||
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA GETDEVICEBUF: NEED %d BYTES", requested_bytes);
|
||||
*buffer_size = requested_bytes;
|
||||
return device->hidden->mixbuf;
|
||||
}
|
||||
|
||||
static int ALSA_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
|
||||
{
|
||||
Uint8 *sample_buf = (Uint8 *)buffer;
|
||||
const int frame_size = SDL_AUDIO_FRAMESIZE(device->spec);
|
||||
const int total_frames = buflen / frame_size;
|
||||
snd_pcm_uframes_t frames_left = total_frames;
|
||||
|
||||
SDL_assert((buflen % frame_size) == 0);
|
||||
|
||||
while ((frames_left > 0) && !SDL_AtomicGet(&device->shutdown)) {
|
||||
int status = ALSA_snd_pcm_readi(device->hidden->pcm_handle,
|
||||
sample_buf, frames_left);
|
||||
const snd_pcm_sframes_t total_available = ALSA_snd_pcm_avail(device->hidden->pcm_handle);
|
||||
const int total_frames = SDL_min(buflen / frame_size, total_available);
|
||||
|
||||
if (status == -EAGAIN) {
|
||||
break; // Can this even happen? Go back to WaitCaptureDevice, where the device lock isn't held.
|
||||
} else if (status < 0) {
|
||||
/*printf("ALSA: capture error %d\n", status);*/
|
||||
status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, status, 0);
|
||||
if (status < 0) {
|
||||
/* Hmm, not much we can do - abort */
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
|
||||
"ALSA read failed (unrecoverable): %s\n",
|
||||
ALSA_snd_strerror(status));
|
||||
return -1;
|
||||
}
|
||||
break; // Go back to WaitCaptureDevice, where the device lock isn't held.
|
||||
const int rc = ALSA_snd_pcm_readi(device->hidden->pcm_handle, buffer, total_frames);
|
||||
|
||||
SDL_assert(rc != -EAGAIN); // assuming this can't happen if we used snd_pcm_wait and queried for available space. snd_pcm_recover won't handle it!
|
||||
|
||||
if (rc < 0) {
|
||||
const int status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, rc, 0);
|
||||
if (status < 0) {
|
||||
// Hmm, not much we can do - abort
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA read failed (unrecoverable): %s", ALSA_snd_strerror(rc));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*printf("ALSA: captured %d bytes\n", status * frame_size);*/
|
||||
sample_buf += status * frame_size;
|
||||
frames_left -= status;
|
||||
return 0; // go back to WaitDevice and try again.
|
||||
} else if (rc > 0) {
|
||||
device->hidden->swizzle_func(device, buffer, total_frames - rc);
|
||||
}
|
||||
|
||||
device->hidden->swizzle_func(device, buffer, total_frames - frames_left);
|
||||
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: captured %d bytes", rc * frame_size);
|
||||
|
||||
return (total_frames - frames_left) * frame_size;
|
||||
return rc * frame_size;
|
||||
}
|
||||
|
||||
static void ALSA_FlushCapture(SDL_AudioDevice *device)
|
||||
@ -445,9 +465,7 @@ static void ALSA_CloseDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
if (device->hidden) {
|
||||
if (device->hidden->pcm_handle) {
|
||||
/* Wait for the submitted audio to drain
|
||||
ALSA_snd_pcm_drop() can hang, so don't use that.
|
||||
*/
|
||||
// Wait for the submitted audio to drain. ALSA_snd_pcm_drop() can hang, so don't use that.
|
||||
SDL_Delay(((device->sample_frames * 1000) / device->spec.freq) * 2);
|
||||
ALSA_snd_pcm_close(device->hidden->pcm_handle);
|
||||
}
|
||||
@ -463,11 +481,11 @@ static int ALSA_set_buffer_size(SDL_AudioDevice *device, snd_pcm_hw_params_t *pa
|
||||
snd_pcm_uframes_t persize;
|
||||
unsigned int periods;
|
||||
|
||||
/* Copy the hardware parameters for this setup */
|
||||
// Copy the hardware parameters for this setup
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
ALSA_snd_pcm_hw_params_copy(hwparams, params);
|
||||
|
||||
/* Attempt to match the period size to the requested buffer size */
|
||||
// Attempt to match the period size to the requested buffer size
|
||||
persize = device->sample_frames;
|
||||
status = ALSA_snd_pcm_hw_params_set_period_size_near(
|
||||
device->hidden->pcm_handle, hwparams, &persize, NULL);
|
||||
@ -475,7 +493,7 @@ static int ALSA_set_buffer_size(SDL_AudioDevice *device, snd_pcm_hw_params_t *pa
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Need to at least double buffer */
|
||||
// Need to at least double buffer
|
||||
periods = 2;
|
||||
status = ALSA_snd_pcm_hw_params_set_periods_min(
|
||||
device->hidden->pcm_handle, hwparams, &periods, NULL);
|
||||
@ -489,7 +507,7 @@ static int ALSA_set_buffer_size(SDL_AudioDevice *device, snd_pcm_hw_params_t *pa
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* "set" the hardware with the desired parameters */
|
||||
// "set" the hardware with the desired parameters
|
||||
status = ALSA_snd_pcm_hw_params(device->hidden->pcm_handle, hwparams);
|
||||
if (status < 0) {
|
||||
return -1;
|
||||
@ -497,14 +515,14 @@ static int ALSA_set_buffer_size(SDL_AudioDevice *device, snd_pcm_hw_params_t *pa
|
||||
|
||||
device->sample_frames = persize;
|
||||
|
||||
/* This is useful for debugging */
|
||||
// This is useful for debugging
|
||||
if (SDL_getenv("SDL_AUDIO_ALSA_DEBUG")) {
|
||||
snd_pcm_uframes_t bufsize;
|
||||
|
||||
ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize);
|
||||
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
|
||||
"ALSA: period size = %ld, periods = %u, buffer size = %lu\n",
|
||||
"ALSA: period size = %ld, periods = %u, buffer size = %lu",
|
||||
persize, periods, bufsize);
|
||||
}
|
||||
|
||||
@ -516,14 +534,14 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
const SDL_bool iscapture = device->iscapture;
|
||||
int status = 0;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Open the audio device */
|
||||
/* Name of device should depend on # channels in spec */
|
||||
// Open the audio device
|
||||
// Name of device should depend on # channels in spec
|
||||
snd_pcm_t *pcm_handle = NULL;
|
||||
status = ALSA_snd_pcm_open(&pcm_handle,
|
||||
get_audio_device(device->handle, device->spec.channels),
|
||||
@ -536,7 +554,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
device->hidden->pcm_handle = pcm_handle;
|
||||
|
||||
/* Figure out what the hardware is capable of */
|
||||
// Figure out what the hardware is capable of
|
||||
snd_pcm_hw_params_t *hwparams = NULL;
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
|
||||
@ -544,14 +562,14 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
return SDL_SetError("ALSA: Couldn't get hardware config: %s", ALSA_snd_strerror(status));
|
||||
}
|
||||
|
||||
/* SDL only uses interleaved sample output */
|
||||
// SDL only uses interleaved sample output
|
||||
status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (status < 0) {
|
||||
return SDL_SetError("ALSA: Couldn't set interleaved access: %s", ALSA_snd_strerror(status));
|
||||
}
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
// Try for a closest match on audio format
|
||||
snd_pcm_format_t format = 0;
|
||||
const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format);
|
||||
SDL_AudioFormat test_format;
|
||||
@ -593,9 +611,8 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
device->spec.format = test_format;
|
||||
|
||||
/* Validate number of channels and determine if swizzling is necessary
|
||||
* Assume original swizzling, until proven otherwise.
|
||||
*/
|
||||
// Validate number of channels and determine if swizzling is necessary.
|
||||
// Assume original swizzling, until proven otherwise.
|
||||
device->hidden->swizzle_func = swizzle_alsa_channels;
|
||||
#ifdef SND_CHMAP_API_VERSION
|
||||
snd_pcm_chmap_t *chmap = ALSA_snd_pcm_get_chmap(pcm_handle);
|
||||
@ -607,11 +624,11 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
device->hidden->swizzle_func = no_swizzle;
|
||||
}
|
||||
}
|
||||
free(chmap); /* This should NOT be SDL_free() */
|
||||
free(chmap); // This should NOT be SDL_free()
|
||||
}
|
||||
#endif /* SND_CHMAP_API_VERSION */
|
||||
#endif // SND_CHMAP_API_VERSION
|
||||
|
||||
/* Set the number of channels */
|
||||
// Set the number of channels
|
||||
status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams,
|
||||
device->spec.channels);
|
||||
unsigned int channels = device->spec.channels;
|
||||
@ -623,7 +640,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
device->spec.channels = channels;
|
||||
}
|
||||
|
||||
/* Set the audio rate */
|
||||
// Set the audio rate
|
||||
unsigned int rate = device->spec.freq;
|
||||
status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
|
||||
&rate, NULL);
|
||||
@ -632,13 +649,13 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
device->spec.freq = rate;
|
||||
|
||||
/* Set the buffer size, in samples */
|
||||
// Set the buffer size, in samples
|
||||
status = ALSA_set_buffer_size(device, hwparams);
|
||||
if (status < 0) {
|
||||
return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
|
||||
}
|
||||
|
||||
/* Set the software parameters */
|
||||
// Set the software parameters
|
||||
snd_pcm_sw_params_t *swparams = NULL;
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
|
||||
@ -665,8 +682,8 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
// Allocate mixing buffer
|
||||
if (!iscapture) {
|
||||
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
|
||||
if (device->hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size);
|
||||
}
|
||||
@ -679,35 +696,26 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
ALSA_snd_pcm_start(pcm_handle);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 0;
|
||||
return 0; // We're ready to rock and roll. :-)
|
||||
}
|
||||
|
||||
typedef struct ALSA_Device
|
||||
{
|
||||
char *name;
|
||||
SDL_bool iscapture;
|
||||
struct ALSA_Device *next;
|
||||
} ALSA_Device;
|
||||
|
||||
static void add_device(const SDL_bool iscapture, const char *name, void *hint, ALSA_Device **pSeen)
|
||||
{
|
||||
ALSA_Device *dev = SDL_malloc(sizeof(ALSA_Device));
|
||||
char *desc;
|
||||
char *handle = NULL;
|
||||
char *ptr;
|
||||
|
||||
if (dev == NULL) {
|
||||
if (!dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not all alsa devices are enumerable via snd_device_name_get_hint
|
||||
(i.e. bluetooth devices). Therefore if hint is passed in to this
|
||||
function as NULL, assume name contains desc.
|
||||
Make sure not to free the storage associated with desc in this case */
|
||||
// Not all alsa devices are enumerable via snd_device_name_get_hint
|
||||
// (i.e. bluetooth devices). Therefore if hint is passed in to this
|
||||
// function as NULL, assume name contains desc.
|
||||
// Make sure not to free the storage associated with desc in this case
|
||||
if (hint) {
|
||||
desc = ALSA_snd_device_name_get_hint(hint, "DESC");
|
||||
if (desc == NULL) {
|
||||
if (!desc) {
|
||||
SDL_free(dev);
|
||||
return;
|
||||
}
|
||||
@ -717,34 +725,34 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A
|
||||
|
||||
SDL_assert(name != NULL);
|
||||
|
||||
/* some strings have newlines, like "HDA NVidia, HDMI 0\nHDMI Audio Output".
|
||||
just chop the extra lines off, this seems to get a reasonable device
|
||||
name without extra details. */
|
||||
// some strings have newlines, like "HDA NVidia, HDMI 0\nHDMI Audio Output".
|
||||
// just chop the extra lines off, this seems to get a reasonable device
|
||||
// name without extra details.
|
||||
ptr = SDL_strchr(desc, '\n');
|
||||
if (ptr != NULL) {
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
/*printf("ALSA: adding %s device '%s' (%s)\n", iscapture ? "capture" : "output", name, desc);*/
|
||||
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: adding %s device '%s' (%s)", iscapture ? "capture" : "output", name, desc);
|
||||
|
||||
handle = SDL_strdup(name);
|
||||
if (handle == NULL) {
|
||||
dev->name = SDL_strdup(name);
|
||||
if (!dev->name) {
|
||||
if (hint) {
|
||||
free(desc); /* This should NOT be SDL_free() */
|
||||
free(desc); // This should NOT be SDL_free()
|
||||
}
|
||||
SDL_free(dev->name);
|
||||
SDL_free(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Note that spec is NULL, because we are required to open the device before
|
||||
* acquiring the mix format, making this information inaccessible at
|
||||
* enumeration time
|
||||
*/
|
||||
SDL_AddAudioDevice(iscapture, desc, NULL, handle);
|
||||
// Note that spec is NULL, because we are required to open the device before
|
||||
// acquiring the mix format, making this information inaccessible at
|
||||
// enumeration time
|
||||
SDL_AddAudioDevice(iscapture, desc, NULL, dev);
|
||||
if (hint) {
|
||||
free(desc); /* This should NOT be SDL_free() */
|
||||
free(desc); // This should NOT be SDL_free()
|
||||
}
|
||||
dev->name = handle;
|
||||
|
||||
dev->iscapture = iscapture;
|
||||
dev->next = *pSeen;
|
||||
*pSeen = dev;
|
||||
@ -770,13 +778,13 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de
|
||||
unseen = hotplug_devices;
|
||||
seen = NULL;
|
||||
|
||||
/* Apparently there are several different ways that ALSA lists
|
||||
actual hardware. It could be prefixed with "hw:" or "default:"
|
||||
or "sysdefault:" and maybe others. Go through the list and see
|
||||
if we can find a preferred prefix for the system. */
|
||||
// Apparently there are several different ways that ALSA lists
|
||||
// actual hardware. It could be prefixed with "hw:" or "default:"
|
||||
// or "sysdefault:" and maybe others. Go through the list and see
|
||||
// if we can find a preferred prefix for the system.
|
||||
for (int i = 0; hints[i]; i++) {
|
||||
char *name = ALSA_snd_device_name_get_hint(hints[i], "NAME");
|
||||
if (name == NULL) {
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -797,31 +805,31 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de
|
||||
}
|
||||
}
|
||||
|
||||
free(name); /* This should NOT be SDL_free() */
|
||||
free(name); // This should NOT be SDL_free()
|
||||
}
|
||||
}
|
||||
|
||||
/* look through the list of device names to find matches */
|
||||
// look through the list of device names to find matches
|
||||
if (match || (has_default >= 0)) { // did we find a device name prefix we like at all...?
|
||||
for (int i = 0; hints[i]; i++) {
|
||||
char *name = ALSA_snd_device_name_get_hint(hints[i], "NAME");
|
||||
if (name == NULL) {
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// only want physical hardware interfaces
|
||||
const SDL_bool is_default = (has_default == i) ? SDL_TRUE : SDL_FALSE;
|
||||
if (is_default || (match != NULL && SDL_strncmp(name, match, match_len) == 0)) {
|
||||
const SDL_bool is_default = (has_default == i);
|
||||
if (is_default || (match && SDL_strncmp(name, match, match_len) == 0)) {
|
||||
char *ioid = ALSA_snd_device_name_get_hint(hints[i], "IOID");
|
||||
const SDL_bool isoutput = (ioid == NULL) || (SDL_strcmp(ioid, "Output") == 0);
|
||||
const SDL_bool isinput = (ioid == NULL) || (SDL_strcmp(ioid, "Input") == 0);
|
||||
const SDL_bool isoutput = (!ioid) || (SDL_strcmp(ioid, "Output") == 0);
|
||||
const SDL_bool isinput = (!ioid) || (SDL_strcmp(ioid, "Input") == 0);
|
||||
SDL_bool have_output = SDL_FALSE;
|
||||
SDL_bool have_input = SDL_FALSE;
|
||||
|
||||
free(ioid);
|
||||
free(ioid); // This should NOT be SDL_free()
|
||||
|
||||
if (!isoutput && !isinput) {
|
||||
free(name);
|
||||
free(name); // This should NOT be SDL_free()
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -831,7 +839,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de
|
||||
} else if (has_default_capture && isinput) {
|
||||
*has_default_capture = SDL_TRUE;
|
||||
}
|
||||
free(name);
|
||||
free(name); // This should NOT be SDL_free()
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -866,20 +874,20 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de
|
||||
}
|
||||
}
|
||||
|
||||
free(name); /* This should NOT be SDL_free() */
|
||||
free(name); // This should NOT be SDL_free()
|
||||
}
|
||||
}
|
||||
|
||||
ALSA_snd_device_name_free_hint(hints);
|
||||
|
||||
hotplug_devices = seen; /* now we have a known-good list of attached devices. */
|
||||
hotplug_devices = seen; // now we have a known-good list of attached devices.
|
||||
|
||||
/* report anything still in unseen as removed. */
|
||||
// report anything still in unseen as removed.
|
||||
ALSA_Device *next = NULL;
|
||||
for (ALSA_Device *dev = unseen; dev; dev = next) {
|
||||
/*printf("ALSA: removing usb %s device '%s'\n", dev->iscapture ? "capture" : "output", dev->name);*/
|
||||
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name);
|
||||
next = dev->next;
|
||||
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev->name));
|
||||
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev));
|
||||
SDL_free(dev->name);
|
||||
SDL_free(dev);
|
||||
}
|
||||
@ -895,13 +903,13 @@ static int SDLCALL ALSA_HotplugThread(void *arg)
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
|
||||
|
||||
while (!SDL_AtomicGet(&ALSA_hotplug_shutdown)) {
|
||||
/* Block awhile before checking again, unless we're told to stop. */
|
||||
// Block awhile before checking again, unless we're told to stop.
|
||||
const Uint64 ticks = SDL_GetTicks() + 5000;
|
||||
while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && SDL_GetTicks() < ticks) {
|
||||
SDL_Delay(100);
|
||||
}
|
||||
|
||||
ALSA_HotplugIteration(NULL, NULL); /* run the check. */
|
||||
ALSA_HotplugIteration(NULL, NULL); // run the check.
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -913,43 +921,46 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice
|
||||
// ALSA doesn't have a concept of a changeable default device, afaik, so we expose a generic default
|
||||
// device here. It's the best we can do at this level.
|
||||
SDL_bool has_default_output = SDL_FALSE, has_default_capture = SDL_FALSE;
|
||||
ALSA_HotplugIteration(&has_default_output, &has_default_capture); // run once now before a thread continues to check. */
|
||||
ALSA_HotplugIteration(&has_default_output, &has_default_capture); // run once now before a thread continues to check.
|
||||
if (has_default_output) {
|
||||
*default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, SDL_strdup("default"));
|
||||
*default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, (void*)&default_output_handle);
|
||||
}
|
||||
if (has_default_capture) {
|
||||
*default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, SDL_strdup("default"));
|
||||
*default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, (void*)&default_capture_handle);
|
||||
}
|
||||
|
||||
#if SDL_ALSA_HOTPLUG_THREAD
|
||||
SDL_AtomicSet(&ALSA_hotplug_shutdown, 0);
|
||||
ALSA_hotplug_thread = SDL_CreateThread(ALSA_HotplugThread, "SDLHotplugALSA", NULL);
|
||||
/* if the thread doesn't spin, oh well, you just don't get further hotplug events. */
|
||||
// if the thread doesn't spin, oh well, you just don't get further hotplug events.
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ALSA_Deinitialize(void)
|
||||
static void ALSA_DeinitializeStart(void)
|
||||
{
|
||||
ALSA_Device *dev;
|
||||
ALSA_Device *next;
|
||||
|
||||
#if SDL_ALSA_HOTPLUG_THREAD
|
||||
if (ALSA_hotplug_thread != NULL) {
|
||||
if (ALSA_hotplug_thread) {
|
||||
SDL_AtomicSet(&ALSA_hotplug_shutdown, 1);
|
||||
SDL_WaitThread(ALSA_hotplug_thread, NULL);
|
||||
ALSA_hotplug_thread = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shutting down! Clean up any data we've gathered. */
|
||||
// Shutting down! Clean up any data we've gathered.
|
||||
for (dev = hotplug_devices; dev; dev = next) {
|
||||
/*printf("ALSA: at shutdown, removing %s device '%s'\n", dev->iscapture ? "capture" : "output", dev->name);*/
|
||||
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: at shutdown, removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name);
|
||||
next = dev->next;
|
||||
SDL_free(dev->name);
|
||||
SDL_free(dev);
|
||||
}
|
||||
hotplug_devices = NULL;
|
||||
}
|
||||
|
||||
static void ALSA_Deinitialize(void)
|
||||
{
|
||||
UnloadALSALibrary();
|
||||
}
|
||||
|
||||
@ -959,13 +970,13 @@ static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl)
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = ALSA_DetectDevices;
|
||||
impl->OpenDevice = ALSA_OpenDevice;
|
||||
impl->WaitDevice = ALSA_WaitDevice;
|
||||
impl->GetDeviceBuf = ALSA_GetDeviceBuf;
|
||||
impl->PlayDevice = ALSA_PlayDevice;
|
||||
impl->CloseDevice = ALSA_CloseDevice;
|
||||
impl->DeinitializeStart = ALSA_DeinitializeStart;
|
||||
impl->Deinitialize = ALSA_Deinitialize;
|
||||
impl->WaitCaptureDevice = ALSA_WaitDevice;
|
||||
impl->CaptureFromDevice = ALSA_CaptureFromDevice;
|
||||
@ -973,11 +984,11 @@ static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl)
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
AudioBootStrap ALSA_bootstrap = {
|
||||
"alsa", "ALSA PCM audio", ALSA_Init, SDL_FALSE
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_ALSA */
|
||||
#endif // SDL_AUDIO_DRIVER_ALSA
|
||||
|
10
external/sdl/SDL/src/audio/alsa/SDL_alsa_audio.h
vendored
10
external/sdl/SDL/src/audio/alsa/SDL_alsa_audio.h
vendored
@ -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
|
||||
@ -29,14 +29,14 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The audio device handle */
|
||||
// The audio device handle
|
||||
snd_pcm_t *pcm_handle;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
// Raw mixing buffer
|
||||
Uint8 *mixbuf;
|
||||
|
||||
/* swizzle function */
|
||||
// swizzle function
|
||||
void (*swizzle_func)(SDL_AudioDevice *_this, void *buffer, Uint32 bufferlen);
|
||||
};
|
||||
|
||||
#endif /* SDL_ALSA_audio_h_ */
|
||||
#endif // SDL_ALSA_audio_h_
|
||||
|
@ -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
|
||||
@ -25,7 +25,6 @@
|
||||
// Output audio to Android (legacy interface)
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_androidaudio.h"
|
||||
|
||||
#include "../../core/android/SDL_android.h"
|
||||
@ -43,8 +42,8 @@ static SDL_AudioDevice *captureDevice = NULL;
|
||||
static int ANDROIDAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SDL_bool iscapture = device->iscapture;
|
||||
@ -132,13 +131,13 @@ void ANDROIDAUDIO_PauseDevices(void)
|
||||
{
|
||||
// TODO: Handle multiple devices?
|
||||
struct SDL_PrivateAudioData *hidden;
|
||||
if (audioDevice != NULL && audioDevice->hidden != NULL) {
|
||||
if (audioDevice && audioDevice->hidden) {
|
||||
hidden = (struct SDL_PrivateAudioData *)audioDevice->hidden;
|
||||
SDL_LockMutex(audioDevice->lock);
|
||||
hidden->resume = SDL_TRUE;
|
||||
}
|
||||
|
||||
if (captureDevice != NULL && captureDevice->hidden != NULL) {
|
||||
if (captureDevice && captureDevice->hidden) {
|
||||
hidden = (struct SDL_PrivateAudioData *)captureDevice->hidden;
|
||||
SDL_LockMutex(captureDevice->lock);
|
||||
hidden->resume = SDL_TRUE;
|
||||
@ -150,7 +149,7 @@ void ANDROIDAUDIO_ResumeDevices(void)
|
||||
{
|
||||
// TODO: Handle multiple devices?
|
||||
struct SDL_PrivateAudioData *hidden;
|
||||
if (audioDevice != NULL && audioDevice->hidden != NULL) {
|
||||
if (audioDevice && audioDevice->hidden) {
|
||||
hidden = (struct SDL_PrivateAudioData *)audioDevice->hidden;
|
||||
if (hidden->resume) {
|
||||
hidden->resume = SDL_FALSE;
|
||||
@ -158,7 +157,7 @@ void ANDROIDAUDIO_ResumeDevices(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (captureDevice != NULL && captureDevice->hidden != NULL) {
|
||||
if (captureDevice && captureDevice->hidden) {
|
||||
hidden = (struct SDL_PrivateAudioData *)captureDevice->hidden;
|
||||
if (hidden->resume) {
|
||||
hidden->resume = SDL_FALSE;
|
||||
@ -172,7 +171,7 @@ static SDL_bool ANDROIDAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
// !!! FIXME: if on Android API < 24, DetectDevices and Deinitialize should be NULL and OnlyHasDefaultOutputDevice and OnlyHasDefaultCaptureDevice should be SDL_TRUE, since audio device enum and hotplug appears to require Android 7.0+.
|
||||
impl->ThreadInit = Android_AudioThreadInit;
|
||||
impl->DetectDevices = Android_StartAudioHotplug;
|
||||
impl->Deinitialize = Android_StopAudioHotplug;
|
||||
impl->DeinitializeStart = Android_StopAudioHotplug;
|
||||
impl->OpenDevice = ANDROIDAUDIO_OpenDevice;
|
||||
impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
|
||||
impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
|
||||
|
@ -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
|
||||
@ -35,4 +35,4 @@ static void ANDROIDAUDIO_PauseDevices(void) {}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SDL_androidaudio_h_ */
|
||||
#endif // SDL_androidaudio_h_
|
||||
|
@ -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
|
||||
@ -39,7 +39,7 @@
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
/* Things named "Master" were renamed to "Main" in macOS 12.0's SDK. */
|
||||
// Things named "Master" were renamed to "Main" in macOS 12.0's SDK.
|
||||
#ifdef MACOSX_COREAUDIO
|
||||
#include <AvailabilityMacros.h>
|
||||
#ifndef MAC_OS_VERSION_12_0
|
||||
@ -65,4 +65,4 @@ struct SDL_PrivateAudioData
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* SDL_coreaudio_h_ */
|
||||
#endif // SDL_coreaudio_h_
|
||||
|
@ -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
|
||||
@ -22,7 +22,6 @@
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_COREAUDIO
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_coreaudio.h"
|
||||
#include "../../thread/SDL_systhread.h"
|
||||
@ -79,9 +78,9 @@ static OSStatus DeviceAliveNotification(AudioObjectID devid, UInt32 num_addr, co
|
||||
|
||||
SDL_bool dead = SDL_FALSE;
|
||||
if (error == kAudioHardwareBadDeviceError) {
|
||||
dead = SDL_TRUE; /* device was unplugged. */
|
||||
dead = SDL_TRUE; // device was unplugged.
|
||||
} else if ((error == kAudioHardwareNoError) && (!alive)) {
|
||||
dead = SDL_TRUE; /* device died in some other way. */
|
||||
dead = SDL_TRUE; // device died in some other way.
|
||||
}
|
||||
|
||||
if (dead) {
|
||||
@ -186,7 +185,7 @@ static void RefreshPhysicalDevices(void)
|
||||
|
||||
CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), kCFStringEncodingUTF8);
|
||||
char *name = (char *)SDL_malloc(len + 1);
|
||||
SDL_bool usable = ((name != NULL) && (CFStringGetCString(cfstr, name, len + 1, kCFStringEncodingUTF8))) ? SDL_TRUE : SDL_FALSE;
|
||||
SDL_bool usable = ((name != NULL) && (CFStringGetCString(cfstr, name, len + 1, kCFStringEncodingUTF8)));
|
||||
|
||||
CFRelease(cfstr);
|
||||
|
||||
@ -232,7 +231,7 @@ static OSStatus DeviceListChangedNotification(AudioObjectID systemObj, UInt32 nu
|
||||
static OSStatus DefaultAudioDeviceChangedNotification(AudioObjectID inObjectID, const AudioObjectPropertyAddress *addr)
|
||||
{
|
||||
AudioDeviceID devid;
|
||||
Uint32 size = sizeof(devid);
|
||||
UInt32 size = sizeof(devid);
|
||||
if (AudioObjectGetPropertyData(inObjectID, addr, 0, NULL, &size, &devid) == noErr) {
|
||||
SDL_DefaultAudioDeviceChanged(SDL_FindPhysicalAudioDeviceByHandle((void *)((size_t)devid)));
|
||||
}
|
||||
@ -263,7 +262,7 @@ static void COREAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioD
|
||||
|
||||
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, DeviceListChangedNotification, NULL);
|
||||
|
||||
/* Get the Device ID */
|
||||
// Get the Device ID
|
||||
UInt32 size;
|
||||
AudioDeviceID devid;
|
||||
|
||||
@ -428,7 +427,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b
|
||||
/* AVAudioSessionCategoryOptionAllowBluetooth isn't available in the SDK for
|
||||
Apple TV but is still needed in order to output to Bluetooth devices.
|
||||
*/
|
||||
options |= 0x4; /* AVAudioSessionCategoryOptionAllowBluetooth; */
|
||||
options |= 0x4; // AVAudioSessionCategoryOptionAllowBluetooth;
|
||||
}
|
||||
if (category == AVAudioSessionCategoryPlayAndRecord) {
|
||||
options |= AVAudioSessionCategoryOptionAllowBluetoothA2DP |
|
||||
@ -441,7 +440,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b
|
||||
|
||||
if ([session respondsToSelector:@selector(setCategory:mode:options:error:)]) {
|
||||
if (![session.category isEqualToString:category] || session.categoryOptions != options) {
|
||||
/* Stop the current session so we don't interrupt other application audio */
|
||||
// Stop the current session so we don't interrupt other application audio
|
||||
PauseAudioDevices();
|
||||
[session setActive:NO error:nil];
|
||||
session_active = SDL_FALSE;
|
||||
@ -454,7 +453,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b
|
||||
}
|
||||
} else {
|
||||
if (![session.category isEqualToString:category]) {
|
||||
/* Stop the current session so we don't interrupt other application audio */
|
||||
// Stop the current session so we don't interrupt other application audio
|
||||
PauseAudioDevices();
|
||||
[session setActive:NO error:nil];
|
||||
session_active = SDL_FALSE;
|
||||
@ -498,7 +497,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b
|
||||
/* An interruption end notification is not guaranteed to be sent if
|
||||
we were previously interrupted... resuming if needed when the app
|
||||
becomes active seems to be the way to go. */
|
||||
// Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications. johna
|
||||
// Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications.
|
||||
[center addObserver:listener
|
||||
selector:@selector(applicationBecameActive:)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
@ -717,7 +716,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device)
|
||||
|
||||
SDL_UpdatedAudioDeviceFormat(device); // make sure this is correct.
|
||||
|
||||
/* Set the channel layout for the audio queue */
|
||||
// Set the channel layout for the audio queue
|
||||
AudioChannelLayout layout;
|
||||
SDL_zero(layout);
|
||||
switch (device->spec.channels) {
|
||||
@ -740,7 +739,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device)
|
||||
layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_A;
|
||||
break;
|
||||
case 7:
|
||||
/* FIXME: Need to move channel[4] (BC) to channel[6] */
|
||||
// FIXME: Need to move channel[4] (BC) to channel[6]
|
||||
layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_6_1_A;
|
||||
break;
|
||||
case 8:
|
||||
@ -763,14 +762,14 @@ static int PrepareAudioQueue(SDL_AudioDevice *device)
|
||||
|
||||
int numAudioBuffers = 2;
|
||||
const double msecs = (device->sample_frames / ((double)device->spec.freq)) * 1000.0;
|
||||
if (msecs < MINIMUM_AUDIO_BUFFER_TIME_MS) { /* use more buffers if we have a VERY small sample set. */
|
||||
if (msecs < MINIMUM_AUDIO_BUFFER_TIME_MS) { // use more buffers if we have a VERY small sample set.
|
||||
numAudioBuffers = ((int)SDL_ceil(MINIMUM_AUDIO_BUFFER_TIME_MS / msecs) * 2);
|
||||
}
|
||||
|
||||
device->hidden->numAudioBuffers = numAudioBuffers;
|
||||
device->hidden->audioBuffer = SDL_calloc(numAudioBuffers, sizeof(AudioQueueBufferRef));
|
||||
if (device->hidden->audioBuffer == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if DEBUG_COREAUDIO
|
||||
@ -782,7 +781,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device)
|
||||
CHECK_RESULT("AudioQueueAllocateBuffer");
|
||||
SDL_memset(device->hidden->audioBuffer[i]->mAudioData, device->silence_value, device->hidden->audioBuffer[i]->mAudioDataBytesCapacity);
|
||||
device->hidden->audioBuffer[i]->mAudioDataByteSize = device->hidden->audioBuffer[i]->mAudioDataBytesCapacity;
|
||||
/* !!! FIXME: should we use AudioQueueEnqueueBufferWithParameters and specify all frames be "trimmed" so these are immediately ready to refill with SDL callback data? */
|
||||
// !!! FIXME: should we use AudioQueueEnqueueBufferWithParameters and specify all frames be "trimmed" so these are immediately ready to refill with SDL callback data?
|
||||
result = AudioQueueEnqueueBuffer(device->hidden->audioQueue, device->hidden->audioBuffer[i], 0, NULL);
|
||||
CHECK_RESULT("AudioQueueEnqueueBuffer");
|
||||
}
|
||||
@ -831,10 +830,10 @@ static int AudioQueueThreadEntry(void *arg)
|
||||
|
||||
static int COREAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef MACOSX_COREAUDIO
|
||||
@ -842,7 +841,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Stop CoreAudio from doing expensive audio rate conversion */
|
||||
// Stop CoreAudio from doing expensive audio rate conversion
|
||||
@autoreleasepool {
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
[session setPreferredSampleRate:device->spec.freq error:nil];
|
||||
@ -856,12 +855,12 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
device->spec.channels = session.preferredOutputNumberOfChannels;
|
||||
}
|
||||
#else
|
||||
/* Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS */
|
||||
#endif /* TARGET_OS_TV */
|
||||
// Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS
|
||||
#endif // TARGET_OS_TV
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup a AudioStreamBasicDescription with the requested format */
|
||||
// Setup a AudioStreamBasicDescription with the requested format
|
||||
AudioStreamBasicDescription *strdesc = &device->hidden->strdesc;
|
||||
strdesc->mFormatID = kAudioFormatLinearPCM;
|
||||
strdesc->mFormatFlags = kLinearPCMFormatFlagIsPacked;
|
||||
@ -872,7 +871,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format);
|
||||
SDL_AudioFormat test_format;
|
||||
while ((test_format = *(closefmts++)) != 0) {
|
||||
/* CoreAudio handles most of SDL's formats natively. */
|
||||
// CoreAudio handles most of SDL's formats natively.
|
||||
switch (test_format) {
|
||||
case SDL_AUDIO_U8:
|
||||
case SDL_AUDIO_S8:
|
||||
@ -890,7 +889,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!test_format) { /* shouldn't happen, but just in case... */
|
||||
if (!test_format) { // shouldn't happen, but just in case...
|
||||
return SDL_SetError("%s: Unsupported audio format", "coreaudio");
|
||||
}
|
||||
device->spec.format = test_format;
|
||||
@ -914,10 +913,10 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This has to init in a new thread so it can get its own CFRunLoop. :/ */
|
||||
// This has to init in a new thread so it can get its own CFRunLoop. :/
|
||||
device->hidden->ready_semaphore = SDL_CreateSemaphore(0);
|
||||
if (!device->hidden->ready_semaphore) {
|
||||
return -1; /* oh well. */
|
||||
return -1; // oh well.
|
||||
}
|
||||
|
||||
char threadname[64];
|
||||
@ -940,7 +939,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
return (device->hidden->thread != NULL) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void COREAUDIO_Deinitialize(void)
|
||||
static void COREAUDIO_DeinitializeStart(void)
|
||||
{
|
||||
#ifdef MACOSX_COREAUDIO
|
||||
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, DeviceListChangedNotification, NULL);
|
||||
@ -951,14 +950,13 @@ static void COREAUDIO_Deinitialize(void)
|
||||
|
||||
static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = COREAUDIO_OpenDevice;
|
||||
impl->PlayDevice = COREAUDIO_PlayDevice;
|
||||
impl->GetDeviceBuf = COREAUDIO_GetDeviceBuf;
|
||||
impl->CaptureFromDevice = COREAUDIO_CaptureFromDevice;
|
||||
impl->FlushCapture = COREAUDIO_FlushCapture;
|
||||
impl->CloseDevice = COREAUDIO_CloseDevice;
|
||||
impl->Deinitialize = COREAUDIO_Deinitialize;
|
||||
impl->DeinitializeStart = COREAUDIO_DeinitializeStart;
|
||||
|
||||
#ifdef MACOSX_COREAUDIO
|
||||
impl->DetectDevices = COREAUDIO_DetectDevices;
|
||||
@ -971,11 +969,11 @@ static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->ProvidesOwnCallbackThread = SDL_TRUE;
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
AudioBootStrap COREAUDIO_bootstrap = {
|
||||
"coreaudio", "CoreAudio", COREAUDIO_Init, SDL_FALSE
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_COREAUDIO */
|
||||
#endif // SDL_AUDIO_DRIVER_COREAUDIO
|
||||
|
@ -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
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_DSOUND
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_directsound.h"
|
||||
#include <mmreg.h>
|
||||
#ifdef HAVE_MMDEVICEAPI_H
|
||||
@ -62,7 +62,7 @@ static void DSOUND_Unload(void)
|
||||
pDirectSoundCaptureEnumerateW = NULL;
|
||||
pGetDeviceID = NULL;
|
||||
|
||||
if (DSoundDLL != NULL) {
|
||||
if (DSoundDLL) {
|
||||
SDL_UnloadObject(DSoundDLL);
|
||||
DSoundDLL = NULL;
|
||||
}
|
||||
@ -75,7 +75,7 @@ static int DSOUND_Load(void)
|
||||
DSOUND_Unload();
|
||||
|
||||
DSoundDLL = SDL_LoadObject("DSOUND.DLL");
|
||||
if (DSoundDLL == NULL) {
|
||||
if (!DSoundDLL) {
|
||||
SDL_SetError("DirectSound: failed to load DSOUND.DLL");
|
||||
} else {
|
||||
// Now make sure we have DirectX 8 or better...
|
||||
@ -176,7 +176,7 @@ static BOOL CALLBACK FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVO
|
||||
FindAllDevsData *data = (FindAllDevsData *) userdata;
|
||||
if (guid != NULL) { // skip default device
|
||||
char *str = WIN_LookupAudioDeviceName(desc, guid);
|
||||
if (str != NULL) {
|
||||
if (str) {
|
||||
LPGUID cpyguid = (LPGUID)SDL_malloc(sizeof(GUID));
|
||||
if (cpyguid) {
|
||||
SDL_copyp(cpyguid, guid);
|
||||
@ -225,64 +225,39 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevi
|
||||
|
||||
}
|
||||
|
||||
static void DSOUND_WaitDevice(SDL_AudioDevice *device)
|
||||
static int DSOUND_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
DWORD status = 0;
|
||||
DWORD cursor = 0;
|
||||
DWORD junk = 0;
|
||||
HRESULT result = DS_OK;
|
||||
|
||||
/* Semi-busy wait, since we have no way of getting play notification
|
||||
on a primary mixing buffer located in hardware (DirectX 5.0)
|
||||
*/
|
||||
result = IDirectSoundBuffer_GetCurrentPosition(device->hidden->mixbuf,
|
||||
&junk, &cursor);
|
||||
if (result != DS_OK) {
|
||||
if (result == DSERR_BUFFERLOST) {
|
||||
IDirectSoundBuffer_Restore(device->hidden->mixbuf);
|
||||
}
|
||||
#ifdef DEBUG_SOUND
|
||||
SetDSerror("DirectSound GetCurrentPosition", result);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
while ((cursor / device->buffer_size) == device->hidden->lastchunk) {
|
||||
if (SDL_AtomicGet(&device->shutdown)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Delay(1);
|
||||
while (!SDL_AtomicGet(&device->shutdown)) {
|
||||
DWORD status = 0;
|
||||
DWORD cursor = 0;
|
||||
DWORD junk = 0;
|
||||
HRESULT result = DS_OK;
|
||||
|
||||
// Try to restore a lost sound buffer
|
||||
IDirectSoundBuffer_GetStatus(device->hidden->mixbuf, &status);
|
||||
if (status & DSBSTATUS_BUFFERLOST) {
|
||||
IDirectSoundBuffer_Restore(device->hidden->mixbuf);
|
||||
IDirectSoundBuffer_GetStatus(device->hidden->mixbuf, &status);
|
||||
if (status & DSBSTATUS_BUFFERLOST) {
|
||||
break;
|
||||
} else if (!(status & DSBSTATUS_PLAYING)) {
|
||||
result = IDirectSoundBuffer_Play(device->hidden->mixbuf, 0, 0, DSBPLAY_LOOPING);
|
||||
} else {
|
||||
// Find out where we are playing
|
||||
result = IDirectSoundBuffer_GetCurrentPosition(device->hidden->mixbuf, &junk, &cursor);
|
||||
if ((result == DS_OK) && ((cursor / device->buffer_size) != device->hidden->lastchunk)) {
|
||||
break; // ready for next chunk!
|
||||
}
|
||||
}
|
||||
if (!(status & DSBSTATUS_PLAYING)) {
|
||||
result = IDirectSoundBuffer_Play(device->hidden->mixbuf, 0, 0,
|
||||
DSBPLAY_LOOPING);
|
||||
if (result == DS_OK) {
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG_SOUND
|
||||
SetDSerror("DirectSound Play", result);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Find out where we are playing
|
||||
result = IDirectSoundBuffer_GetCurrentPosition(device->hidden->mixbuf,
|
||||
&junk, &cursor);
|
||||
if (result != DS_OK) {
|
||||
SetDSerror("DirectSound GetCurrentPosition", result);
|
||||
return;
|
||||
if ((result != DS_OK) && (result != DSERR_BUFFERLOST)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Delay(1); // not ready yet; sleep a bit.
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DSOUND_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
@ -354,19 +329,20 @@ static Uint8 *DSOUND_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
return device->hidden->locked_buf;
|
||||
}
|
||||
|
||||
static void DSOUND_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
static int DSOUND_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = device->hidden;
|
||||
while (!SDL_AtomicGet(&device->shutdown)) {
|
||||
DWORD junk, cursor;
|
||||
if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) {
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
return;
|
||||
return -1;
|
||||
} else if ((cursor / device->buffer_size) != h->lastchunk) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
|
||||
@ -408,18 +384,18 @@ static void DSOUND_FlushCapture(SDL_AudioDevice *device)
|
||||
static void DSOUND_CloseDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
if (device->hidden) {
|
||||
if (device->hidden->mixbuf != NULL) {
|
||||
if (device->hidden->mixbuf) {
|
||||
IDirectSoundBuffer_Stop(device->hidden->mixbuf);
|
||||
IDirectSoundBuffer_Release(device->hidden->mixbuf);
|
||||
}
|
||||
if (device->hidden->sound != NULL) {
|
||||
if (device->hidden->sound) {
|
||||
IDirectSound_Release(device->hidden->sound);
|
||||
}
|
||||
if (device->hidden->capturebuf != NULL) {
|
||||
if (device->hidden->capturebuf) {
|
||||
IDirectSoundCaptureBuffer_Stop(device->hidden->capturebuf);
|
||||
IDirectSoundCaptureBuffer_Release(device->hidden->capturebuf);
|
||||
}
|
||||
if (device->hidden->capture != NULL) {
|
||||
if (device->hidden->capture) {
|
||||
IDirectSoundCapture_Release(device->hidden->capture);
|
||||
}
|
||||
SDL_free(device->hidden);
|
||||
@ -515,8 +491,8 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Open the audio device
|
||||
@ -647,15 +623,21 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device)
|
||||
return 0; // good to go.
|
||||
}
|
||||
|
||||
static void DSOUND_Deinitialize(void)
|
||||
static void DSOUND_DeinitializeStart(void)
|
||||
{
|
||||
#ifdef HAVE_MMDEVICEAPI_H
|
||||
if (SupportsIMMDevice) {
|
||||
SDL_IMMDevice_Quit();
|
||||
SupportsIMMDevice = SDL_FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DSOUND_Deinitialize(void)
|
||||
{
|
||||
DSOUND_Unload();
|
||||
#ifdef HAVE_MMDEVICEAPI_H
|
||||
SupportsIMMDevice = SDL_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl)
|
||||
@ -665,7 +647,7 @@ static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl)
|
||||
}
|
||||
|
||||
#ifdef HAVE_MMDEVICEAPI_H
|
||||
SupportsIMMDevice = !(SDL_IMMDevice_Init() < 0);
|
||||
SupportsIMMDevice = !(SDL_IMMDevice_Init(NULL) < 0);
|
||||
#endif
|
||||
|
||||
impl->DetectDevices = DSOUND_DetectDevices;
|
||||
@ -678,6 +660,7 @@ static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->FlushCapture = DSOUND_FlushCapture;
|
||||
impl->CloseDevice = DSOUND_CloseDevice;
|
||||
impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
|
||||
impl->DeinitializeStart = DSOUND_DeinitializeStart;
|
||||
impl->Deinitialize = DSOUND_Deinitialize;
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
@ -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
|
||||
|
24
external/sdl/SDL/src/audio/disk/SDL_diskaudio.c
vendored
24
external/sdl/SDL/src/audio/disk/SDL_diskaudio.c
vendored
@ -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
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
// Output raw audio data to a file.
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_diskaudio.h"
|
||||
|
||||
// !!! FIXME: these should be SDL hints, not environment variables.
|
||||
@ -35,9 +35,10 @@
|
||||
#define DISKDEFAULT_INFILE "sdlaudio-in.raw"
|
||||
#define DISKENVR_IODELAY "SDL_DISKAUDIODELAY"
|
||||
|
||||
static void DISKAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
static int DISKAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
SDL_Delay(device->hidden->io_delay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DISKAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
|
||||
@ -86,7 +87,7 @@ static void DISKAUDIO_FlushCapture(SDL_AudioDevice *device)
|
||||
static void DISKAUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
if (device->hidden) {
|
||||
if (device->hidden->io != NULL) {
|
||||
if (device->hidden->io) {
|
||||
SDL_RWclose(device->hidden->io);
|
||||
}
|
||||
SDL_free(device->hidden->mixbuf);
|
||||
@ -98,7 +99,7 @@ static void DISKAUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
static const char *get_filename(const SDL_bool iscapture)
|
||||
{
|
||||
const char *devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE);
|
||||
if (devname == NULL) {
|
||||
if (!devname) {
|
||||
devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE;
|
||||
}
|
||||
return devname;
|
||||
@ -111,11 +112,11 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
const char *envr = SDL_getenv(DISKENVR_IODELAY);
|
||||
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (envr != NULL) {
|
||||
if (envr) {
|
||||
device->hidden->io_delay = SDL_atoi(envr);
|
||||
} else {
|
||||
device->hidden->io_delay = ((device->sample_frames * 1000) / device->spec.freq);
|
||||
@ -123,15 +124,15 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
// Open the "audio device"
|
||||
device->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
|
||||
if (device->hidden->io == NULL) {
|
||||
if (!device->hidden->io) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Allocate mixing buffer
|
||||
if (!iscapture) {
|
||||
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
|
||||
if (device->hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size);
|
||||
}
|
||||
@ -160,7 +161,6 @@ static SDL_bool DISKAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->CloseDevice = DISKAUDIO_CloseDevice;
|
||||
impl->DetectDevices = DISKAUDIO_DetectDevices;
|
||||
|
||||
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE;
|
||||
|
@ -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
|
||||
@ -27,10 +27,10 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
// The file descriptor for the audio device
|
||||
SDL_RWops *io;
|
||||
Uint32 io_delay;
|
||||
Uint8 *mixbuf;
|
||||
};
|
||||
|
||||
#endif /* SDL_diskaudio_h_ */
|
||||
#endif // SDL_diskaudio_h_
|
||||
|
44
external/sdl/SDL/src/audio/dsp/SDL_dspaudio.c
vendored
44
external/sdl/SDL/src/audio/dsp/SDL_dspaudio.c
vendored
@ -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
|
||||
@ -24,8 +24,8 @@
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_OSS
|
||||
|
||||
#include <stdio.h> /* For perror() */
|
||||
#include <string.h> /* For strerror() */
|
||||
#include <stdio.h> // For perror()
|
||||
#include <string.h> // For strerror()
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@ -36,7 +36,6 @@
|
||||
|
||||
#include <sys/soundcard.h>
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_audiodev_c.h"
|
||||
#include "../../SDL_utils_c.h"
|
||||
#include "SDL_dspaudio.h"
|
||||
@ -71,8 +70,8 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that.
|
||||
@ -97,7 +96,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
|
||||
return SDL_SetError("Couldn't get audio format list");
|
||||
}
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
// Try for a closest match on audio format
|
||||
int format = 0;
|
||||
SDL_AudioFormat test_format;
|
||||
const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format);
|
||||
@ -156,7 +155,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
device->spec.freq = value;
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
// Calculate the final parameters for this audio specification
|
||||
SDL_UpdatedAudioDeviceFormat(device);
|
||||
|
||||
/* Determine the power of two of the fragment size
|
||||
@ -168,9 +167,9 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
|
||||
while ((0x01U << frag_spec) < device->buffer_size) {
|
||||
frag_spec++;
|
||||
}
|
||||
frag_spec |= 0x00020000; /* two fragments, for low latency */
|
||||
frag_spec |= 0x00020000; // two fragments, for low latency
|
||||
|
||||
/* Set the audio buffering parameters */
|
||||
// Set the audio buffering parameters
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Requesting %d fragments of size %d\n",
|
||||
(frag_spec >> 16), 1 << (frag_spec & 0xFFFF));
|
||||
@ -189,11 +188,11 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
// Allocate mixing buffer
|
||||
if (!device->iscapture) {
|
||||
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
|
||||
if (device->hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size);
|
||||
}
|
||||
@ -201,7 +200,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
|
||||
return 0; // We're ready to rock and roll. :-)
|
||||
}
|
||||
|
||||
static void DSP_WaitDevice(SDL_AudioDevice *device)
|
||||
static int DSP_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
const unsigned long ioctlreq = device->iscapture ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE;
|
||||
struct SDL_PrivateAudioData *h = device->hidden;
|
||||
@ -215,14 +214,15 @@ static void DSP_WaitDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
// Hmm, not much we can do - abort
|
||||
fprintf(stderr, "dsp WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno));
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
return;
|
||||
return -1;
|
||||
} else if (info.bytes < device->buffer_size) {
|
||||
SDL_Delay(10);
|
||||
} else {
|
||||
break; // ready to go!
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DSP_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
@ -268,8 +268,8 @@ static void DSP_FlushCapture(SDL_AudioDevice *device)
|
||||
static SDL_bool InitTimeDevicesExist = SDL_FALSE;
|
||||
static SDL_bool look_for_devices_test(int fd)
|
||||
{
|
||||
InitTimeDevicesExist = SDL_TRUE; /* note that _something_ exists. */
|
||||
/* Don't add to the device list, we're just seeing if any devices exist. */
|
||||
InitTimeDevicesExist = SDL_TRUE; // note that _something_ exists.
|
||||
// Don't add to the device list, we're just seeing if any devices exist.
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
@ -279,10 +279,9 @@ static SDL_bool DSP_Init(SDL_AudioDriverImpl *impl)
|
||||
SDL_EnumUnixAudioDevices(SDL_FALSE, look_for_devices_test);
|
||||
if (!InitTimeDevicesExist) {
|
||||
SDL_SetError("dsp: No such audio device");
|
||||
return SDL_FALSE; /* maybe try a different backend. */
|
||||
return SDL_FALSE; // maybe try a different backend.
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = DSP_DetectDevices;
|
||||
impl->OpenDevice = DSP_OpenDevice;
|
||||
impl->WaitDevice = DSP_WaitDevice;
|
||||
@ -293,14 +292,13 @@ static SDL_bool DSP_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->CaptureFromDevice = DSP_CaptureFromDevice;
|
||||
impl->FlushCapture = DSP_FlushCapture;
|
||||
|
||||
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
AudioBootStrap DSP_bootstrap = {
|
||||
"dsp", "Open Sound System (/dev/dsp)", DSP_Init, SDL_FALSE
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_OSS */
|
||||
#endif // SDL_AUDIO_DRIVER_OSS
|
||||
|
@ -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
|
||||
@ -27,11 +27,11 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
// The file descriptor for the audio device
|
||||
int audio_fd;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
// Raw mixing buffer
|
||||
Uint8 *mixbuf;
|
||||
};
|
||||
|
||||
#endif /* SDL_dspaudio_h_ */
|
||||
#endif // SDL_dspaudio_h_
|
||||
|
@ -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
|
||||
@ -22,15 +22,16 @@
|
||||
|
||||
// Output audio to nowhere...
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_dummyaudio.h"
|
||||
|
||||
// !!! FIXME: this should be an SDL hint, not an environment variable.
|
||||
#define DUMMYENVR_IODELAY "SDL_DUMMYAUDIODELAY"
|
||||
|
||||
static void DUMMYAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
static int DUMMYAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
SDL_Delay(device->hidden->io_delay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
@ -39,13 +40,13 @@ static int DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (!device->hidden) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!device->iscapture) {
|
||||
device->hidden->mixbuf = (Uint8 *) SDL_malloc(device->buffer_size);
|
||||
if (!device->hidden->mixbuf) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_EMSCRIPTEN
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_emscriptenaudio.h"
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
@ -177,8 +177,8 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// limit to native freq
|
||||
@ -188,8 +188,8 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
if (!device->iscapture) {
|
||||
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
|
||||
if (device->hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size);
|
||||
}
|
||||
@ -321,7 +321,7 @@ static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}) ? SDL_TRUE : SDL_FALSE;
|
||||
});
|
||||
|
||||
if (!available) {
|
||||
SDL_SetError("No audio context available");
|
||||
@ -334,10 +334,10 @@ static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}) ? SDL_TRUE : SDL_FALSE;
|
||||
});
|
||||
|
||||
impl->HasCaptureSupport = capture_available ? SDL_TRUE : SDL_FALSE;
|
||||
impl->OnlyHasDefaultCaptureDevice = capture_available ? SDL_TRUE : SDL_FALSE;
|
||||
impl->HasCaptureSupport = capture_available;
|
||||
impl->OnlyHasDefaultCaptureDevice = capture_available;
|
||||
|
||||
return available;
|
||||
}
|
||||
|
@ -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
|
||||
@ -30,4 +30,4 @@ struct SDL_PrivateAudioData
|
||||
Uint8 *mixbuf;
|
||||
};
|
||||
|
||||
#endif /* SDL_emscriptenaudio_h_ */
|
||||
#endif // SDL_emscriptenaudio_h_
|
||||
|
@ -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
|
||||
@ -32,7 +32,6 @@
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_haikuaudio.h"
|
||||
|
||||
|
@ -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
|
||||
@ -32,4 +32,4 @@ struct SDL_PrivateAudioData
|
||||
int current_buffer_len;
|
||||
};
|
||||
|
||||
#endif /* SDL_haikuaudio_h_ */
|
||||
#endif // SDL_haikuaudio_h_
|
||||
|
106
external/sdl/SDL/src/audio/jack/SDL_jackaudio.c
vendored
106
external/sdl/SDL/src/audio/jack/SDL_jackaudio.c
vendored
@ -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
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_JACK
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_jackaudio.h"
|
||||
#include "../../thread/SDL_systhread.h"
|
||||
|
||||
@ -43,6 +43,8 @@ static const char *(*JACK_jack_port_name)(const jack_port_t *);
|
||||
static const char *(*JACK_jack_port_type)(const jack_port_t *);
|
||||
static int (*JACK_jack_connect)(jack_client_t *, const char *, const char *);
|
||||
static int (*JACK_jack_set_process_callback)(jack_client_t *, JackProcessCallback, void *);
|
||||
static int (*JACK_jack_set_sample_rate_callback)(jack_client_t *, JackSampleRateCallback, void *);
|
||||
static int (*JACK_jack_set_buffer_size_callback)(jack_client_t *, JackBufferSizeCallback, void *);
|
||||
|
||||
static int load_jack_syms(void);
|
||||
|
||||
@ -51,26 +53,26 @@ static int load_jack_syms(void);
|
||||
static const char *jack_library = SDL_AUDIO_DRIVER_JACK_DYNAMIC;
|
||||
static void *jack_handle = NULL;
|
||||
|
||||
/* !!! FIXME: this is copy/pasted in several places now */
|
||||
// !!! FIXME: this is copy/pasted in several places now
|
||||
static int load_jack_sym(const char *fn, void **addr)
|
||||
{
|
||||
*addr = SDL_LoadFunction(jack_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;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
|
||||
// cast funcs to char* first, to please GCC's strict aliasing rules.
|
||||
#define SDL_JACK_SYM(x) \
|
||||
if (!load_jack_sym(#x, (void **)(char *)&JACK_##x)) \
|
||||
return -1
|
||||
|
||||
static void UnloadJackLibrary(void)
|
||||
{
|
||||
if (jack_handle != NULL) {
|
||||
if (jack_handle) {
|
||||
SDL_UnloadObject(jack_handle);
|
||||
jack_handle = NULL;
|
||||
}
|
||||
@ -79,11 +81,11 @@ static void UnloadJackLibrary(void)
|
||||
static int LoadJackLibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (jack_handle == NULL) {
|
||||
if (!jack_handle) {
|
||||
jack_handle = SDL_LoadObject(jack_library);
|
||||
if (jack_handle == NULL) {
|
||||
if (!jack_handle) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
// Don't call SDL_SetError(): SDL_LoadObject already did.
|
||||
} else {
|
||||
retval = load_jack_syms();
|
||||
if (retval < 0) {
|
||||
@ -108,7 +110,7 @@ static int LoadJackLibrary(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_JACK_DYNAMIC */
|
||||
#endif // SDL_AUDIO_DRIVER_JACK_DYNAMIC
|
||||
|
||||
static int load_jack_syms(void)
|
||||
{
|
||||
@ -129,18 +131,41 @@ static int load_jack_syms(void)
|
||||
SDL_JACK_SYM(jack_port_type);
|
||||
SDL_JACK_SYM(jack_connect);
|
||||
SDL_JACK_SYM(jack_set_process_callback);
|
||||
SDL_JACK_SYM(jack_set_sample_rate_callback);
|
||||
SDL_JACK_SYM(jack_set_buffer_size_callback);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jackShutdownCallback(void *arg) /* JACK went away; device is lost. */
|
||||
static void jackShutdownCallback(void *arg) // JACK went away; device is lost.
|
||||
{
|
||||
SDL_AudioDeviceDisconnected((SDL_AudioDevice *)arg);
|
||||
}
|
||||
|
||||
// !!! FIXME: implement and register these!
|
||||
// typedef int(* JackSampleRateCallback)(jack_nframes_t nframes, void *arg)
|
||||
// typedef int(* JackBufferSizeCallback)(jack_nframes_t nframes, void *arg)
|
||||
static int jackSampleRateCallback(jack_nframes_t nframes, void *arg)
|
||||
{
|
||||
//SDL_Log("JACK Sample Rate Callback! %d", (int) nframes);
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) arg;
|
||||
SDL_AudioSpec newspec;
|
||||
SDL_copyp(&newspec, &device->spec);
|
||||
newspec.freq = (int) nframes;
|
||||
if (SDL_AudioDeviceFormatChanged(device, &newspec, device->sample_frames) < 0) {
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jackBufferSizeCallback(jack_nframes_t nframes, void *arg)
|
||||
{
|
||||
//SDL_Log("JACK Buffer Size Callback! %d", (int) nframes);
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) arg;
|
||||
SDL_AudioSpec newspec;
|
||||
SDL_copyp(&newspec, &device->spec);
|
||||
if (SDL_AudioDeviceFormatChanged(device, &newspec, (int) nframes) < 0) {
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg)
|
||||
{
|
||||
@ -269,34 +294,34 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
|
||||
int ports = 0;
|
||||
int i;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL);
|
||||
device->hidden->client = client;
|
||||
if (client == NULL) {
|
||||
if (!client) {
|
||||
return SDL_SetError("Can't open JACK client");
|
||||
}
|
||||
|
||||
devports = JACK_jack_get_ports(client, NULL, NULL, JackPortIsPhysical | sysportflags);
|
||||
if (devports == NULL || !devports[0]) {
|
||||
if (!devports || !devports[0]) {
|
||||
return SDL_SetError("No physical JACK ports available");
|
||||
}
|
||||
|
||||
while (devports[++ports]) {
|
||||
/* spin to count devports */
|
||||
// spin to count devports
|
||||
}
|
||||
|
||||
/* Filter out non-audio ports */
|
||||
// Filter out non-audio ports
|
||||
audio_ports = SDL_calloc(ports, sizeof(*audio_ports));
|
||||
for (i = 0; i < ports; i++) {
|
||||
const jack_port_t *dport = JACK_jack_port_by_name(client, devports[i]);
|
||||
const char *type = JACK_jack_port_type(dport);
|
||||
const int len = SDL_strlen(type);
|
||||
/* See if type ends with "audio" */
|
||||
// See if type ends with "audio"
|
||||
if (len >= 5 && !SDL_memcmp(type + len - 5, "audio", 5)) {
|
||||
audio_ports[channels++] = i;
|
||||
}
|
||||
@ -306,9 +331,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
|
||||
return SDL_SetError("No physical JACK ports available");
|
||||
}
|
||||
|
||||
/* !!! FIXME: docs say about buffer size: "This size may change, clients that depend on it must register a bufsize_callback so they will be notified if it does." */
|
||||
|
||||
/* Jack pretty much demands what it wants. */
|
||||
// Jack pretty much demands what it wants.
|
||||
device->spec.format = SDL_AUDIO_F32;
|
||||
device->spec.freq = JACK_jack_get_sample_rate(client);
|
||||
device->spec.channels = channels;
|
||||
@ -320,15 +343,15 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
|
||||
device->hidden->iobuffer = (float *)SDL_calloc(1, device->buffer_size);
|
||||
if (!device->hidden->iobuffer) {
|
||||
SDL_free(audio_ports);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build SDL's ports, which we will connect to the device ports. */
|
||||
// Build SDL's ports, which we will connect to the device ports.
|
||||
device->hidden->sdlports = (jack_port_t **)SDL_calloc(channels, sizeof(jack_port_t *));
|
||||
if (device->hidden->sdlports == NULL) {
|
||||
if (!device->hidden->sdlports) {
|
||||
SDL_free(audio_ports);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < channels; i++) {
|
||||
@ -341,7 +364,13 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
if (JACK_jack_set_process_callback(client, callback, device) != 0) {
|
||||
if (JACK_jack_set_buffer_size_callback(client, jackBufferSizeCallback, device) != 0) {
|
||||
SDL_free(audio_ports);
|
||||
return SDL_SetError("JACK: Couldn't set buffer size callback");
|
||||
} else if (JACK_jack_set_sample_rate_callback(client, jackSampleRateCallback, device) != 0) {
|
||||
SDL_free(audio_ports);
|
||||
return SDL_SetError("JACK: Couldn't set sample rate callback");
|
||||
} else if (JACK_jack_set_process_callback(client, callback, device) != 0) {
|
||||
SDL_free(audio_ports);
|
||||
return SDL_SetError("JACK: Couldn't set process callback");
|
||||
}
|
||||
@ -353,7 +382,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
|
||||
return SDL_SetError("Failed to activate JACK client");
|
||||
}
|
||||
|
||||
/* once activated, we can connect all the ports. */
|
||||
// once activated, we can connect all the ports.
|
||||
for (i = 0; i < channels; i++) {
|
||||
const char *sdlport = JACK_jack_port_name(device->hidden->sdlports[i]);
|
||||
const char *srcport = iscapture ? devports[audio_ports[i]] : sdlport;
|
||||
@ -364,11 +393,11 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
/* don't need these anymore. */
|
||||
// don't need these anymore.
|
||||
JACK_jack_free(devports);
|
||||
SDL_free(audio_ports);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
// We're ready to rock and roll. :-)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -382,17 +411,16 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl)
|
||||
if (LoadJackLibrary() < 0) {
|
||||
return SDL_FALSE;
|
||||
} else {
|
||||
/* Make sure a JACK server is running and available. */
|
||||
// Make sure a JACK server is running and available.
|
||||
jack_status_t status;
|
||||
jack_client_t *client = JACK_jack_client_open("SDL", JackNoStartServer, &status, NULL);
|
||||
if (client == NULL) {
|
||||
if (!client) {
|
||||
UnloadJackLibrary();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
JACK_jack_client_close(client);
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = JACK_OpenDevice;
|
||||
impl->GetDeviceBuf = JACK_GetDeviceBuf;
|
||||
impl->PlayDevice = JACK_PlayDevice;
|
||||
@ -405,11 +433,11 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->ProvidesOwnCallbackThread = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
AudioBootStrap JACK_bootstrap = {
|
||||
"jack", "JACK Audio Connection Kit", JACK_Init, SDL_FALSE
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_JACK */
|
||||
#endif // SDL_AUDIO_DRIVER_JACK
|
||||
|
@ -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
|
||||
@ -32,4 +32,4 @@ struct SDL_PrivateAudioData
|
||||
float *iobuffer;
|
||||
};
|
||||
|
||||
#endif /* SDL_jackaudio_h_ */
|
||||
#endif // SDL_jackaudio_h_
|
||||
|
18
external/sdl/SDL/src/audio/n3ds/SDL_n3dsaudio.c
vendored
18
external/sdl/SDL/src/audio/n3ds/SDL_n3dsaudio.c
vendored
@ -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
|
||||
@ -32,6 +32,7 @@
|
||||
static dspHookCookie dsp_hook;
|
||||
static SDL_AudioDevice *audio_device;
|
||||
|
||||
// fully local functions related to the wavebufs / DSP, not the same as the `device->lock` SDL_Mutex!
|
||||
static SDL_INLINE void contextLock(SDL_AudioDevice *device)
|
||||
{
|
||||
LightLock_Lock(&device->hidden->lock);
|
||||
@ -82,8 +83,8 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
float mix[12];
|
||||
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initialise the DSP service
|
||||
@ -133,14 +134,14 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
|
||||
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
|
||||
if (device->hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size);
|
||||
|
||||
data_vaddr = (Uint8 *)linearAlloc(device->buffer_size * NUM_BUFFERS);
|
||||
if (data_vaddr == NULL) {
|
||||
if (!data_vaddr) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
@ -200,7 +201,7 @@ static int N3DSAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void N3DSAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
static int N3DSAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
contextLock(device);
|
||||
while (!device->hidden->isCancelled && !SDL_AtomicGet(&device->shutdown) &&
|
||||
@ -208,6 +209,7 @@ static void N3DSAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
CondVar_Wait(&device->hidden->cv, &device->hidden->lock);
|
||||
}
|
||||
contextUnlock(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint8 *N3DSAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
@ -251,7 +253,7 @@ static void N3DSAUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
|
||||
static void N3DSAUDIO_ThreadInit(SDL_AudioDevice *device)
|
||||
{
|
||||
s32 current_priority;
|
||||
s32 current_priority = 0x30;
|
||||
svcGetThreadPriority(¤t_priority, CUR_THREAD_HANDLE);
|
||||
current_priority--;
|
||||
// 0x18 is reserved for video, 0x30 is the default for main thread
|
||||
|
@ -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
|
||||
@ -24,11 +24,11 @@
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#define NUM_BUFFERS 2 /* -- Don't lower this! */
|
||||
#define NUM_BUFFERS 3 // -- Minimum 2!
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* Speaker data */
|
||||
// Speaker data
|
||||
Uint8 *mixbuf;
|
||||
Uint32 nextbuf;
|
||||
ndspWaveBuf waveBuf[NUM_BUFFERS];
|
||||
@ -37,4 +37,4 @@ struct SDL_PrivateAudioData
|
||||
SDL_bool isCancelled;
|
||||
};
|
||||
|
||||
#endif /* SDL_n3dsaudio_h */
|
||||
#endif // SDL_n3dsaudio_h
|
||||
|
@ -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
|
||||
@ -34,7 +34,6 @@
|
||||
#include <sys/audioio.h>
|
||||
|
||||
#include "../../core/unix/SDL_poll.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_audiodev_c.h"
|
||||
#include "SDL_netbsdaudio.h"
|
||||
|
||||
@ -115,7 +114,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device)
|
||||
#endif // DEBUG_AUDIO
|
||||
}
|
||||
|
||||
static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
const SDL_bool iscapture = device->iscapture;
|
||||
while (!SDL_AtomicGet(&device->shutdown)) {
|
||||
@ -127,8 +126,7 @@ static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
// Hmm, not much we can do - abort
|
||||
fprintf(stderr, "netbsdaudio WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno));
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
const size_t remain = (size_t)((iscapture ? info.record.seek : info.play.seek) * SDL_AUDIO_BYTESIZE(device->spec.format));
|
||||
if (!iscapture && (remain >= device->buffer_size)) {
|
||||
@ -136,9 +134,11 @@ static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
} else if (iscapture && (remain < device->buffer_size)) {
|
||||
SDL_Delay(10);
|
||||
} else {
|
||||
break; /* ready to go! */
|
||||
break; // ready to go!
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int NETBSDAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
@ -215,8 +215,8 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that.
|
||||
@ -293,8 +293,8 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
// Allocate mixing buffer
|
||||
device->hidden->mixlen = device->buffer_size;
|
||||
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->hidden->mixlen);
|
||||
if (device->hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size);
|
||||
}
|
||||
@ -317,7 +317,6 @@ static SDL_bool NETBSDAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->FlushCapture = NETBSDAUDIO_FlushCapture;
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
@ -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
|
||||
@ -27,18 +27,18 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
// The file descriptor for the audio device
|
||||
int audio_fd;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
// Raw mixing buffer
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
|
||||
/* Support for audio timing using a timer, in addition to SDL_IOReady() */
|
||||
// Support for audio timing using a timer, in addition to SDL_IOReady()
|
||||
float frame_ticks;
|
||||
float next_frame;
|
||||
};
|
||||
|
||||
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
|
||||
#define FUDGE_TICKS 10 // The scheduler overhead ticks per frame
|
||||
|
||||
#endif /* SDL_netbsdaudio_h_ */
|
||||
#endif // SDL_netbsdaudio_h_
|
||||
|
109
external/sdl/SDL/src/audio/openslES/SDL_openslES.c
vendored
109
external/sdl/SDL/src/audio/openslES/SDL_openslES.c
vendored
@ -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
|
||||
@ -26,7 +26,6 @@
|
||||
// https://googlesamples.github.io/android-audio-high-performance/guides/opensl_es.html
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_openslES.h"
|
||||
|
||||
#include "../../core/android/SDL_android.h"
|
||||
@ -108,7 +107,7 @@ static const char *sldevaudioplayerstr = "SLES Audio Player";
|
||||
|
||||
#define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr
|
||||
#define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr
|
||||
static void openslES_DetectDevices( int iscapture )
|
||||
static void OPENSLES_DetectDevices( int iscapture )
|
||||
{
|
||||
LOGI( "openSLES_DetectDevices()" );
|
||||
if ( iscapture )
|
||||
@ -118,9 +117,9 @@ static void openslES_DetectDevices( int iscapture )
|
||||
}
|
||||
#endif
|
||||
|
||||
static void openslES_DestroyEngine(void)
|
||||
static void OPENSLES_DestroyEngine(void)
|
||||
{
|
||||
LOGI("openslES_DestroyEngine()");
|
||||
LOGI("OPENSLES_DestroyEngine()");
|
||||
|
||||
// destroy output mix object, and invalidate all associated interfaces
|
||||
if (outputMixObject != NULL) {
|
||||
@ -136,7 +135,7 @@ static void openslES_DestroyEngine(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int openslES_CreateEngine(void)
|
||||
static int OPENSLES_CreateEngine(void)
|
||||
{
|
||||
const SLInterfaceID ids[1] = { SL_IID_VOLUME };
|
||||
const SLboolean req[1] = { SL_BOOLEAN_FALSE };
|
||||
@ -185,7 +184,7 @@ static int openslES_CreateEngine(void)
|
||||
return 1;
|
||||
|
||||
error:
|
||||
openslES_DestroyEngine();
|
||||
OPENSLES_DestroyEngine();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -198,7 +197,7 @@ static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||
SDL_PostSemaphore(audiodata->playsem);
|
||||
}
|
||||
|
||||
static void openslES_DestroyPCMRecorder(SDL_AudioDevice *device)
|
||||
static void OPENSLES_DestroyPCMRecorder(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = device->hidden;
|
||||
SLresult result;
|
||||
@ -229,7 +228,7 @@ static void openslES_DestroyPCMRecorder(SDL_AudioDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
static int openslES_CreatePCMRecorder(SDL_AudioDevice *device)
|
||||
static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = device->hidden;
|
||||
SLDataFormat_PCM format_pcm;
|
||||
@ -328,7 +327,7 @@ static int openslES_CreatePCMRecorder(SDL_AudioDevice *device)
|
||||
|
||||
// Create the sound buffers
|
||||
audiodata->mixbuff = (Uint8 *)SDL_malloc(NUM_BUFFERS * device->buffer_size);
|
||||
if (audiodata->mixbuff == NULL) {
|
||||
if (!audiodata->mixbuff) {
|
||||
LOGE("mixbuffer allocate - out of memory");
|
||||
goto failed;
|
||||
}
|
||||
@ -375,7 +374,7 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||
SDL_PostSemaphore(audiodata->playsem);
|
||||
}
|
||||
|
||||
static void openslES_DestroyPCMPlayer(SDL_AudioDevice *device)
|
||||
static void OPENSLES_DestroyPCMPlayer(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = device->hidden;
|
||||
|
||||
@ -406,7 +405,7 @@ static void openslES_DestroyPCMPlayer(SDL_AudioDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
static int openslES_CreatePCMPlayer(SDL_AudioDevice *device)
|
||||
static int OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device)
|
||||
{
|
||||
/* If we want to add floating point audio support (requires API level 21)
|
||||
it can be done as described here:
|
||||
@ -575,7 +574,7 @@ static int openslES_CreatePCMPlayer(SDL_AudioDevice *device)
|
||||
|
||||
// Create the sound buffers
|
||||
audiodata->mixbuff = (Uint8 *)SDL_malloc(NUM_BUFFERS * device->buffer_size);
|
||||
if (audiodata->mixbuff == NULL) {
|
||||
if (!audiodata->mixbuff) {
|
||||
LOGE("mixbuffer allocate - out of memory");
|
||||
goto failed;
|
||||
}
|
||||
@ -597,26 +596,26 @@ failed:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int openslES_OpenDevice(SDL_AudioDevice *device)
|
||||
static int OPENSLES_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (device->iscapture) {
|
||||
LOGI("openslES_OpenDevice() for capture");
|
||||
return openslES_CreatePCMRecorder(device);
|
||||
LOGI("OPENSLES_OpenDevice() for capture");
|
||||
return OPENSLES_CreatePCMRecorder(device);
|
||||
} else {
|
||||
int ret;
|
||||
LOGI("openslES_OpenDevice() for playing");
|
||||
ret = openslES_CreatePCMPlayer(device);
|
||||
LOGI("OPENSLES_OpenDevice() for playing");
|
||||
ret = OPENSLES_CreatePCMPlayer(device);
|
||||
if (ret < 0) {
|
||||
// Another attempt to open the device with a lower frequency
|
||||
if (device->spec.freq > 48000) {
|
||||
openslES_DestroyPCMPlayer(device);
|
||||
OPENSLES_DestroyPCMPlayer(device);
|
||||
device->spec.freq = 48000;
|
||||
ret = openslES_CreatePCMPlayer(device);
|
||||
ret = OPENSLES_CreatePCMPlayer(device);
|
||||
}
|
||||
}
|
||||
|
||||
@ -628,21 +627,21 @@ static int openslES_OpenDevice(SDL_AudioDevice *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void openslES_WaitDevice(SDL_AudioDevice *device)
|
||||
static int OPENSLES_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = device->hidden;
|
||||
|
||||
LOGV("openslES_WaitDevice()");
|
||||
LOGV("OPENSLES_WaitDevice()");
|
||||
|
||||
// Wait for an audio chunk to finish
|
||||
SDL_WaitSemaphore(audiodata->playsem);
|
||||
return SDL_WaitSemaphore(audiodata->playsem);
|
||||
}
|
||||
|
||||
static int openslES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
static int OPENSLES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = device->hidden;
|
||||
|
||||
LOGV("======openslES_PlayDevice()======");
|
||||
LOGV("======OPENSLES_PlayDevice()======");
|
||||
|
||||
// Queue it up
|
||||
const SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer, buflen);
|
||||
@ -673,15 +672,15 @@ static int openslES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
|
||||
//
|
||||
// okay..
|
||||
|
||||
static Uint8 *openslES_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize)
|
||||
static Uint8 *OPENSLES_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = device->hidden;
|
||||
|
||||
LOGV("openslES_GetDeviceBuf()");
|
||||
LOGV("OPENSLES_GetDeviceBuf()");
|
||||
return audiodata->pmixbuff[audiodata->next_buffer];
|
||||
}
|
||||
|
||||
static int openslES_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
|
||||
static int OPENSLES_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = device->hidden;
|
||||
|
||||
@ -704,16 +703,16 @@ static int openslES_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int
|
||||
return device->buffer_size;
|
||||
}
|
||||
|
||||
static void openslES_CloseDevice(SDL_AudioDevice *device)
|
||||
static void OPENSLES_CloseDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// struct SDL_PrivateAudioData *audiodata = device->hidden;
|
||||
if (device->hidden) {
|
||||
if (device->iscapture) {
|
||||
LOGI("openslES_CloseDevice() for capture");
|
||||
openslES_DestroyPCMRecorder(device);
|
||||
LOGI("OPENSLES_CloseDevice() for capture");
|
||||
OPENSLES_DestroyPCMRecorder(device);
|
||||
} else {
|
||||
LOGI("openslES_CloseDevice() for playing");
|
||||
openslES_DestroyPCMPlayer(device);
|
||||
LOGI("OPENSLES_CloseDevice() for playing");
|
||||
OPENSLES_DestroyPCMPlayer(device);
|
||||
}
|
||||
|
||||
SDL_free(device->hidden);
|
||||
@ -721,61 +720,61 @@ static void openslES_CloseDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool openslES_Init(SDL_AudioDriverImpl *impl)
|
||||
static SDL_bool OPENSLES_Init(SDL_AudioDriverImpl *impl)
|
||||
{
|
||||
LOGI("openslES_Init() called");
|
||||
LOGI("OPENSLES_Init() called");
|
||||
|
||||
if (!openslES_CreateEngine()) {
|
||||
if (!OPENSLES_CreateEngine()) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
LOGI("openslES_Init() - set pointers");
|
||||
LOGI("OPENSLES_Init() - set pointers");
|
||||
|
||||
// Set the function pointers
|
||||
// impl->DetectDevices = openslES_DetectDevices;
|
||||
// impl->DetectDevices = OPENSLES_DetectDevices;
|
||||
impl->ThreadInit = Android_AudioThreadInit;
|
||||
impl->OpenDevice = openslES_OpenDevice;
|
||||
impl->WaitDevice = openslES_WaitDevice;
|
||||
impl->PlayDevice = openslES_PlayDevice;
|
||||
impl->GetDeviceBuf = openslES_GetDeviceBuf;
|
||||
impl->WaitCaptureDevice = openslES_WaitDevice;
|
||||
impl->CaptureFromDevice = openslES_CaptureFromDevice;
|
||||
impl->CloseDevice = openslES_CloseDevice;
|
||||
impl->Deinitialize = openslES_DestroyEngine;
|
||||
impl->OpenDevice = OPENSLES_OpenDevice;
|
||||
impl->WaitDevice = OPENSLES_WaitDevice;
|
||||
impl->PlayDevice = OPENSLES_PlayDevice;
|
||||
impl->GetDeviceBuf = OPENSLES_GetDeviceBuf;
|
||||
impl->WaitCaptureDevice = OPENSLES_WaitDevice;
|
||||
impl->CaptureFromDevice = OPENSLES_CaptureFromDevice;
|
||||
impl->CloseDevice = OPENSLES_CloseDevice;
|
||||
impl->Deinitialize = OPENSLES_DestroyEngine;
|
||||
|
||||
// and the capabilities
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
|
||||
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
|
||||
|
||||
LOGI("openslES_Init() - success");
|
||||
LOGI("OPENSLES_Init() - success");
|
||||
|
||||
// this audio target is available.
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
AudioBootStrap openslES_bootstrap = {
|
||||
"openslES", "opensl ES audio driver", openslES_Init, SDL_FALSE
|
||||
AudioBootStrap OPENSLES_bootstrap = {
|
||||
"openslES", "OpenSL ES audio driver", OPENSLES_Init, SDL_FALSE
|
||||
};
|
||||
|
||||
void openslES_ResumeDevices(void)
|
||||
void OPENSLES_ResumeDevices(void)
|
||||
{
|
||||
if (bqPlayerPlay != NULL) {
|
||||
// set the player's state to 'playing'
|
||||
SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("openslES_ResumeDevices failed: %d", result);
|
||||
LOGE("OPENSLES_ResumeDevices failed: %d", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void openslES_PauseDevices(void)
|
||||
void OPENSLES_PauseDevices(void)
|
||||
{
|
||||
if (bqPlayerPlay != NULL) {
|
||||
// set the player's state to 'paused'
|
||||
SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("openslES_PauseDevices failed: %d", result);
|
||||
LOGE("OPENSLES_PauseDevices failed: %d", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -25,14 +25,14 @@
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_OPENSLES
|
||||
|
||||
void openslES_ResumeDevices(void);
|
||||
void openslES_PauseDevices(void);
|
||||
void OPENSLES_ResumeDevices(void);
|
||||
void OPENSLES_PauseDevices(void);
|
||||
|
||||
#else
|
||||
|
||||
static void openslES_ResumeDevices(void) {}
|
||||
static void openslES_PauseDevices(void) {}
|
||||
static void OPENSLES_ResumeDevices(void) {}
|
||||
static void OPENSLES_PauseDevices(void) {}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SDL_openslesaudio_h_ */
|
||||
#endif // SDL_openslesaudio_h_
|
||||
|
190
external/sdl/SDL/src/audio/pipewire/SDL_pipewire.c
vendored
190
external/sdl/SDL/src/audio/pipewire/SDL_pipewire.c
vendored
@ -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
|
||||
|
@ -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
|
||||
@ -33,11 +33,11 @@ struct SDL_PrivateAudioData
|
||||
struct pw_stream *stream;
|
||||
struct pw_context *context;
|
||||
|
||||
Sint32 stride; /* Bytes-per-frame */
|
||||
Sint32 stride; // Bytes-per-frame
|
||||
int stream_init_status;
|
||||
|
||||
// Set in GetDeviceBuf, filled in AudioThreadIterate, queued in PlayDevice
|
||||
struct pw_buffer *pw_buf;
|
||||
};
|
||||
|
||||
#endif /* SDL_pipewire_h_ */
|
||||
#endif // SDL_pipewire_h_
|
||||
|
15
external/sdl/SDL/src/audio/ps2/SDL_ps2audio.c
vendored
15
external/sdl/SDL/src/audio/ps2/SDL_ps2audio.c
vendored
@ -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
|
||||
@ -20,7 +20,7 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_ps2audio.h"
|
||||
|
||||
#include <kernel.h>
|
||||
@ -30,8 +30,8 @@
|
||||
static int PS2AUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// These are the native supported audio PS2 configs
|
||||
@ -73,7 +73,7 @@ static int PS2AUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
64, so spec->size should be a multiple of 64 as well. */
|
||||
const int mixlen = device->buffer_size * NUM_BUFFERS;
|
||||
device->hidden->rawbuf = (Uint8 *)SDL_aligned_alloc(64, mixlen);
|
||||
if (device->hidden->rawbuf == NULL) {
|
||||
if (!device->hidden->rawbuf) {
|
||||
return SDL_SetError("Couldn't allocate mixing buffer");
|
||||
}
|
||||
|
||||
@ -91,9 +91,10 @@ static int PS2AUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
|
||||
return (audsrv_play_audio((char *)buffer, buflen) != buflen) ? -1 : 0;
|
||||
}
|
||||
|
||||
static void PS2AUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
static int PS2AUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
audsrv_wait_audio(device->buffer_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint8 *PS2AUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
@ -111,7 +112,7 @@ static void PS2AUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
device->hidden->channel = -1;
|
||||
}
|
||||
|
||||
if (device->hidden->rawbuf != NULL) {
|
||||
if (device->hidden->rawbuf) {
|
||||
SDL_aligned_free(device->hidden->rawbuf);
|
||||
device->hidden->rawbuf = NULL;
|
||||
}
|
||||
|
12
external/sdl/SDL/src/audio/ps2/SDL_ps2audio.h
vendored
12
external/sdl/SDL/src/audio/ps2/SDL_ps2audio.h
vendored
@ -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
|
||||
@ -29,14 +29,14 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The hardware output channel. */
|
||||
// The hardware output channel.
|
||||
int channel;
|
||||
/* The raw allocated mixing buffer. */
|
||||
// The raw allocated mixing buffer.
|
||||
Uint8 *rawbuf;
|
||||
/* Individual mixing buffers. */
|
||||
// Individual mixing buffers.
|
||||
Uint8 *mixbufs[NUM_BUFFERS];
|
||||
/* Index of the next available mixing buffer. */
|
||||
// Index of the next available mixing buffer.
|
||||
int next_buffer;
|
||||
};
|
||||
|
||||
#endif /* SDL_ps2audio_h_ */
|
||||
#endif // SDL_ps2audio_h_
|
||||
|
15
external/sdl/SDL/src/audio/psp/SDL_pspaudio.c
vendored
15
external/sdl/SDL/src/audio/psp/SDL_pspaudio.c
vendored
@ -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
|
||||
@ -26,7 +26,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_audiodev_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_pspaudio.h"
|
||||
@ -42,8 +41,8 @@ static inline SDL_bool isBasicAudioConfig(const SDL_AudioSpec *spec)
|
||||
static int PSPAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// device only natively supports S16LSB
|
||||
@ -94,7 +93,7 @@ static int PSPAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
64, so spec->size should be a multiple of 64 as well. */
|
||||
const int mixlen = device->buffer_size * NUM_BUFFERS;
|
||||
device->hidden->rawbuf = (Uint8 *)SDL_aligned_alloc(64, mixlen);
|
||||
if (device->hidden->rawbuf == NULL) {
|
||||
if (!device->hidden->rawbuf) {
|
||||
return SDL_SetError("Couldn't allocate mixing buffer");
|
||||
}
|
||||
|
||||
@ -118,9 +117,9 @@ static int PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
|
||||
return (rc == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void PSPAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
static int PSPAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// Because we block when sending audio, there's no need for this function to do anything.
|
||||
return 0; // Because we block when sending audio, there's no need for this function to do anything.
|
||||
}
|
||||
|
||||
static Uint8 *PSPAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
@ -142,7 +141,7 @@ static void PSPAUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
device->hidden->channel = -1;
|
||||
}
|
||||
|
||||
if (device->hidden->rawbuf != NULL) {
|
||||
if (device->hidden->rawbuf) {
|
||||
SDL_aligned_free(device->hidden->rawbuf);
|
||||
device->hidden->rawbuf = NULL;
|
||||
}
|
||||
|
12
external/sdl/SDL/src/audio/psp/SDL_pspaudio.h
vendored
12
external/sdl/SDL/src/audio/psp/SDL_pspaudio.h
vendored
@ -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
|
||||
@ -28,14 +28,14 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The hardware output channel. */
|
||||
// The hardware output channel.
|
||||
int channel;
|
||||
/* The raw allocated mixing buffer. */
|
||||
// The raw allocated mixing buffer.
|
||||
Uint8 *rawbuf;
|
||||
/* Individual mixing buffers. */
|
||||
// Individual mixing buffers.
|
||||
Uint8 *mixbufs[NUM_BUFFERS];
|
||||
/* Index of the next available mixing buffer. */
|
||||
// Index of the next available mixing buffer.
|
||||
int next_buffer;
|
||||
};
|
||||
|
||||
#endif /* SDL_pspaudio_h_ */
|
||||
#endif // SDL_pspaudio_h_
|
||||
|
@ -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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_PULSEAUDIO
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
// Allow access to a raw mixing buffer
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
@ -31,11 +31,21 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_pulseaudio.h"
|
||||
#include "../../thread/SDL_systhread.h"
|
||||
|
||||
/* should we include monitors in the device list? Set at SDL_Init time */
|
||||
#if (PA_PROTOCOL_VERSION < 28)
|
||||
typedef void (*pa_operation_notify_cb_t) (pa_operation *o, void *userdata);
|
||||
#endif
|
||||
|
||||
typedef struct PulseDeviceHandle
|
||||
{
|
||||
char *device_path;
|
||||
uint32_t device_index;
|
||||
} PulseDeviceHandle;
|
||||
|
||||
// should we include monitors in the device list? Set at SDL_Init time
|
||||
static SDL_bool include_monitors = SDL_FALSE;
|
||||
|
||||
static pa_threaded_mainloop *pulseaudio_threaded_mainloop = NULL;
|
||||
@ -43,12 +53,14 @@ static pa_context *pulseaudio_context = NULL;
|
||||
static SDL_Thread *pulseaudio_hotplug_thread = NULL;
|
||||
static SDL_AtomicInt pulseaudio_hotplug_thread_active;
|
||||
|
||||
// These are the OS identifiers (i.e. ALSA strings)...
|
||||
// These are the OS identifiers (i.e. ALSA strings)...these are allocated in a callback
|
||||
// when the default changes, and noticed by the hotplug thread when it alerts SDL
|
||||
// to the change.
|
||||
static char *default_sink_path = NULL;
|
||||
static char *default_source_path = NULL;
|
||||
// ... and these are the PulseAudio device indices of the default devices.
|
||||
static uint32_t default_sink_index = 0;
|
||||
static uint32_t default_source_index = 0;
|
||||
static SDL_bool default_sink_changed = SDL_FALSE;
|
||||
static SDL_bool default_source_changed = SDL_FALSE;
|
||||
|
||||
|
||||
static const char *(*PULSEAUDIO_pa_get_library_version)(void);
|
||||
static pa_channel_map *(*PULSEAUDIO_pa_channel_map_init_auto)(
|
||||
@ -94,11 +106,13 @@ static int (*PULSEAUDIO_pa_stream_connect_playback)(pa_stream *, const char *,
|
||||
const pa_buffer_attr *, pa_stream_flags_t, const pa_cvolume *, pa_stream *);
|
||||
static int (*PULSEAUDIO_pa_stream_connect_record)(pa_stream *, const char *,
|
||||
const pa_buffer_attr *, pa_stream_flags_t);
|
||||
static const pa_buffer_attr *(*PULSEAUDIO_pa_stream_get_buffer_attr)(pa_stream *);
|
||||
static pa_stream_state_t (*PULSEAUDIO_pa_stream_get_state)(const pa_stream *);
|
||||
static size_t (*PULSEAUDIO_pa_stream_writable_size)(const pa_stream *);
|
||||
static size_t (*PULSEAUDIO_pa_stream_readable_size)(const pa_stream *);
|
||||
static int (*PULSEAUDIO_pa_stream_write)(pa_stream *, const void *, size_t,
|
||||
pa_free_cb_t, int64_t, pa_seek_mode_t);
|
||||
static int (*PULSEAUDIO_pa_stream_begin_write)(pa_stream *, void **, size_t *);
|
||||
static pa_operation *(*PULSEAUDIO_pa_stream_drain)(pa_stream *,
|
||||
pa_stream_success_cb_t, void *);
|
||||
static int (*PULSEAUDIO_pa_stream_peek)(pa_stream *, const void **, size_t *);
|
||||
@ -121,22 +135,22 @@ static void *pulseaudio_handle = NULL;
|
||||
static int load_pulseaudio_sym(const char *fn, void **addr)
|
||||
{
|
||||
*addr = SDL_LoadFunction(pulseaudio_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;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
|
||||
// cast funcs to char* first, to please GCC's strict aliasing rules.
|
||||
#define SDL_PULSEAUDIO_SYM(x) \
|
||||
if (!load_pulseaudio_sym(#x, (void **)(char *)&PULSEAUDIO_##x)) \
|
||||
return -1
|
||||
|
||||
static void UnloadPulseAudioLibrary(void)
|
||||
{
|
||||
if (pulseaudio_handle != NULL) {
|
||||
if (pulseaudio_handle) {
|
||||
SDL_UnloadObject(pulseaudio_handle);
|
||||
pulseaudio_handle = NULL;
|
||||
}
|
||||
@ -145,11 +159,11 @@ static void UnloadPulseAudioLibrary(void)
|
||||
static int LoadPulseAudioLibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (pulseaudio_handle == NULL) {
|
||||
if (!pulseaudio_handle) {
|
||||
pulseaudio_handle = SDL_LoadObject(pulseaudio_library);
|
||||
if (pulseaudio_handle == NULL) {
|
||||
if (!pulseaudio_handle) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
// Don't call SDL_SetError(): SDL_LoadObject already did.
|
||||
} else {
|
||||
retval = load_pulseaudio_syms();
|
||||
if (retval < 0) {
|
||||
@ -174,7 +188,7 @@ static int LoadPulseAudioLibrary(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC */
|
||||
#endif // SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC
|
||||
|
||||
static int load_pulseaudio_syms(void)
|
||||
{
|
||||
@ -188,10 +202,8 @@ static int load_pulseaudio_syms(void)
|
||||
SDL_PULSEAUDIO_SYM(pa_threaded_mainloop_wait);
|
||||
SDL_PULSEAUDIO_SYM(pa_threaded_mainloop_signal);
|
||||
SDL_PULSEAUDIO_SYM(pa_threaded_mainloop_free);
|
||||
SDL_PULSEAUDIO_SYM(pa_threaded_mainloop_set_name);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_get_state);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_cancel);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_set_state_callback);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_unref);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_new);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_set_state_callback);
|
||||
@ -209,9 +221,11 @@ static int load_pulseaudio_syms(void)
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_set_state_callback);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_connect_playback);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_connect_record);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_get_buffer_attr);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_get_state);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_writable_size);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_readable_size);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_begin_write);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_write);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_drain);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_disconnect);
|
||||
@ -225,6 +239,21 @@ static int load_pulseaudio_syms(void)
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_set_read_callback);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_get_server_info);
|
||||
|
||||
// optional
|
||||
#ifdef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC
|
||||
load_pulseaudio_sym("pa_operation_set_state_callback", (void **)(char *)&PULSEAUDIO_pa_operation_set_state_callback); // needs pulseaudio 4.0
|
||||
load_pulseaudio_sym("pa_threaded_mainloop_set_name", (void **)(char *)&PULSEAUDIO_pa_threaded_mainloop_set_name); // needs pulseaudio 5.0
|
||||
#elif (PA_PROTOCOL_VERSION >= 29)
|
||||
PULSEAUDIO_pa_operation_set_state_callback = pa_operation_set_state_callback;
|
||||
PULSEAUDIO_pa_threaded_mainloop_set_name = pa_threaded_mainloop_set_name;
|
||||
#elif (PA_PROTOCOL_VERSION >= 28)
|
||||
PULSEAUDIO_pa_operation_set_state_callback = pa_operation_set_state_callback;
|
||||
PULSEAUDIO_pa_threaded_mainloop_set_name = NULL;
|
||||
#else
|
||||
PULSEAUDIO_pa_operation_set_state_callback = NULL;
|
||||
PULSEAUDIO_pa_threaded_mainloop_set_name = NULL;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -233,7 +262,7 @@ static SDL_INLINE int squashVersion(const int major, const int minor, const int
|
||||
return ((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF);
|
||||
}
|
||||
|
||||
/* Workaround for older pulse: pa_context_new() must have non-NULL appname */
|
||||
// Workaround for older pulse: pa_context_new() must have non-NULL appname
|
||||
static const char *getAppName(void)
|
||||
{
|
||||
const char *retval = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME);
|
||||
@ -245,12 +274,12 @@ static const char *getAppName(void)
|
||||
return retval;
|
||||
} else {
|
||||
const char *verstr = PULSEAUDIO_pa_get_library_version();
|
||||
retval = "SDL Application"; /* the "oh well" default. */
|
||||
if (verstr != NULL) {
|
||||
retval = "SDL Application"; // the "oh well" default.
|
||||
if (verstr) {
|
||||
int maj, min, patch;
|
||||
if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) {
|
||||
if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) {
|
||||
retval = NULL; /* 0.9.15+ handles NULL correctly. */
|
||||
retval = NULL; // 0.9.15+ handles NULL correctly.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -267,12 +296,18 @@ static void OperationStateChangeCallback(pa_operation *o, void *userdata)
|
||||
you did the work in the callback and just want to know it's done, though. */
|
||||
static void WaitForPulseOperation(pa_operation *o)
|
||||
{
|
||||
/* This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. */
|
||||
// This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about.
|
||||
SDL_assert(pulseaudio_threaded_mainloop != NULL);
|
||||
if (o) {
|
||||
PULSEAUDIO_pa_operation_set_state_callback(o, OperationStateChangeCallback, NULL);
|
||||
// note that if PULSEAUDIO_pa_operation_set_state_callback == NULL, then `o` must have a callback that will signal pulseaudio_threaded_mainloop.
|
||||
// If not, on really old (earlier PulseAudio 4.0, from the year 2013!) installs, this call will block forever.
|
||||
// On more modern installs, we won't ever block forever, and maybe be more efficient, thanks to pa_operation_set_state_callback.
|
||||
// WARNING: at the time of this writing: the Steam Runtime is still on PulseAudio 1.1!
|
||||
if (PULSEAUDIO_pa_operation_set_state_callback) {
|
||||
PULSEAUDIO_pa_operation_set_state_callback(o, OperationStateChangeCallback, NULL);
|
||||
}
|
||||
while (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); /* this releases the lock and blocks on an internal condition variable. */
|
||||
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); // this releases the lock and blocks on an internal condition variable.
|
||||
}
|
||||
PULSEAUDIO_pa_operation_unref(o);
|
||||
}
|
||||
@ -280,13 +315,15 @@ static void WaitForPulseOperation(pa_operation *o)
|
||||
|
||||
static void DisconnectFromPulseServer(void)
|
||||
{
|
||||
if (pulseaudio_threaded_mainloop) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_stop(pulseaudio_threaded_mainloop);
|
||||
}
|
||||
if (pulseaudio_context) {
|
||||
PULSEAUDIO_pa_context_disconnect(pulseaudio_context);
|
||||
PULSEAUDIO_pa_context_unref(pulseaudio_context);
|
||||
pulseaudio_context = NULL;
|
||||
}
|
||||
if (pulseaudio_threaded_mainloop != NULL) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_stop(pulseaudio_threaded_mainloop);
|
||||
if (pulseaudio_threaded_mainloop) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_free(pulseaudio_threaded_mainloop);
|
||||
pulseaudio_threaded_mainloop = NULL;
|
||||
}
|
||||
@ -294,7 +331,7 @@ static void DisconnectFromPulseServer(void)
|
||||
|
||||
static void PulseContextStateChangeCallback(pa_context *context, void *userdata)
|
||||
{
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* just signal any waiting code, it can look up the details. */
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
|
||||
}
|
||||
|
||||
static int ConnectToPulseServer(void)
|
||||
@ -305,12 +342,14 @@ static int ConnectToPulseServer(void)
|
||||
SDL_assert(pulseaudio_threaded_mainloop == NULL);
|
||||
SDL_assert(pulseaudio_context == NULL);
|
||||
|
||||
/* Set up a new main loop */
|
||||
// Set up a new main loop
|
||||
if (!(pulseaudio_threaded_mainloop = PULSEAUDIO_pa_threaded_mainloop_new())) {
|
||||
return SDL_SetError("pa_threaded_mainloop_new() failed");
|
||||
}
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_set_name(pulseaudio_threaded_mainloop, "PulseMainloop");
|
||||
if (PULSEAUDIO_pa_threaded_mainloop_set_name) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_set_name(pulseaudio_threaded_mainloop, "PulseMainloop");
|
||||
}
|
||||
|
||||
if (PULSEAUDIO_pa_threaded_mainloop_start(pulseaudio_threaded_mainloop) < 0) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_free(pulseaudio_threaded_mainloop);
|
||||
@ -321,17 +360,17 @@ static int ConnectToPulseServer(void)
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
|
||||
mainloop_api = PULSEAUDIO_pa_threaded_mainloop_get_api(pulseaudio_threaded_mainloop);
|
||||
SDL_assert(mainloop_api); /* this never fails, right? */
|
||||
SDL_assert(mainloop_api != NULL); // this never fails, right?
|
||||
|
||||
pulseaudio_context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName());
|
||||
if (pulseaudio_context == NULL) {
|
||||
if (!pulseaudio_context) {
|
||||
SDL_SetError("pa_context_new() failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
PULSEAUDIO_pa_context_set_state_callback(pulseaudio_context, PulseContextStateChangeCallback, NULL);
|
||||
|
||||
/* Connect to the PulseAudio server */
|
||||
// Connect to the PulseAudio server
|
||||
if (PULSEAUDIO_pa_context_connect(pulseaudio_context, NULL, 0, NULL) < 0) {
|
||||
SDL_SetError("Could not setup connection to PulseAudio");
|
||||
goto failed;
|
||||
@ -350,7 +389,7 @@ static int ConnectToPulseServer(void)
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
|
||||
return 0; /* connected and ready! */
|
||||
return 0; // connected and ready!
|
||||
|
||||
failed:
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
@ -361,38 +400,42 @@ failed:
|
||||
static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = (struct SDL_PrivateAudioData *)userdata;
|
||||
/*printf("PULSEAUDIO WRITE CALLBACK! nbytes=%u\n", (unsigned int) nbytes);*/
|
||||
//SDL_Log("PULSEAUDIO WRITE CALLBACK! nbytes=%u", (unsigned int) nbytes);
|
||||
h->bytes_requested += nbytes;
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
||||
}
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void PULSEAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
// This function waits until it is possible to write a full sound buffer
|
||||
static int PULSEAUDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = device->hidden;
|
||||
int retval = 0;
|
||||
|
||||
/*printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available);*/
|
||||
//SDL_Log("PULSEAUDIO PLAYDEVICE START! mixlen=%d", available);
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
|
||||
while (!SDL_AtomicGet(&device->shutdown) && (h->bytes_requested < (device->buffer_size / 2))) {
|
||||
/*printf("PULSEAUDIO WAIT IN WAITDEVICE!\n");*/
|
||||
while (!SDL_AtomicGet(&device->shutdown) && (h->bytes_requested == 0)) {
|
||||
//SDL_Log("PULSEAUDIO WAIT IN WAITDEVICE!");
|
||||
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
|
||||
|
||||
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
|
||||
/*printf("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!\n");*/
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
//SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!");
|
||||
retval = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = device->hidden;
|
||||
|
||||
/*printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available);*/
|
||||
//SDL_Log("PULSEAUDIO PLAYDEVICE START! mixlen=%d", available);
|
||||
|
||||
SDL_assert(h->bytes_requested >= buffer_size);
|
||||
|
||||
@ -404,41 +447,52 @@ static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*printf("PULSEAUDIO FEED! nbytes=%d\n", buffer_size);*/
|
||||
//SDL_Log("PULSEAUDIO FEED! nbytes=%d", buffer_size);
|
||||
h->bytes_requested -= buffer_size;
|
||||
|
||||
/*printf("PULSEAUDIO PLAYDEVICE END! written=%d\n", written);*/
|
||||
//SDL_Log("PULSEAUDIO PLAYDEVICE END! written=%d", written);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint8 *PULSEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = device->hidden;
|
||||
*buffer_size = SDL_min(*buffer_size, h->bytes_requested);
|
||||
const size_t reqsize = (size_t) SDL_min(*buffer_size, h->bytes_requested);
|
||||
size_t nbytes = reqsize;
|
||||
void *data = NULL;
|
||||
if (PULSEAUDIO_pa_stream_begin_write(h->stream, &data, &nbytes) == 0) {
|
||||
*buffer_size = (int) nbytes;
|
||||
return (Uint8 *) data;
|
||||
}
|
||||
|
||||
// don't know why this would fail, but we'll fall back just in case.
|
||||
*buffer_size = (int) reqsize;
|
||||
return device->hidden->mixbuf;
|
||||
}
|
||||
|
||||
static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata)
|
||||
{
|
||||
/*printf("PULSEAUDIO READ CALLBACK! nbytes=%u\n", (unsigned int) nbytes);*/
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* the capture code queries what it needs, we just need to signal to end any wait */
|
||||
//SDL_Log("PULSEAUDIO READ CALLBACK! nbytes=%u", (unsigned int) nbytes);
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the capture code queries what it needs, we just need to signal to end any wait
|
||||
}
|
||||
|
||||
static void PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = device->hidden;
|
||||
|
||||
if (h->capturebuf != NULL) {
|
||||
return; // there's still data available to read.
|
||||
if (h->capturebuf) {
|
||||
return 0; // there's still data available to read.
|
||||
}
|
||||
|
||||
int retval = 0;
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
|
||||
while (!SDL_AtomicGet(&device->shutdown)) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
|
||||
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
|
||||
//printf("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!\n");
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
//SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!");
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) {
|
||||
// a new fragment is available!
|
||||
@ -446,11 +500,11 @@ static void PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
size_t nbytes = 0;
|
||||
PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes);
|
||||
SDL_assert(nbytes > 0);
|
||||
if (data == NULL) { // If NULL, then the buffer had a hole, ignore that
|
||||
if (!data) { // If NULL, then the buffer had a hole, ignore that
|
||||
PULSEAUDIO_pa_stream_drop(h->stream); // drop this fragment.
|
||||
} else {
|
||||
// store this fragment's data for use with CaptureFromDevice
|
||||
//printf("PULSEAUDIO: captured %d new bytes\n", (int) nbytes);
|
||||
//SDL_Log("PULSEAUDIO: captured %d new bytes", (int) nbytes);
|
||||
h->capturebuf = (const Uint8 *)data;
|
||||
h->capturelen = nbytes;
|
||||
break;
|
||||
@ -459,16 +513,18 @@ static void PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = device->hidden;
|
||||
|
||||
if (h->capturebuf != NULL) {
|
||||
if (h->capturebuf) {
|
||||
const int cpy = SDL_min(buflen, h->capturelen);
|
||||
if (cpy > 0) {
|
||||
//printf("PULSEAUDIO: fed %d captured bytes\n", cpy);
|
||||
//SDL_Log("PULSEAUDIO: fed %d captured bytes", cpy);
|
||||
SDL_memcpy(buffer, h->capturebuf, cpy);
|
||||
h->capturebuf += cpy;
|
||||
h->capturelen -= cpy;
|
||||
@ -479,7 +535,7 @@ static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, i
|
||||
PULSEAUDIO_pa_stream_drop(h->stream); // done with this fragment.
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
}
|
||||
return cpy; /* new data, return it. */
|
||||
return cpy; // new data, return it.
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -493,7 +549,7 @@ static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device)
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
|
||||
if (h->capturebuf != NULL) {
|
||||
if (h->capturebuf) {
|
||||
PULSEAUDIO_pa_stream_drop(h->stream);
|
||||
h->capturebuf = NULL;
|
||||
h->capturelen = 0;
|
||||
@ -502,15 +558,15 @@ static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device)
|
||||
while (!SDL_AtomicGet(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
|
||||
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
|
||||
/*printf("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!\n");*/
|
||||
//SDL_Log("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!");
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
break;
|
||||
}
|
||||
|
||||
if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) {
|
||||
/* a new fragment is available! Just dump it. */
|
||||
// a new fragment is available! Just dump it.
|
||||
PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes);
|
||||
PULSEAUDIO_pa_stream_drop(h->stream); /* drop this fragment. */
|
||||
PULSEAUDIO_pa_stream_drop(h->stream); // drop this fragment.
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,7 +578,7 @@ static void PULSEAUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
|
||||
if (device->hidden->stream) {
|
||||
if (device->hidden->capturebuf != NULL) {
|
||||
if (device->hidden->capturebuf) {
|
||||
PULSEAUDIO_pa_stream_drop(device->hidden->stream);
|
||||
}
|
||||
PULSEAUDIO_pa_stream_disconnect(device->hidden->stream);
|
||||
@ -532,46 +588,12 @@ static void PULSEAUDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
|
||||
SDL_free(device->hidden->mixbuf);
|
||||
SDL_free(device->hidden->device_name);
|
||||
SDL_free(device->hidden);
|
||||
}
|
||||
|
||||
static void SinkDeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
|
||||
{
|
||||
if (i) {
|
||||
char **devname = (char **)data;
|
||||
*devname = SDL_strdup(i->name);
|
||||
}
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
||||
}
|
||||
|
||||
static void SourceDeviceNameCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
|
||||
{
|
||||
if (i) {
|
||||
char **devname = (char **)data;
|
||||
*devname = SDL_strdup(i->name);
|
||||
}
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
||||
}
|
||||
|
||||
static SDL_bool FindDeviceName(SDL_AudioDevice *device)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = device->hidden;
|
||||
SDL_assert(device->handle != NULL); // this was a thing in SDL2, but shouldn't be in SDL3.
|
||||
const uint32_t idx = ((uint32_t)((intptr_t)device->handle)) - 1;
|
||||
|
||||
if (device->iscapture) {
|
||||
WaitForPulseOperation(PULSEAUDIO_pa_context_get_source_info_by_index(pulseaudio_context, idx, SourceDeviceNameCallback, &h->device_name));
|
||||
} else {
|
||||
WaitForPulseOperation(PULSEAUDIO_pa_context_get_sink_info_by_index(pulseaudio_context, idx, SinkDeviceNameCallback, &h->device_name));
|
||||
}
|
||||
|
||||
return h->device_name != NULL;
|
||||
}
|
||||
|
||||
static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata)
|
||||
{
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* just signal any waiting code, it can look up the details. */
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details.
|
||||
}
|
||||
|
||||
static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
@ -590,17 +612,17 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
SDL_assert(pulseaudio_threaded_mainloop != NULL);
|
||||
SDL_assert(pulseaudio_context != NULL);
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
// Initialize all variables that we clean on shutdown
|
||||
h = device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
// Try for a closest match on audio format
|
||||
closefmts = SDL_ClosestAudioFormats(device->spec.format);
|
||||
while ((test_format = *(closefmts++)) != 0) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
SDL_Log("pulseaudio: Trying format 0x%4.4x", test_format);
|
||||
#endif
|
||||
switch (test_format) {
|
||||
case SDL_AUDIO_U8:
|
||||
@ -635,14 +657,14 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
device->spec.format = test_format;
|
||||
paspec.format = format;
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
// Calculate the final parameters for this audio specification
|
||||
SDL_UpdatedAudioDeviceFormat(device);
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
// Allocate mixing buffer
|
||||
if (!iscapture) {
|
||||
h->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
|
||||
if (h->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!h->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(h->mixbuf, device->silence_value, device->buffer_size);
|
||||
}
|
||||
@ -650,8 +672,8 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
paspec.channels = device->spec.channels;
|
||||
paspec.rate = device->spec.freq;
|
||||
|
||||
/* Reduced prebuffering compared to the defaults. */
|
||||
paattr.fragsize = device->buffer_size;
|
||||
// Reduced prebuffering compared to the defaults.
|
||||
paattr.fragsize = device->buffer_size; // despite the name, this is only used for capture devices, according to PulseAudio docs!
|
||||
paattr.tlength = device->buffer_size;
|
||||
paattr.prebuf = -1;
|
||||
paattr.maxlength = -1;
|
||||
@ -660,50 +682,55 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
|
||||
if (!FindDeviceName(device)) {
|
||||
retval = SDL_SetError("Requested PulseAudio sink/source missing?");
|
||||
const char *name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
|
||||
// The SDL ALSA output hints us that we use Windows' channel mapping
|
||||
// https://bugzilla.libsdl.org/show_bug.cgi?id=110
|
||||
PULSEAUDIO_pa_channel_map_init_auto(&pacmap, device->spec.channels, PA_CHANNEL_MAP_WAVEEX);
|
||||
|
||||
h->stream = PULSEAUDIO_pa_stream_new(
|
||||
pulseaudio_context,
|
||||
(name && *name) ? name : "Audio Stream", // stream description
|
||||
&paspec, // sample format spec
|
||||
&pacmap // channel map
|
||||
);
|
||||
|
||||
if (!h->stream) {
|
||||
retval = SDL_SetError("Could not set up PulseAudio stream");
|
||||
} else {
|
||||
const char *name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
|
||||
/* The SDL ALSA output hints us that we use Windows' channel mapping */
|
||||
/* https://bugzilla.libsdl.org/show_bug.cgi?id=110 */
|
||||
PULSEAUDIO_pa_channel_map_init_auto(&pacmap, device->spec.channels, PA_CHANNEL_MAP_WAVEEX);
|
||||
int rc;
|
||||
|
||||
h->stream = PULSEAUDIO_pa_stream_new(
|
||||
pulseaudio_context,
|
||||
(name && *name) ? name : "Audio Stream", /* stream description */
|
||||
&paspec, /* sample format spec */
|
||||
&pacmap /* channel map */
|
||||
);
|
||||
PULSEAUDIO_pa_stream_set_state_callback(h->stream, PulseStreamStateChangeCallback, NULL);
|
||||
|
||||
if (h->stream == NULL) {
|
||||
retval = SDL_SetError("Could not set up PulseAudio stream");
|
||||
// SDL manages device moves if the default changes, so don't ever let Pulse automatically migrate this stream.
|
||||
flags |= PA_STREAM_DONT_MOVE;
|
||||
|
||||
const char *device_path = ((PulseDeviceHandle *) device->handle)->device_path;
|
||||
if (iscapture) {
|
||||
PULSEAUDIO_pa_stream_set_read_callback(h->stream, ReadCallback, h);
|
||||
rc = PULSEAUDIO_pa_stream_connect_record(h->stream, device_path, &paattr, flags);
|
||||
} else {
|
||||
int rc;
|
||||
PULSEAUDIO_pa_stream_set_write_callback(h->stream, WriteCallback, h);
|
||||
rc = PULSEAUDIO_pa_stream_connect_playback(h->stream, device_path, &paattr, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
PULSEAUDIO_pa_stream_set_state_callback(h->stream, PulseStreamStateChangeCallback, NULL);
|
||||
|
||||
// SDL manages device moves if the default changes, so don't ever let Pulse automatically migrate this stream.
|
||||
flags |= PA_STREAM_DONT_MOVE;
|
||||
|
||||
if (iscapture) {
|
||||
PULSEAUDIO_pa_stream_set_read_callback(h->stream, ReadCallback, h);
|
||||
rc = PULSEAUDIO_pa_stream_connect_record(h->stream, h->device_name, &paattr, flags);
|
||||
} else {
|
||||
PULSEAUDIO_pa_stream_set_write_callback(h->stream, WriteCallback, h);
|
||||
rc = PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags, NULL, NULL);
|
||||
if (rc < 0) {
|
||||
retval = SDL_SetError("Could not connect PulseAudio stream");
|
||||
} else {
|
||||
int state = PULSEAUDIO_pa_stream_get_state(h->stream);
|
||||
while (PA_STREAM_IS_GOOD(state) && (state != PA_STREAM_READY)) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
|
||||
state = PULSEAUDIO_pa_stream_get_state(h->stream);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
if (!PA_STREAM_IS_GOOD(state)) {
|
||||
retval = SDL_SetError("Could not connect PulseAudio stream");
|
||||
} else {
|
||||
int state = PULSEAUDIO_pa_stream_get_state(h->stream);
|
||||
while (PA_STREAM_IS_GOOD(state) && (state != PA_STREAM_READY)) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
|
||||
state = PULSEAUDIO_pa_stream_get_state(h->stream);
|
||||
}
|
||||
|
||||
if (!PA_STREAM_IS_GOOD(state)) {
|
||||
retval = SDL_SetError("Could not connect PulseAudio stream");
|
||||
const pa_buffer_attr *actual_bufattr = PULSEAUDIO_pa_stream_get_buffer_attr(h->stream);
|
||||
if (!actual_bufattr) {
|
||||
retval = SDL_SetError("Could not determine connected PulseAudio stream's buffer attributes");
|
||||
} else {
|
||||
device->buffer_size = (int) iscapture ? actual_bufattr->tlength : actual_bufattr->fragsize;
|
||||
device->sample_frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -711,11 +738,11 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
|
||||
/* We're (hopefully) ready to rock and roll. :-) */
|
||||
// We're (hopefully) ready to rock and roll. :-)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* device handles are device index + 1, cast to void*, so we never pass a NULL. */
|
||||
// device handles are device index + 1, cast to void*, so we never pass a NULL.
|
||||
|
||||
static SDL_AudioFormat PulseFormatToSDLFormat(pa_sample_format_t format)
|
||||
{
|
||||
@ -739,76 +766,90 @@ static SDL_AudioFormat PulseFormatToSDLFormat(pa_sample_format_t format)
|
||||
}
|
||||
}
|
||||
|
||||
static void AddPulseAudioDevice(const SDL_bool iscapture, const char *description, const char *name, const uint32_t index, const pa_sample_spec *sample_spec)
|
||||
{
|
||||
SDL_AudioSpec spec;
|
||||
spec.format = PulseFormatToSDLFormat(sample_spec->format);
|
||||
spec.channels = sample_spec->channels;
|
||||
spec.freq = sample_spec->rate;
|
||||
PulseDeviceHandle *handle = (PulseDeviceHandle *) SDL_malloc(sizeof (PulseDeviceHandle));
|
||||
if (handle) {
|
||||
handle->device_path = SDL_strdup(name);
|
||||
if (!handle->device_path) {
|
||||
SDL_free(handle);
|
||||
} else {
|
||||
handle->device_index = index;
|
||||
}
|
||||
SDL_AddAudioDevice(iscapture, description, &spec, handle);
|
||||
}
|
||||
}
|
||||
|
||||
// This is called when PulseAudio adds an output ("sink") device.
|
||||
// !!! FIXME: this is almost identical to SourceInfoCallback, merge the two.
|
||||
static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
|
||||
{
|
||||
if (i) {
|
||||
const SDL_bool add = (SDL_bool) ((intptr_t)data);
|
||||
|
||||
if (add) {
|
||||
SDL_AudioSpec spec;
|
||||
spec.format = PulseFormatToSDLFormat(i->sample_spec.format);
|
||||
spec.channels = i->sample_spec.channels;
|
||||
spec.freq = i->sample_spec.rate;
|
||||
SDL_AddAudioDevice(SDL_FALSE, i->description, &spec, (void *)((intptr_t)i->index + 1));
|
||||
}
|
||||
|
||||
if (default_sink_path != NULL && SDL_strcmp(i->name, default_sink_path) == 0) {
|
||||
default_sink_index = i->index;
|
||||
}
|
||||
AddPulseAudioDevice(SDL_FALSE, i->description, i->name, i->index, &i->sample_spec);
|
||||
}
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
||||
}
|
||||
|
||||
/* This is called when PulseAudio adds a capture ("source") device. */
|
||||
// !!! FIXME: this is almost identical to SinkInfoCallback, merge the two.
|
||||
// This is called when PulseAudio adds a capture ("source") device.
|
||||
static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
|
||||
{
|
||||
/* Maybe skip "monitor" sources. These are just output from other sinks. */
|
||||
// Maybe skip "monitor" sources. These are just output from other sinks.
|
||||
if (i && (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX))) {
|
||||
const SDL_bool add = (SDL_bool) ((intptr_t)data);
|
||||
|
||||
if (add) {
|
||||
SDL_AudioSpec spec;
|
||||
spec.format = PulseFormatToSDLFormat(i->sample_spec.format);
|
||||
spec.channels = i->sample_spec.channels;
|
||||
spec.freq = i->sample_spec.rate;
|
||||
SDL_AddAudioDevice(SDL_TRUE, i->description, &spec, (void *)((intptr_t)i->index + 1));
|
||||
}
|
||||
|
||||
if (default_source_path != NULL && SDL_strcmp(i->name, default_source_path) == 0) {
|
||||
default_source_index = i->index;
|
||||
}
|
||||
AddPulseAudioDevice(SDL_TRUE, i->description, i->name, i->index, &i->sample_spec);
|
||||
}
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
||||
}
|
||||
|
||||
static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data)
|
||||
{
|
||||
if (!default_sink_path || (SDL_strcmp(i->default_sink_name, default_sink_path) != 0)) {
|
||||
/*printf("DEFAULT SINK PATH CHANGED TO '%s'\n", i->default_sink_name);*/
|
||||
SDL_free(default_sink_path);
|
||||
default_sink_path = SDL_strdup(i->default_sink_name);
|
||||
//SDL_Log("PULSEAUDIO ServerInfoCallback!");
|
||||
|
||||
if (!default_sink_path || (SDL_strcmp(default_sink_path, i->default_sink_name) != 0)) {
|
||||
char *str = SDL_strdup(i->default_sink_name);
|
||||
if (str) {
|
||||
SDL_free(default_sink_path);
|
||||
default_sink_path = str;
|
||||
default_sink_changed = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!default_source_path || (SDL_strcmp(i->default_source_name, default_source_path) != 0)) {
|
||||
/*printf("DEFAULT SOURCE PATH CHANGED TO '%s'\n", i->default_source_name);*/
|
||||
SDL_free(default_source_path);
|
||||
default_source_path = SDL_strdup(i->default_source_name);
|
||||
if (!default_source_path || (SDL_strcmp(default_source_path, i->default_source_name) != 0)) {
|
||||
char *str = SDL_strdup(i->default_source_name);
|
||||
if (str) {
|
||||
SDL_free(default_source_path);
|
||||
default_source_path = str;
|
||||
default_source_changed = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
||||
}
|
||||
|
||||
// This is called when PulseAudio has a device connected/removed/changed. */
|
||||
static SDL_bool FindAudioDeviceByIndex(SDL_AudioDevice *device, void *userdata)
|
||||
{
|
||||
const uint32_t idx = (uint32_t) (uintptr_t) userdata;
|
||||
const PulseDeviceHandle *handle = (const PulseDeviceHandle *) device->handle;
|
||||
return (handle->device_index == idx);
|
||||
}
|
||||
|
||||
static SDL_bool FindAudioDeviceByPath(SDL_AudioDevice *device, void *userdata)
|
||||
{
|
||||
const char *path = (const char *) userdata;
|
||||
const PulseDeviceHandle *handle = (const PulseDeviceHandle *) device->handle;
|
||||
return (SDL_strcmp(handle->device_path, path) == 0);
|
||||
}
|
||||
|
||||
// This is called when PulseAudio has a device connected/removed/changed.
|
||||
static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *data)
|
||||
{
|
||||
const SDL_bool added = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW);
|
||||
const SDL_bool removed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE);
|
||||
const SDL_bool changed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE);
|
||||
|
||||
if (added || removed || changed) { /* we only care about add/remove events. */
|
||||
if (added || removed || changed) { // we only care about add/remove events.
|
||||
const SDL_bool sink = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK);
|
||||
const SDL_bool source = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
|
||||
|
||||
@ -819,41 +860,44 @@ static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint3
|
||||
/* adds need sink details from the PulseAudio server. Another callback...
|
||||
(just unref all these operations right away, because we aren't going to wait on them
|
||||
and their callbacks will handle any work, so they can free as soon as that happens.) */
|
||||
if ((added || changed) && sink) {
|
||||
PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_sink_info_by_index(pulseaudio_context, idx, SinkInfoCallback, (void *)((intptr_t)added)));
|
||||
} else if ((added || changed) && source) {
|
||||
PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_source_info_by_index(pulseaudio_context, idx, SourceInfoCallback, (void *)((intptr_t)added)));
|
||||
if (added && sink) {
|
||||
PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_sink_info_by_index(pulseaudio_context, idx, SinkInfoCallback, NULL));
|
||||
} else if (added && source) {
|
||||
PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_source_info_by_index(pulseaudio_context, idx, SourceInfoCallback, NULL));
|
||||
} else if (removed && (sink || source)) {
|
||||
// removes we can handle just with the device index.
|
||||
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle((void *)((intptr_t)idx + 1)));
|
||||
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByIndex, (void *)(uintptr_t)idx));
|
||||
}
|
||||
}
|
||||
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
|
||||
}
|
||||
|
||||
static void CheckDefaultDevice(uint32_t *prev_default, uint32_t new_default)
|
||||
static SDL_bool CheckDefaultDevice(const SDL_bool changed, char *device_path)
|
||||
{
|
||||
if (*prev_default != new_default) {
|
||||
SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByHandle((void *)((intptr_t)new_default + 1));
|
||||
if (device) {
|
||||
*prev_default = new_default;
|
||||
SDL_DefaultAudioDeviceChanged(device);
|
||||
}
|
||||
if (!changed) {
|
||||
return SDL_FALSE; // nothing's happening, leave the flag marked as unchanged.
|
||||
} else if (!device_path) {
|
||||
return SDL_TRUE; // check again later, we don't have a device name...
|
||||
}
|
||||
|
||||
SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, device_path);
|
||||
if (device) { // if NULL, we might still be waiting for a SinkInfoCallback or something, we'll try later.
|
||||
SDL_DefaultAudioDeviceChanged(device);
|
||||
return SDL_FALSE; // changing complete, set flag to unchanged for future tests.
|
||||
}
|
||||
return SDL_TRUE; // couldn't find the changed device, leave it marked as changed to try again later.
|
||||
}
|
||||
|
||||
// this runs as a thread while the Pulse target is initialized to catch hotplug events.
|
||||
static int SDLCALL HotplugThread(void *data)
|
||||
{
|
||||
uint32_t prev_default_sink_index = default_sink_index;
|
||||
uint32_t prev_default_source_index = default_source_index;
|
||||
pa_operation *op;
|
||||
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
PULSEAUDIO_pa_context_set_subscribe_callback(pulseaudio_context, HotplugCallback, NULL);
|
||||
|
||||
/* don't WaitForPulseOperation on the subscription; when it's done we'll be able to get hotplug events, but waiting doesn't changing anything. */
|
||||
// don't WaitForPulseOperation on the subscription; when it's done we'll be able to get hotplug events, but waiting doesn't changing anything.
|
||||
op = PULSEAUDIO_pa_context_subscribe(pulseaudio_context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SERVER, NULL, NULL);
|
||||
|
||||
SDL_PostSemaphore((SDL_Semaphore *) data);
|
||||
@ -866,11 +910,23 @@ static int SDLCALL HotplugThread(void *data)
|
||||
}
|
||||
|
||||
// Update default devices; don't hold the pulse lock during this, since it could deadlock vs a playing device that we're about to lock here.
|
||||
SDL_bool check_default_sink = default_sink_changed;
|
||||
SDL_bool check_default_source = default_source_changed;
|
||||
char *current_default_sink = check_default_sink ? SDL_strdup(default_sink_path) : NULL;
|
||||
char *current_default_source = check_default_source ? SDL_strdup(default_source_path) : NULL;
|
||||
default_sink_changed = default_source_changed = SDL_FALSE;
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
CheckDefaultDevice(&prev_default_sink_index, default_sink_index);
|
||||
CheckDefaultDevice(&prev_default_source_index, default_source_index);
|
||||
check_default_sink = CheckDefaultDevice(check_default_sink, current_default_sink);
|
||||
check_default_source = CheckDefaultDevice(check_default_source, current_default_source);
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
|
||||
// free our copies (which will be NULL if nothing changed)
|
||||
SDL_free(current_default_sink);
|
||||
SDL_free(current_default_source);
|
||||
|
||||
// set these to true if we didn't handle the change OR there was _another_ change while we were working unlocked.
|
||||
default_sink_changed = (default_sink_changed || check_default_sink);
|
||||
default_source_changed = (default_source_changed || check_default_source);
|
||||
}
|
||||
|
||||
if (op) {
|
||||
@ -880,8 +936,6 @@ static int SDLCALL HotplugThread(void *data)
|
||||
PULSEAUDIO_pa_context_set_subscribe_callback(pulseaudio_context, NULL, NULL);
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture)
|
||||
@ -890,29 +944,33 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio
|
||||
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
WaitForPulseOperation(PULSEAUDIO_pa_context_get_server_info(pulseaudio_context, ServerInfoCallback, NULL));
|
||||
WaitForPulseOperation(PULSEAUDIO_pa_context_get_sink_info_list(pulseaudio_context, SinkInfoCallback, (void *)((intptr_t)SDL_TRUE)));
|
||||
WaitForPulseOperation(PULSEAUDIO_pa_context_get_source_info_list(pulseaudio_context, SourceInfoCallback, (void *)((intptr_t)SDL_TRUE)));
|
||||
WaitForPulseOperation(PULSEAUDIO_pa_context_get_sink_info_list(pulseaudio_context, SinkInfoCallback, NULL));
|
||||
WaitForPulseOperation(PULSEAUDIO_pa_context_get_source_info_list(pulseaudio_context, SourceInfoCallback, NULL));
|
||||
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
|
||||
|
||||
SDL_AudioDevice *device;
|
||||
device = SDL_FindPhysicalAudioDeviceByHandle((void *)((intptr_t)default_sink_index + 1));
|
||||
if (device) {
|
||||
*default_output = device;
|
||||
if (default_sink_path) {
|
||||
*default_output = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path);
|
||||
}
|
||||
|
||||
device = SDL_FindPhysicalAudioDeviceByHandle((void *)((intptr_t)default_source_index + 1));
|
||||
if (device) {
|
||||
*default_capture = device;
|
||||
if (default_source_path) {
|
||||
*default_capture = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path);
|
||||
}
|
||||
|
||||
/* ok, we have a sane list, let's set up hotplug notifications now... */
|
||||
// ok, we have a sane list, let's set up hotplug notifications now...
|
||||
SDL_AtomicSet(&pulseaudio_hotplug_thread_active, 1);
|
||||
pulseaudio_hotplug_thread = SDL_CreateThreadInternal(HotplugThread, "PulseHotplug", 256 * 1024, ready_sem); // !!! FIXME: this can probably survive in significantly less stack space.
|
||||
SDL_WaitSemaphore(ready_sem);
|
||||
SDL_DestroySemaphore(ready_sem);
|
||||
}
|
||||
|
||||
static void PULSEAUDIO_Deinitialize(void)
|
||||
static void PULSEAUDIO_FreeDeviceHandle(SDL_AudioDevice *device)
|
||||
{
|
||||
PulseDeviceHandle *handle = (PulseDeviceHandle *) device->handle;
|
||||
SDL_free(handle->device_path);
|
||||
SDL_free(handle);
|
||||
}
|
||||
|
||||
static void PULSEAUDIO_DeinitializeStart(void)
|
||||
{
|
||||
if (pulseaudio_hotplug_thread) {
|
||||
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
|
||||
@ -922,16 +980,18 @@ static void PULSEAUDIO_Deinitialize(void)
|
||||
SDL_WaitThread(pulseaudio_hotplug_thread, NULL);
|
||||
pulseaudio_hotplug_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void PULSEAUDIO_Deinitialize(void)
|
||||
{
|
||||
DisconnectFromPulseServer();
|
||||
|
||||
SDL_free(default_sink_path);
|
||||
default_sink_path = NULL;
|
||||
default_sink_changed = SDL_FALSE;
|
||||
SDL_free(default_source_path);
|
||||
default_source_path = NULL;
|
||||
|
||||
default_source_index = 0;
|
||||
default_sink_index = 0;
|
||||
default_source_changed = SDL_FALSE;
|
||||
|
||||
UnloadPulseAudioLibrary();
|
||||
}
|
||||
@ -947,25 +1007,26 @@ static SDL_bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
|
||||
include_monitors = SDL_GetHintBoolean(SDL_HINT_AUDIO_INCLUDE_MONITORS, SDL_FALSE);
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = PULSEAUDIO_DetectDevices;
|
||||
impl->OpenDevice = PULSEAUDIO_OpenDevice;
|
||||
impl->PlayDevice = PULSEAUDIO_PlayDevice;
|
||||
impl->WaitDevice = PULSEAUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = PULSEAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = PULSEAUDIO_CloseDevice;
|
||||
impl->DeinitializeStart = PULSEAUDIO_DeinitializeStart;
|
||||
impl->Deinitialize = PULSEAUDIO_Deinitialize;
|
||||
impl->WaitCaptureDevice = PULSEAUDIO_WaitCaptureDevice;
|
||||
impl->CaptureFromDevice = PULSEAUDIO_CaptureFromDevice;
|
||||
impl->FlushCapture = PULSEAUDIO_FlushCapture;
|
||||
impl->FreeDeviceHandle = PULSEAUDIO_FreeDeviceHandle;
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
AudioBootStrap PULSEAUDIO_bootstrap = {
|
||||
"pulseaudio", "PulseAudio", PULSEAUDIO_Init, SDL_FALSE
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_PULSEAUDIO */
|
||||
#endif // SDL_AUDIO_DRIVER_PULSEAUDIO
|
||||
|
@ -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
|
||||
@ -29,18 +29,16 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
char *device_name;
|
||||
|
||||
/* pulseaudio structures */
|
||||
// pulseaudio structures
|
||||
pa_stream *stream;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
// Raw mixing buffer
|
||||
Uint8 *mixbuf;
|
||||
|
||||
int bytes_requested; /* bytes of data the hardware wants _now_. */
|
||||
int bytes_requested; // bytes of data the hardware wants _now_.
|
||||
|
||||
const Uint8 *capturebuf;
|
||||
int capturelen;
|
||||
};
|
||||
|
||||
#endif /* SDL_pulseaudio_h_ */
|
||||
#endif // SDL_pulseaudio_h_
|
||||
|
26
external/sdl/SDL/src/audio/qnx/SDL_qsa_audio.c
vendored
26
external/sdl/SDL/src/audio/qnx/SDL_qsa_audio.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 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
|
||||
@ -39,7 +39,7 @@
|
||||
#include "SDL3/SDL_timer.h"
|
||||
#include "SDL3/SDL_audio.h"
|
||||
#include "../../core/unix/SDL_poll.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_qsa_audio.h"
|
||||
|
||||
// default channel communication parameters
|
||||
@ -86,21 +86,19 @@ static void QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
|
||||
}
|
||||
|
||||
// This function waits until it is possible to write a full sound buffer
|
||||
static void QSA_WaitDevice(SDL_AudioDevice *device)
|
||||
static int QSA_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
int result;
|
||||
|
||||
// Setup timeout for playing one fragment equal to 2 seconds
|
||||
// If timeout occurred than something wrong with hardware or driver
|
||||
// For example, Vortex 8820 audio driver stucks on second DAC because
|
||||
// it doesn't exist !
|
||||
result = SDL_IOReady(device->hidden->audio_fd,
|
||||
device->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE,
|
||||
2 * 1000);
|
||||
const int result = SDL_IOReady(device->hidden->audio_fd,
|
||||
device->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE,
|
||||
2 * 1000);
|
||||
switch (result) {
|
||||
case -1:
|
||||
SDL_SetError("QSA: SDL_IOReady() failed: %s", strerror(errno)); // !!! FIXME: Should we just disconnect the device in this case?
|
||||
break;
|
||||
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "QSA: SDL_IOReady() failed: %s", strerror(errno));
|
||||
return -1;
|
||||
case 0:
|
||||
device->hidden->timeout_on_wait = SDL_TRUE; // !!! FIXME: Should we just disconnect the device in this case?
|
||||
break;
|
||||
@ -108,6 +106,8 @@ static void QSA_WaitDevice(SDL_AudioDevice *device)
|
||||
device->hidden->timeout_on_wait = SDL_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
@ -176,7 +176,7 @@ static Uint8 *QSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
static void QSA_CloseDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
if (device->hidden) {
|
||||
if (device->hidden->audio_handle != NULL) {
|
||||
if (device->hidden->audio_handle) {
|
||||
#if _NTO_VERSION < 710
|
||||
// Finish playing available samples or cancel unread samples during capture
|
||||
snd_pcm_plugin_flush(device->hidden->audio_handle, device->iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK);
|
||||
@ -206,7 +206,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device)
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof (struct SDL_PrivateAudioData)));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initialize channel transfer parameters to default
|
||||
@ -275,7 +275,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
device->hidden->pcm_buf = (Uint8 *) SDL_malloc(device->buffer_size);
|
||||
if (device->hidden->pcm_buf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(device->hidden->pcm_buf, device->silence_value, device->buffer_size);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 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
|
||||
@ -36,6 +36,5 @@ struct SDL_PrivateAudioData
|
||||
Uint8 *pcm_buf; // Raw mixing buffer
|
||||
};
|
||||
|
||||
#endif /* __SDL_QSA_AUDIO_H__ */
|
||||
#endif // __SDL_QSA_AUDIO_H__
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
@ -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
|
||||
@ -36,7 +36,7 @@
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_sndioaudio.h"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
|
||||
@ -71,7 +71,7 @@ static void *sndio_handle = NULL;
|
||||
static int load_sndio_sym(const char *fn, void **addr)
|
||||
{
|
||||
*addr = SDL_LoadFunction(sndio_handle, fn);
|
||||
if (*addr == NULL) {
|
||||
if (!*addr) {
|
||||
return 0; // Don't call SDL_SetError(): SDL_LoadFunction already did.
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ static int load_sndio_syms(void)
|
||||
|
||||
static void UnloadSNDIOLibrary(void)
|
||||
{
|
||||
if (sndio_handle != NULL) {
|
||||
if (sndio_handle) {
|
||||
SDL_UnloadObject(sndio_handle);
|
||||
sndio_handle = NULL;
|
||||
}
|
||||
@ -119,9 +119,9 @@ static void UnloadSNDIOLibrary(void)
|
||||
static int LoadSNDIOLibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (sndio_handle == NULL) {
|
||||
if (!sndio_handle) {
|
||||
sndio_handle = SDL_LoadObject(sndio_library);
|
||||
if (sndio_handle == NULL) {
|
||||
if (!sndio_handle) {
|
||||
retval = -1; // Don't call SDL_SetError(): SDL_LoadObject already did.
|
||||
} else {
|
||||
retval = load_sndio_syms();
|
||||
@ -147,32 +147,31 @@ static int LoadSNDIOLibrary(void)
|
||||
|
||||
#endif // SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
|
||||
|
||||
static void SNDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
static int SNDIO_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
const SDL_bool iscapture = device->iscapture;
|
||||
|
||||
while (!SDL_AtomicGet(&device->shutdown)) {
|
||||
if (SNDIO_sio_eof(device->hidden->dev)) {
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int nfds = SNDIO_sio_pollfd(device->hidden->dev, device->hidden->pfd, iscapture ? POLLIN : POLLOUT);
|
||||
if (nfds <= 0 || poll(device->hidden->pfd, nfds, 10) < 0) {
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int revents = SNDIO_sio_revents(device->hidden->dev, device->hidden->pfd);
|
||||
if (iscapture && (revents & POLLIN)) {
|
||||
return;
|
||||
break;
|
||||
} else if (!iscapture && (revents & POLLOUT)) {
|
||||
return;
|
||||
break;
|
||||
} else if (revents & POLLHUP) {
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SNDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
@ -214,7 +213,7 @@ static Uint8 *SNDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
static void SNDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
if (device->hidden) {
|
||||
if (device->hidden->dev != NULL) {
|
||||
if (device->hidden->dev) {
|
||||
SNDIO_sio_stop(device->hidden->dev);
|
||||
SNDIO_sio_close(device->hidden->dev);
|
||||
}
|
||||
@ -228,23 +227,23 @@ static void SNDIO_CloseDevice(SDL_AudioDevice *device)
|
||||
static int SNDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// !!! FIXME: we really should standardize this on a specific SDL hint.
|
||||
const char *audiodev = SDL_getenv("AUDIODEV");
|
||||
|
||||
// Capture devices must be non-blocking for SNDIO_FlushCapture
|
||||
device->hidden->dev = SNDIO_sio_open(audiodev != NULL ? audiodev : SIO_DEVANY,
|
||||
device->hidden->dev = SNDIO_sio_open(audiodev ? audiodev : SIO_DEVANY,
|
||||
device->iscapture ? SIO_REC : SIO_PLAY, device->iscapture);
|
||||
if (device->hidden->dev == NULL) {
|
||||
if (!device->hidden->dev) {
|
||||
return SDL_SetError("sio_open() failed");
|
||||
}
|
||||
|
||||
device->hidden->pfd = SDL_malloc(sizeof(struct pollfd) * SNDIO_sio_nfds(device->hidden->dev));
|
||||
if (device->hidden->pfd == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden->pfd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sio_par par;
|
||||
@ -308,8 +307,8 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device)
|
||||
|
||||
// Allocate mixing buffer
|
||||
device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size);
|
||||
if (device->hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden->mixbuf) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size);
|
||||
|
||||
@ -348,7 +347,6 @@ static SDL_bool SNDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->Deinitialize = SNDIO_Deinitialize;
|
||||
impl->DetectDevices = SNDIO_DetectDevices;
|
||||
|
||||
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE;
|
||||
|
@ -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
|
||||
@ -35,4 +35,4 @@ struct SDL_PrivateAudioData
|
||||
struct pollfd *pfd; // Polling structures for non-blocking sndio devices
|
||||
};
|
||||
|
||||
#endif /* SDL_sndioaudio_h_ */
|
||||
#endif // SDL_sndioaudio_h_
|
||||
|
22
external/sdl/SDL/src/audio/vita/SDL_vitaaudio.c
vendored
22
external/sdl/SDL/src/audio/vita/SDL_vitaaudio.c
vendored
@ -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
|
||||
@ -26,7 +26,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_audiodev_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_vitaaudio.h"
|
||||
@ -63,11 +62,10 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device)
|
||||
const SDL_AudioFormat *closefmts;
|
||||
|
||||
device->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc(sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
}
|
||||
SDL_memset(device->hidden, 0, sizeof(*device->hidden));
|
||||
|
||||
closefmts = SDL_ClosestAudioFormats(device->spec.format);
|
||||
while ((test_format = *(closefmts++)) != 0) {
|
||||
@ -96,7 +94,7 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device)
|
||||
64, so spec->size should be a multiple of 64 as well. */
|
||||
mixlen = device->buffer_size * NUM_BUFFERS;
|
||||
device->hidden->rawbuf = (Uint8 *)SDL_aligned_alloc(64, mixlen);
|
||||
if (device->hidden->rawbuf == NULL) {
|
||||
if (!device->hidden->rawbuf) {
|
||||
return SDL_SetError("Couldn't allocate mixing buffer");
|
||||
}
|
||||
|
||||
@ -136,12 +134,13 @@ static int VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
|
||||
}
|
||||
|
||||
// This function waits until it is possible to write a full sound buffer
|
||||
static void VITAAUD_WaitDevice(SDL_AudioDevice *device)
|
||||
static int VITAAUD_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// !!! FIXME: we might just need to sleep roughly as long as playback buffers take to process, based on sample rate, etc.
|
||||
while (!SDL_AtomicGet(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) {
|
||||
SDL_Delay(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint8 *VITAAUD_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
@ -163,8 +162,8 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device)
|
||||
device->hidden->port = -1;
|
||||
}
|
||||
|
||||
if (!device->iscapture && device->hidden->rawbuf != NULL) {
|
||||
SDL_aligned_free(device->hidden->rawbuf); // this uses memalign(), not SDL_malloc().
|
||||
if (!device->iscapture && device->hidden->rawbuf) {
|
||||
SDL_aligned_free(device->hidden->rawbuf); // this uses SDL_aligned_alloc(), not SDL_malloc()
|
||||
device->hidden->rawbuf = NULL;
|
||||
}
|
||||
SDL_free(device->hidden);
|
||||
@ -172,7 +171,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
}
|
||||
|
||||
static void VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
static int VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// there's only a blocking call to obtain more data, so we'll just sleep as
|
||||
// long as a buffer would run.
|
||||
@ -180,6 +179,7 @@ static void VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device)
|
||||
while (!SDL_AtomicGet(&device->shutdown) && (SDL_GetTicks() < endticks)) {
|
||||
SDL_Delay(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int VITAAUD_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
|
||||
|
12
external/sdl/SDL/src/audio/vita/SDL_vitaaudio.h
vendored
12
external/sdl/SDL/src/audio/vita/SDL_vitaaudio.h
vendored
@ -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
|
||||
@ -28,14 +28,14 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The hardware input/output port. */
|
||||
// The hardware input/output port.
|
||||
int port;
|
||||
/* The raw allocated mixing buffer. */
|
||||
// The raw allocated mixing buffer.
|
||||
Uint8 *rawbuf;
|
||||
/* Individual mixing buffers. */
|
||||
// Individual mixing buffers.
|
||||
Uint8 *mixbufs[NUM_BUFFERS];
|
||||
/* Index of the next available mixing buffer. */
|
||||
// Index of the next available mixing buffer.
|
||||
int next_buffer;
|
||||
};
|
||||
|
||||
#endif /* SDL_vitaaudio_h */
|
||||
#endif // SDL_vitaaudio_h
|
||||
|
182
external/sdl/SDL/src/audio/wasapi/SDL_wasapi.c
vendored
182
external/sdl/SDL/src/audio/wasapi/SDL_wasapi.c
vendored
@ -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
|
||||
@ -25,7 +25,6 @@
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../../core/windows/SDL_immdevice.h"
|
||||
#include "../../thread/SDL_systhread.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
#define COBJMACROS
|
||||
@ -94,7 +93,7 @@ static void ManagementThreadMainloop(void)
|
||||
int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, int *wait_on_result)
|
||||
{
|
||||
// We want to block for a result, but we are already running from the management thread! Just run the task now so we don't deadlock.
|
||||
if ((wait_on_result != NULL) && (SDL_ThreadID() == SDL_GetThreadID(ManagementThread))) {
|
||||
if ((wait_on_result) && (SDL_ThreadID() == SDL_GetThreadID(ManagementThread))) {
|
||||
*wait_on_result = task(userdata);
|
||||
return 0; // completed!
|
||||
}
|
||||
@ -105,7 +104,7 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in
|
||||
|
||||
ManagementThreadPendingTask *pending = SDL_calloc(1, sizeof(ManagementThreadPendingTask));
|
||||
if (!pending) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
pending->fn = task;
|
||||
@ -125,11 +124,11 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in
|
||||
|
||||
// add to end of task list.
|
||||
ManagementThreadPendingTask *prev = NULL;
|
||||
for (ManagementThreadPendingTask *i = SDL_AtomicGetPtr((void **) &ManagementThreadPendingTasks); i != NULL; i = i->next) {
|
||||
for (ManagementThreadPendingTask *i = SDL_AtomicGetPtr((void **) &ManagementThreadPendingTasks); i; i = i->next) {
|
||||
prev = i;
|
||||
}
|
||||
|
||||
if (prev != NULL) {
|
||||
if (prev) {
|
||||
prev->next = pending;
|
||||
} else {
|
||||
SDL_AtomicSetPtr((void **) &ManagementThreadPendingTasks, pending);
|
||||
@ -265,6 +264,7 @@ static int mgmtthrtask_DetectDevices(void *userdata)
|
||||
static void WASAPI_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture)
|
||||
{
|
||||
int rc;
|
||||
// this blocks because it needs to finish before the audio subsystem inits
|
||||
mgmtthrtask_DetectDevicesData data = { default_output, default_capture };
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, &data, &rc);
|
||||
}
|
||||
@ -277,26 +277,31 @@ static int mgmtthrtask_DisconnectDevice(void *userdata)
|
||||
|
||||
void WASAPI_DisconnectDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// this runs async, so it can hold the device lock from the management thread.
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_DisconnectDevice, device, NULL);
|
||||
int rc; // block on this; don't disconnect while holding the device lock!
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_DisconnectDevice, device, &rc);
|
||||
}
|
||||
|
||||
static SDL_bool WasapiFailed(SDL_AudioDevice *device, const HRESULT err)
|
||||
{
|
||||
if (err == S_OK) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (err == AUDCLNT_E_DEVICE_INVALIDATED) {
|
||||
} else if (err == AUDCLNT_E_DEVICE_INVALIDATED) {
|
||||
device->hidden->device_lost = SDL_TRUE;
|
||||
} else {
|
||||
IAudioClient_Stop(device->hidden->client);
|
||||
WASAPI_DisconnectDevice(device);
|
||||
device->hidden->device_dead = SDL_TRUE;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static int mgmtthrtask_StopAndReleaseClient(void *userdata)
|
||||
{
|
||||
IAudioClient *client = (IAudioClient *) userdata;
|
||||
IAudioClient_Stop(client);
|
||||
IAudioClient_Release(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mgmtthrtask_ReleaseCaptureClient(void *userdata)
|
||||
{
|
||||
IAudioCaptureClient_Release((IAudioCaptureClient *)userdata);
|
||||
@ -309,56 +314,68 @@ static int mgmtthrtask_ReleaseRenderClient(void *userdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mgmtthrtask_ResetWasapiDevice(void *userdata)
|
||||
static int mgmtthrtask_CoTaskMemFree(void *userdata)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *)userdata;
|
||||
CoTaskMemFree(userdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!device || !device->hidden) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (device->hidden->client) {
|
||||
IAudioClient_Stop(device->hidden->client);
|
||||
IAudioClient_Release(device->hidden->client);
|
||||
device->hidden->client = NULL;
|
||||
}
|
||||
|
||||
if (device->hidden->render) {
|
||||
// this is silly, but this will block indefinitely if you call it from SDLMMNotificationClient_OnDefaultDeviceChanged, so
|
||||
// proxy this to the management thread to be released later.
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_ReleaseRenderClient, device->hidden->render, NULL);
|
||||
device->hidden->render = NULL;
|
||||
}
|
||||
|
||||
if (device->hidden->capture) {
|
||||
// this is silly, but this will block indefinitely if you call it from SDLMMNotificationClient_OnDefaultDeviceChanged, so
|
||||
// proxy this to the management thread to be released later.
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_ReleaseCaptureClient, device->hidden->capture, NULL);
|
||||
device->hidden->capture = NULL;
|
||||
}
|
||||
|
||||
if (device->hidden->waveformat) {
|
||||
CoTaskMemFree(device->hidden->waveformat);
|
||||
device->hidden->waveformat = NULL;
|
||||
}
|
||||
|
||||
if (device->hidden->activation_handler) {
|
||||
WASAPI_PlatformDeleteActivationHandler(device->hidden->activation_handler);
|
||||
device->hidden->activation_handler = NULL;
|
||||
}
|
||||
|
||||
if (device->hidden->event) {
|
||||
CloseHandle(device->hidden->event);
|
||||
device->hidden->event = NULL;
|
||||
}
|
||||
static int mgmtthrtask_PlatformDeleteActivationHandler(void *userdata)
|
||||
{
|
||||
WASAPI_PlatformDeleteActivationHandler(userdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mgmtthrtask_CloseHandle(void *userdata)
|
||||
{
|
||||
CloseHandle((HANDLE) userdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ResetWasapiDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
int rc;
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_ResetWasapiDevice, device, &rc);
|
||||
if (!device || !device->hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
// just queue up all the tasks in the management thread and don't block.
|
||||
// We don't care when any of these actually get free'd.
|
||||
|
||||
if (device->hidden->client) {
|
||||
IAudioClient *client = device->hidden->client;
|
||||
device->hidden->client = NULL;
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_StopAndReleaseClient, client, NULL);
|
||||
}
|
||||
|
||||
if (device->hidden->render) {
|
||||
IAudioRenderClient *render = device->hidden->render;
|
||||
device->hidden->render = NULL;
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_ReleaseRenderClient, render, NULL);
|
||||
}
|
||||
|
||||
if (device->hidden->capture) {
|
||||
IAudioCaptureClient *capture = device->hidden->capture;
|
||||
device->hidden->capture = NULL;
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_ReleaseCaptureClient, capture, NULL);
|
||||
}
|
||||
|
||||
if (device->hidden->waveformat) {
|
||||
void *ptr = device->hidden->waveformat;
|
||||
device->hidden->waveformat = NULL;
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_CoTaskMemFree, ptr, NULL);
|
||||
}
|
||||
|
||||
if (device->hidden->activation_handler) {
|
||||
void *activation_handler = device->hidden->activation_handler;
|
||||
device->hidden->activation_handler = NULL;
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_PlatformDeleteActivationHandler, activation_handler, NULL);
|
||||
}
|
||||
|
||||
if (device->hidden->event) {
|
||||
HANDLE event = device->hidden->event;
|
||||
device->hidden->event = NULL;
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_CloseHandle, (void *) event, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int mgmtthrtask_ActivateDevice(void *userdata)
|
||||
@ -368,10 +385,13 @@ static int mgmtthrtask_ActivateDevice(void *userdata)
|
||||
|
||||
static int ActivateWasapiDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
int rc;
|
||||
// this blocks because we're either being notified from a background thread or we're running during device open,
|
||||
// both of which won't deadlock vs the device thread.
|
||||
int rc = -1;
|
||||
return ((WASAPI_ProxyToManagementThread(mgmtthrtask_ActivateDevice, device, &rc) < 0) || (rc < 0)) ? -1 : 0;
|
||||
}
|
||||
|
||||
// do not call when holding the device lock!
|
||||
static SDL_bool RecoverWasapiDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
ResetWasapiDevice(device); // dump the lost device's handles.
|
||||
@ -387,10 +407,18 @@ static SDL_bool RecoverWasapiDevice(SDL_AudioDevice *device)
|
||||
return SDL_TRUE; // okay, carry on with new device details!
|
||||
}
|
||||
|
||||
// do not call when holding the device lock!
|
||||
static SDL_bool RecoverWasapiIfLost(SDL_AudioDevice *device)
|
||||
{
|
||||
if (SDL_AtomicGet(&device->shutdown)) {
|
||||
return SDL_FALSE; // already failed.
|
||||
} else if (device->hidden->device_dead) { // had a fatal error elsewhere, clean up and quit
|
||||
IAudioClient_Stop(device->hidden->client);
|
||||
WASAPI_DisconnectDevice(device);
|
||||
SDL_assert(SDL_AtomicGet(&device->shutdown)); // so we don't come back through here.
|
||||
return SDL_FALSE; // already failed.
|
||||
} else if (SDL_AtomicGet(&device->zombie)) {
|
||||
return SDL_FALSE; // we're already dead, so just leave and let the Zombie implementations take over.
|
||||
} else if (!device->hidden->client) {
|
||||
return SDL_TRUE; // still waiting for activation.
|
||||
}
|
||||
@ -403,9 +431,12 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
// get an endpoint buffer from WASAPI.
|
||||
BYTE *buffer = NULL;
|
||||
|
||||
if (RecoverWasapiIfLost(device) && device->hidden->render) {
|
||||
if (device->hidden->render) {
|
||||
if (WasapiFailed(device, IAudioRenderClient_GetBuffer(device->hidden->render, device->sample_frames, &buffer))) {
|
||||
SDL_assert(buffer == NULL);
|
||||
if (device->hidden->device_lost) { // just use an available buffer, we won't be playing it anyhow.
|
||||
*buffer_size = 0; // we'll recover during WaitDevice and try again.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,15 +445,16 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
|
||||
|
||||
static int WASAPI_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
||||
{
|
||||
if (device->hidden->render != NULL) { // definitely activated?
|
||||
if (device->hidden->render) { // definitely activated?
|
||||
// WasapiFailed() will mark the device for reacquisition or removal elsewhere.
|
||||
WasapiFailed(device, IAudioRenderClient_ReleaseBuffer(device->hidden->render, device->sample_frames, 0));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void WASAPI_WaitDevice(SDL_AudioDevice *device)
|
||||
static int WASAPI_WaitDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// WaitDevice does not hold the device lock, so check for recovery/disconnect details here.
|
||||
while (RecoverWasapiIfLost(device) && device->hidden->client && device->hidden->event) {
|
||||
DWORD waitResult = WaitForSingleObjectEx(device->hidden->event, 200, FALSE);
|
||||
if (waitResult == WAIT_OBJECT_0) {
|
||||
@ -439,9 +471,11 @@ static void WASAPI_WaitDevice(SDL_AudioDevice *device)
|
||||
} else if (waitResult != WAIT_TIMEOUT) {
|
||||
//SDL_Log("WASAPI FAILED EVENT!");*/
|
||||
IAudioClient_Stop(device->hidden->client);
|
||||
WASAPI_DisconnectDevice(device);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)
|
||||
@ -450,10 +484,10 @@ static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b
|
||||
UINT32 frames = 0;
|
||||
DWORD flags = 0;
|
||||
|
||||
while (RecoverWasapiIfLost(device) && device->hidden->capture) {
|
||||
HRESULT ret = IAudioCaptureClient_GetBuffer(device->hidden->capture, &ptr, &frames, &flags, NULL, NULL);
|
||||
while (device->hidden->capture) {
|
||||
const HRESULT ret = IAudioCaptureClient_GetBuffer(device->hidden->capture, &ptr, &frames, &flags, NULL, NULL);
|
||||
if (ret == AUDCLNT_S_BUFFER_EMPTY) {
|
||||
return 0; // in theory we should have waited until there was data, but oh well, we'll go back to waiting. Returning 0 is safe in SDL
|
||||
return 0; // in theory we should have waited until there was data, but oh well, we'll go back to waiting. Returning 0 is safe in SDL3.
|
||||
}
|
||||
|
||||
WasapiFailed(device, ret); // mark device lost/failed if necessary.
|
||||
@ -472,8 +506,7 @@ static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b
|
||||
SDL_memcpy(buffer, ptr, cpy);
|
||||
}
|
||||
|
||||
ret = IAudioCaptureClient_ReleaseBuffer(device->hidden->capture, frames);
|
||||
WasapiFailed(device, ret); // mark device lost/failed if necessary.
|
||||
WasapiFailed(device, IAudioCaptureClient_ReleaseBuffer(device->hidden->capture, frames));
|
||||
|
||||
return cpy;
|
||||
}
|
||||
@ -537,7 +570,7 @@ static int mgmtthrtask_PrepDevice(void *userdata)
|
||||
device->hidden->event = CreateEventW(NULL, 0, 0, NULL);
|
||||
#endif
|
||||
|
||||
if (device->hidden->event == NULL) {
|
||||
if (!device->hidden->event) {
|
||||
return WIN_SetError("WASAPI can't create an event handle");
|
||||
}
|
||||
|
||||
@ -666,8 +699,8 @@ static int WASAPI_OpenDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
// Initialize all variables that we clean on shutdown
|
||||
device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden));
|
||||
if (device->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!device->hidden) {
|
||||
return -1;
|
||||
} else if (ActivateWasapiDevice(device) < 0) {
|
||||
return -1; // already set error.
|
||||
}
|
||||
@ -702,6 +735,18 @@ static void WASAPI_FreeDeviceHandle(SDL_AudioDevice *device)
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_FreeDeviceHandle, device, &rc);
|
||||
}
|
||||
|
||||
static int mgmtthrtask_DeinitializeStart(void *userdata)
|
||||
{
|
||||
WASAPI_PlatformDeinitializeStart();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void WASAPI_DeinitializeStart(void)
|
||||
{
|
||||
int rc;
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_DeinitializeStart, NULL, &rc);
|
||||
}
|
||||
|
||||
static void WASAPI_Deinitialize(void)
|
||||
{
|
||||
DeinitManagementThread();
|
||||
@ -724,6 +769,7 @@ static SDL_bool WASAPI_Init(SDL_AudioDriverImpl *impl)
|
||||
impl->CaptureFromDevice = WASAPI_CaptureFromDevice;
|
||||
impl->FlushCapture = WASAPI_FlushCapture;
|
||||
impl->CloseDevice = WASAPI_CloseDevice;
|
||||
impl->DeinitializeStart = WASAPI_DeinitializeStart;
|
||||
impl->Deinitialize = WASAPI_Deinitialize;
|
||||
impl->FreeDeviceHandle = WASAPI_FreeDeviceHandle;
|
||||
|
||||
|
12
external/sdl/SDL/src/audio/wasapi/SDL_wasapi.h
vendored
12
external/sdl/SDL/src/audio/wasapi/SDL_wasapi.h
vendored
@ -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
|
||||
@ -41,22 +41,24 @@ struct SDL_PrivateAudioData
|
||||
SDL_bool coinitialized;
|
||||
int framesize;
|
||||
SDL_bool device_lost;
|
||||
SDL_bool device_dead;
|
||||
void *activation_handler;
|
||||
};
|
||||
|
||||
/* win32 and winrt implementations call into these. */
|
||||
// win32 and winrt implementations call into these.
|
||||
int WASAPI_PrepDevice(SDL_AudioDevice *device);
|
||||
void WASAPI_DisconnectDevice(SDL_AudioDevice *device);
|
||||
void WASAPI_DisconnectDevice(SDL_AudioDevice *device); // don't hold the device lock when calling this!
|
||||
|
||||
|
||||
// BE CAREFUL: if you are holding the device lock and proxy to the management thread with wait_until_complete, and grab the lock again, you will deadlock.
|
||||
typedef int (*ManagementThreadTask)(void *userdata);
|
||||
int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, int *wait_until_complete);
|
||||
|
||||
/* These are functions that are implemented differently for Windows vs WinRT. */
|
||||
// These are functions that are implemented differently for Windows vs WinRT.
|
||||
// UNLESS OTHERWISE NOTED THESE ALL HAPPEN ON THE MANAGEMENT THREAD.
|
||||
int WASAPI_PlatformInit(void);
|
||||
void WASAPI_PlatformDeinit(void);
|
||||
void WASAPI_PlatformDeinitializeStart(void);
|
||||
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture);
|
||||
int WASAPI_ActivateDevice(SDL_AudioDevice *device);
|
||||
void WASAPI_PlatformThreadInit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread.
|
||||
@ -68,4 +70,4 @@ void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SDL_wasapi_h_ */
|
||||
#endif // SDL_wasapi_h_
|
||||
|
@ -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
|
||||
@ -30,30 +30,70 @@
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../../core/windows/SDL_immdevice.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
#include <audioclient.h>
|
||||
|
||||
#include "SDL_wasapi.h"
|
||||
|
||||
/* handle to Avrt.dll--Vista and later!--for flagging the callback thread as "Pro Audio" (low latency). */
|
||||
// handle to Avrt.dll--Vista and later!--for flagging the callback thread as "Pro Audio" (low latency).
|
||||
static HMODULE libavrt = NULL;
|
||||
typedef HANDLE(WINAPI *pfnAvSetMmThreadCharacteristicsW)(LPCWSTR, LPDWORD);
|
||||
typedef BOOL(WINAPI *pfnAvRevertMmThreadCharacteristics)(HANDLE);
|
||||
static pfnAvSetMmThreadCharacteristicsW pAvSetMmThreadCharacteristicsW = NULL;
|
||||
static pfnAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL;
|
||||
|
||||
/* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */
|
||||
static SDL_bool immdevice_initialized = SDL_FALSE;
|
||||
|
||||
// Some GUIDs we need to know without linking to libraries that aren't available before Vista.
|
||||
static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
|
||||
|
||||
static int mgmtthrtask_AudioDeviceDisconnected(void *userdata)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
|
||||
SDL_AudioDeviceDisconnected(device);
|
||||
UnrefPhysicalAudioDevice(device); // make sure this lived until the task completes.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void WASAPI_AudioDeviceDisconnected(SDL_AudioDevice *device)
|
||||
{
|
||||
// don't wait on this, IMMDevice's own thread needs to return or everything will deadlock.
|
||||
if (device) {
|
||||
RefPhysicalAudioDevice(device); // make sure this lives until the task completes.
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_AudioDeviceDisconnected, device, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int mgmtthrtask_DefaultAudioDeviceChanged(void *userdata)
|
||||
{
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
|
||||
SDL_DefaultAudioDeviceChanged(device);
|
||||
UnrefPhysicalAudioDevice(device); // make sure this lived until the task completes.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void WASAPI_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device)
|
||||
{
|
||||
// don't wait on this, IMMDevice's own thread needs to return or everything will deadlock.
|
||||
if (new_default_device) {
|
||||
RefPhysicalAudioDevice(new_default_device); // make sure this lives until the task completes.
|
||||
WASAPI_ProxyToManagementThread(mgmtthrtask_DefaultAudioDeviceChanged, new_default_device, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int WASAPI_PlatformInit(void)
|
||||
{
|
||||
if (SDL_IMMDevice_Init() < 0) { // this will call WIN_CoInitialize for us!
|
||||
return -1; /* This is set by SDL_IMMDevice_Init */
|
||||
const SDL_IMMDevice_callbacks callbacks = { WASAPI_AudioDeviceDisconnected, WASAPI_DefaultAudioDeviceChanged };
|
||||
if (FAILED(WIN_CoInitialize())) {
|
||||
return SDL_SetError("CoInitialize() failed");
|
||||
} else if (SDL_IMMDevice_Init(&callbacks) < 0) {
|
||||
return -1; // Error string is set by SDL_IMMDevice_Init
|
||||
}
|
||||
|
||||
libavrt = LoadLibrary(TEXT("avrt.dll")); /* this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now! */
|
||||
immdevice_initialized = SDL_TRUE;
|
||||
|
||||
libavrt = LoadLibrary(TEXT("avrt.dll")); // this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now!
|
||||
if (libavrt) {
|
||||
pAvSetMmThreadCharacteristicsW = (pfnAvSetMmThreadCharacteristicsW)GetProcAddress(libavrt, "AvSetMmThreadCharacteristicsW");
|
||||
pAvRevertMmThreadCharacteristics = (pfnAvRevertMmThreadCharacteristics)GetProcAddress(libavrt, "AvRevertMmThreadCharacteristics");
|
||||
@ -62,6 +102,14 @@ int WASAPI_PlatformInit(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void StopWasapiHotplug(void)
|
||||
{
|
||||
if (immdevice_initialized) {
|
||||
SDL_IMMDevice_Quit();
|
||||
immdevice_initialized = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void WASAPI_PlatformDeinit(void)
|
||||
{
|
||||
if (libavrt) {
|
||||
@ -72,17 +120,24 @@ void WASAPI_PlatformDeinit(void)
|
||||
pAvSetMmThreadCharacteristicsW = NULL;
|
||||
pAvRevertMmThreadCharacteristics = NULL;
|
||||
|
||||
SDL_IMMDevice_Quit(); // This will call WIN_CoUninitialize for us!
|
||||
StopWasapiHotplug();
|
||||
|
||||
WIN_CoUninitialize();
|
||||
}
|
||||
|
||||
void WASAPI_PlatformDeinitializeStart(void)
|
||||
{
|
||||
StopWasapiHotplug();
|
||||
}
|
||||
|
||||
void WASAPI_PlatformThreadInit(SDL_AudioDevice *device)
|
||||
{
|
||||
/* this thread uses COM. */
|
||||
if (SUCCEEDED(WIN_CoInitialize())) { /* can't report errors, hope it worked! */
|
||||
// this thread uses COM.
|
||||
if (SUCCEEDED(WIN_CoInitialize())) { // can't report errors, hope it worked!
|
||||
device->hidden->coinitialized = SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Set this thread to very high "Pro Audio" priority. */
|
||||
// Set this thread to very high "Pro Audio" priority.
|
||||
if (pAvSetMmThreadCharacteristicsW) {
|
||||
DWORD idx = 0;
|
||||
device->hidden->task = pAvSetMmThreadCharacteristicsW(L"Pro Audio", &idx);
|
||||
@ -94,7 +149,7 @@ void WASAPI_PlatformThreadInit(SDL_AudioDevice *device)
|
||||
|
||||
void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device)
|
||||
{
|
||||
/* Set this thread back to normal priority. */
|
||||
// Set this thread back to normal priority.
|
||||
if (device->hidden->task && pAvRevertMmThreadCharacteristics) {
|
||||
pAvRevertMmThreadCharacteristics(device->hidden->task);
|
||||
device->hidden->task = NULL;
|
||||
@ -111,10 +166,10 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device)
|
||||
IMMDevice *immdevice = NULL;
|
||||
if (SDL_IMMDevice_Get(device, &immdevice, device->iscapture) < 0) {
|
||||
device->hidden->client = NULL;
|
||||
return -1; /* This is already set by SDL_IMMDevice_Get */
|
||||
return -1; // This is already set by SDL_IMMDevice_Get
|
||||
}
|
||||
|
||||
/* this is _not_ async in standard win32, yay! */
|
||||
// this is _not_ async in standard win32, yay!
|
||||
HRESULT ret = IMMDevice_Activate(immdevice, &SDL_IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&device->hidden->client);
|
||||
IMMDevice_Release(immdevice);
|
||||
|
||||
@ -124,11 +179,11 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device)
|
||||
}
|
||||
|
||||
SDL_assert(device->hidden->client != NULL);
|
||||
if (WASAPI_PrepDevice(device) == -1) { /* not async, fire it right away. */
|
||||
if (WASAPI_PrepDevice(device) == -1) { // not async, fire it right away.
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0; /* good to go. */
|
||||
return 0; // good to go.
|
||||
}
|
||||
|
||||
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture)
|
||||
@ -138,7 +193,7 @@ void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice
|
||||
|
||||
void WASAPI_PlatformDeleteActivationHandler(void *handler)
|
||||
{
|
||||
/* not asynchronous. */
|
||||
// not asynchronous.
|
||||
SDL_assert(!"This function should have only been called on WinRT.");
|
||||
}
|
||||
|
||||
@ -147,4 +202,4 @@ void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device)
|
||||
SDL_IMMDevice_FreeDeviceHandle(device);
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__) */
|
||||
#endif // SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__)
|
||||
|
@ -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
|
||||
@ -36,7 +36,6 @@
|
||||
|
||||
extern "C" {
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
}
|
||||
|
||||
@ -56,7 +55,7 @@ static Platform::String ^ SDL_PKEY_AudioEngine_DeviceFormat = L"{f19f064d-082c-4
|
||||
|
||||
static SDL_bool FindWinRTAudioDeviceCallback(SDL_AudioDevice *device, void *userdata)
|
||||
{
|
||||
return (SDL_wcscmp((LPCWSTR) device->handle, (LPCWSTR) userdata) == 0) ? SDL_TRUE : SDL_FALSE;
|
||||
return (SDL_wcscmp((LPCWSTR) device->handle, (LPCWSTR) userdata) == 0);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *FindWinRTAudioDevice(LPCWSTR devid)
|
||||
@ -220,7 +219,7 @@ int WASAPI_PlatformInit(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WASAPI_PlatformDeinit(void)
|
||||
static void StopWasapiHotplug(void)
|
||||
{
|
||||
delete playback_device_event_handler;
|
||||
playback_device_event_handler = nullptr;
|
||||
@ -228,6 +227,17 @@ void WASAPI_PlatformDeinit(void)
|
||||
capture_device_event_handler = nullptr;
|
||||
}
|
||||
|
||||
void WASAPI_PlatformDeinit(void)
|
||||
{
|
||||
StopWasapiHotplug();
|
||||
}
|
||||
|
||||
void WASAPI_PlatformDeinitializeStart(void)
|
||||
{
|
||||
StopWasapiHotplug();
|
||||
}
|
||||
|
||||
|
||||
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture)
|
||||
{
|
||||
Platform::String ^ defdevid;
|
||||
|
235
external/sdl/SDL/src/core/SDL_core_unsupported.c
vendored
Normal file
235
external/sdl/SDL/src/core/SDL_core_unsupported.c
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
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
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_VIDEO_DRIVER_X11
|
||||
|
||||
DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __LINUX__
|
||||
|
||||
DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority);
|
||||
int SDL_LinuxSetThreadPriority(Sint64 threadID, int priority)
|
||||
{
|
||||
(void)threadID;
|
||||
(void)priority;
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy);
|
||||
int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy)
|
||||
{
|
||||
(void)threadID;
|
||||
(void)sdlPriority;
|
||||
(void)schedPolicy;
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __GDK__
|
||||
|
||||
DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void);
|
||||
void SDL_GDKSuspendComplete(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(void *outUserHandle); /* XUserHandle *outUserHandle */
|
||||
int SDL_GDKGetDefaultUser(void *outUserHandle)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__))
|
||||
|
||||
DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst);
|
||||
int SDL_RegisterApp(const char *name, Uint32 style, void *hInst)
|
||||
{
|
||||
(void)name;
|
||||
(void)style;
|
||||
(void)hInst;
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(void *callback, void *userdata); /* SDL_WindowsMessageHook callback */
|
||||
void SDL_SetWindowsMessageHook(void *callback, void *userdata)
|
||||
{
|
||||
(void)callback;
|
||||
(void)userdata;
|
||||
SDL_Unsupported();
|
||||
}
|
||||
|
||||
DECLSPEC void SDLCALL SDL_UnregisterApp(void);
|
||||
void SDL_UnregisterApp(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __WINRT__
|
||||
|
||||
/* Returns SDL_WinRT_DeviceFamily enum */
|
||||
DECLSPEC int SDLCALL SDL_WinRTGetDeviceFamily(void);
|
||||
int SDL_WinRTGetDeviceFamily()
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return 0; /* SDL_WINRT_DEVICEFAMILY_UNKNOWN */
|
||||
}
|
||||
|
||||
DECLSPEC const wchar_t *SDLCALL SDL_WinRTGetFSPathUNICODE(int pathType); /* SDL_WinRT_Path pathType */
|
||||
const wchar_t *SDL_WinRTGetFSPathUNICODE(int pathType)
|
||||
{
|
||||
(void)pathType;
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DECLSPEC const char *SDLCALL SDL_WinRTGetFSPathUTF8(int pathType); /* SDL_WinRT_Path pathType */
|
||||
const char *SDL_WinRTGetFSPathUTF8(int pathType)
|
||||
{
|
||||
(void)pathType;
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __ANDROID__
|
||||
|
||||
DECLSPEC void SDLCALL SDL_AndroidBackButton(void);
|
||||
void SDL_AndroidBackButton()
|
||||
{
|
||||
SDL_Unsupported();
|
||||
}
|
||||
|
||||
DECLSPEC void *SDLCALL SDL_AndroidGetActivity(void);
|
||||
void *SDL_AndroidGetActivity()
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DECLSPEC const char *SDLCALL SDL_AndroidGetExternalStoragePath(void);
|
||||
const char* SDL_AndroidGetExternalStoragePath()
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(Uint32 *state);
|
||||
int SDL_AndroidGetExternalStorageState(Uint32 *state)
|
||||
{
|
||||
(void)state;
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
DECLSPEC const char *SDLCALL SDL_AndroidGetInternalStoragePath(void);
|
||||
const char *SDL_AndroidGetInternalStoragePath()
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DECLSPEC void *SDLCALL SDL_AndroidGetJNIEnv(void);
|
||||
void *SDL_AndroidGetJNIEnv()
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission);
|
||||
SDL_bool SDL_AndroidRequestPermission(const char *permission)
|
||||
{
|
||||
(void)permission;
|
||||
SDL_Unsupported();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_AndroidSendMessage(Uint32 command, int param);
|
||||
int SDL_AndroidSendMessage(Uint32 command, int param)
|
||||
{
|
||||
(void)command;
|
||||
(void)param;
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset);
|
||||
int SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset)
|
||||
{
|
||||
(void)message;
|
||||
(void)duration;
|
||||
(void)gravity;
|
||||
(void)xoffset;
|
||||
(void)yoffset;
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void);
|
||||
int SDL_GetAndroidSDKVersion()
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void);
|
||||
SDL_bool SDL_IsAndroidTV()
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void);
|
||||
SDL_bool SDL_IsChromebook()
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void);
|
||||
SDL_bool SDL_IsDeXMode(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
DECLSPEC Sint32 SDLCALL JNI_OnLoad(void *vm, void *reserved);
|
||||
Sint32 JNI_OnLoad(void *vm, void *reserved)
|
||||
{
|
||||
(void)vm;
|
||||
(void)reserved;
|
||||
SDL_Unsupported();
|
||||
return -1; /* JNI_ERR */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
|
||||
char *SDL_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
(void)folder;
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
11
external/sdl/SDL/src/core/SDL_runapp.c
vendored
11
external/sdl/SDL/src/core/SDL_runapp.c
vendored
@ -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
|
||||
@ -27,15 +27,14 @@
|
||||
DECLSPEC int
|
||||
SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved)
|
||||
{
|
||||
char empty[1] = {0};
|
||||
char* argvdummy[2] = { empty, NULL };
|
||||
|
||||
(void)reserved;
|
||||
|
||||
if(argv == NULL)
|
||||
if(!argv)
|
||||
{
|
||||
argc = 0;
|
||||
/* make sure argv isn't NULL, in case some user code doesn't like that */
|
||||
static char dummyargv0[] = { 'S', 'D', 'L', '_', 'a', 'p', 'p', '\0' };
|
||||
static char* argvdummy[2] = { dummyargv0, NULL };
|
||||
argc = 1;
|
||||
argv = argvdummy;
|
||||
}
|
||||
|
||||
|
72
external/sdl/SDL/src/core/android/SDL_android.c
vendored
72
external/sdl/SDL/src/core/android/SDL_android.c
vendored
@ -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
|
||||
@ -434,12 +434,12 @@ JNIEnv *Android_JNI_GetEnv(void)
|
||||
{
|
||||
/* Get JNIEnv from the Thread local storage */
|
||||
JNIEnv *env = pthread_getspecific(mThreadKey);
|
||||
if (env == NULL) {
|
||||
if (!env) {
|
||||
/* If it fails, try to attach ! (e.g the thread isn't created with SDL_CreateThread() */
|
||||
int status;
|
||||
|
||||
/* There should be a JVM */
|
||||
if (mJavaVM == NULL) {
|
||||
if (!mJavaVM) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed, there is no JavaVM");
|
||||
return NULL;
|
||||
}
|
||||
@ -468,7 +468,7 @@ int Android_JNI_SetupThread(void)
|
||||
int status;
|
||||
|
||||
/* There should be a JVM */
|
||||
if (mJavaVM == NULL) {
|
||||
if (!mJavaVM) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed, there is no JavaVM");
|
||||
return 0;
|
||||
}
|
||||
@ -494,7 +494,7 @@ static void Android_JNI_ThreadDestroyed(void *value)
|
||||
{
|
||||
/* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
|
||||
JNIEnv *env = (JNIEnv *)value;
|
||||
if (env != NULL) {
|
||||
if (env) {
|
||||
(*mJavaVM)->DetachCurrentThread(mJavaVM);
|
||||
Android_JNI_SetEnv(NULL);
|
||||
}
|
||||
@ -520,7 +520,7 @@ static void Android_JNI_CreateKey_once(void)
|
||||
static void register_methods(JNIEnv *env, const char *classname, JNINativeMethod *methods, int nb)
|
||||
{
|
||||
jclass clazz = (*env)->FindClass(env, classname);
|
||||
if (clazz == NULL || (*env)->RegisterNatives(env, clazz, methods, nb) < 0) {
|
||||
if (!clazz || (*env)->RegisterNatives(env, clazz, methods, nb) < 0) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed to register methods of %s", classname);
|
||||
return;
|
||||
}
|
||||
@ -573,6 +573,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeSetupJNI()");
|
||||
|
||||
/* Start with a clean slate */
|
||||
SDL_ClearError();
|
||||
|
||||
/*
|
||||
* Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
|
||||
* Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
|
||||
@ -582,28 +585,28 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
|
||||
/* Save JNIEnv of SDLActivity */
|
||||
Android_JNI_SetEnv(env);
|
||||
|
||||
if (mJavaVM == NULL) {
|
||||
if (!mJavaVM) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to found a JavaVM");
|
||||
}
|
||||
|
||||
/* Use a mutex to prevent concurrency issues between Java Activity and Native thread code, when using 'Android_Window'.
|
||||
* (Eg. Java sending Touch events, while native code is destroying the main SDL_Window. )
|
||||
*/
|
||||
if (Android_ActivityMutex == NULL) {
|
||||
if (!Android_ActivityMutex) {
|
||||
Android_ActivityMutex = SDL_CreateMutex(); /* Could this be created twice if onCreate() is called a second time ? */
|
||||
}
|
||||
|
||||
if (Android_ActivityMutex == NULL) {
|
||||
if (!Android_ActivityMutex) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ActivityMutex mutex");
|
||||
}
|
||||
|
||||
Android_PauseSem = SDL_CreateSemaphore(0);
|
||||
if (Android_PauseSem == NULL) {
|
||||
if (!Android_PauseSem) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_PauseSem semaphore");
|
||||
}
|
||||
|
||||
Android_ResumeSem = SDL_CreateSemaphore(0);
|
||||
if (Android_ResumeSem == NULL) {
|
||||
if (!Android_ResumeSem) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ResumeSem semaphore");
|
||||
}
|
||||
|
||||
@ -878,7 +881,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
|
||||
jstring filename)
|
||||
{
|
||||
const char *path = (*env)->GetStringUTFChars(env, filename, NULL);
|
||||
SDL_SendDropFile(NULL, path);
|
||||
SDL_SendDropFile(NULL, NULL, path);
|
||||
(*env)->ReleaseStringUTFChars(env, filename, path);
|
||||
SDL_SendDropComplete(NULL);
|
||||
}
|
||||
@ -1006,24 +1009,28 @@ JNIEXPORT void JNICALL
|
||||
SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture,
|
||||
jstring name, jint device_id)
|
||||
{
|
||||
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
|
||||
if (SDL_GetCurrentAudioDriver() != NULL) {
|
||||
void *handle = (void *)((size_t)device_id);
|
||||
if (!SDL_FindPhysicalAudioDeviceByHandle(handle)) {
|
||||
const char *utf8name = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
SDL_AddAudioDevice(is_capture ? SDL_TRUE : SDL_FALSE, SDL_strdup(utf8name), NULL, handle);
|
||||
SDL_AddAudioDevice(is_capture, SDL_strdup(utf8name), NULL, handle);
|
||||
(*env)->ReleaseStringUTFChars(env, name, utf8name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture,
|
||||
jint device_id)
|
||||
{
|
||||
#if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES
|
||||
if (SDL_GetCurrentAudioDriver() != NULL) {
|
||||
SDL_Log("Removing device with handle %d, capture %d", device_id, is_capture);
|
||||
SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle((void *)((size_t)device_id)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Paddown */
|
||||
@ -1068,7 +1075,7 @@ JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
||||
const char *name = (*env)->GetStringUTFChars(env, device_name, NULL);
|
||||
const char *desc = (*env)->GetStringUTFChars(env, device_desc, NULL);
|
||||
|
||||
retval = Android_AddJoystick(device_id, name, desc, vendor_id, product_id, is_accelerometer ? SDL_TRUE : SDL_FALSE, button_mask, naxes, axis_mask, nhats);
|
||||
retval = Android_AddJoystick(device_id, name, desc, vendor_id, product_id, is_accelerometer, button_mask, naxes, axis_mask, nhats);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, device_name, name);
|
||||
(*env)->ReleaseStringUTFChars(env, device_desc, desc);
|
||||
@ -1610,7 +1617,7 @@ int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device)
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output");
|
||||
result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midAudioOpen, spec->freq, audioformat, spec->channels, device->sample_frames, device_id);
|
||||
}
|
||||
if (result == NULL) {
|
||||
if (!result) {
|
||||
/* Error during audio initialization, error printed from Java */
|
||||
return SDL_SetError("Java-side initialization failed");
|
||||
}
|
||||
@ -1671,7 +1678,7 @@ int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device)
|
||||
return SDL_SetError("Unexpected audio format from Java: %d\n", audioformat);
|
||||
}
|
||||
|
||||
if (jbufobj == NULL) {
|
||||
if (!jbufobj) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer");
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
@ -1942,7 +1949,7 @@ static void Internal_Android_Create_AssetManager()
|
||||
javaAssetManagerRef = (*env)->NewGlobalRef(env, javaAssetManager);
|
||||
asset_manager = AAssetManager_fromJava(env, javaAssetManagerRef);
|
||||
|
||||
if (asset_manager == NULL) {
|
||||
if (!asset_manager) {
|
||||
(*env)->DeleteGlobalRef(env, javaAssetManagerRef);
|
||||
Android_JNI_ExceptionOccurred(SDL_TRUE);
|
||||
}
|
||||
@ -1966,17 +1973,17 @@ int Android_JNI_FileOpen(SDL_RWops *ctx,
|
||||
AAsset *asset = NULL;
|
||||
ctx->hidden.androidio.asset = NULL;
|
||||
|
||||
if (asset_manager == NULL) {
|
||||
if (!asset_manager) {
|
||||
Internal_Android_Create_AssetManager();
|
||||
}
|
||||
|
||||
if (asset_manager == NULL) {
|
||||
return -1;
|
||||
if (!asset_manager) {
|
||||
return SDL_SetError("Couldn't create asset manager");
|
||||
}
|
||||
|
||||
asset = AAssetManager_open(asset_manager, fileName, AASSET_MODE_UNKNOWN);
|
||||
if (asset == NULL) {
|
||||
return -1;
|
||||
if (!asset) {
|
||||
return SDL_SetError("Couldn't open asset '%s'", fileName);
|
||||
}
|
||||
|
||||
ctx->hidden.androidio.asset = (void *)asset;
|
||||
@ -2047,14 +2054,13 @@ char *Android_JNI_GetClipboardText(void)
|
||||
(*env)->DeleteLocalRef(env, string);
|
||||
}
|
||||
|
||||
return (text == NULL) ? SDL_strdup("") : text;
|
||||
return (!text) ? SDL_strdup("") : text;
|
||||
}
|
||||
|
||||
SDL_bool Android_JNI_HasClipboardText(void)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
jboolean retval = (*env)->CallStaticBooleanMethod(env, mActivityClass, midClipboardHasText);
|
||||
return (retval == JNI_TRUE) ? SDL_TRUE : SDL_FALSE;
|
||||
return (*env)->CallStaticBooleanMethod(env, mActivityClass, midClipboardHasText);
|
||||
}
|
||||
|
||||
/* returns 0 on success or -1 on error (others undefined then)
|
||||
@ -2233,7 +2239,7 @@ int Android_JNI_SuspendScreenSaver(SDL_bool suspend)
|
||||
return Android_JNI_SendMessage(COMMAND_SET_KEEP_SCREEN_ON, (suspend == SDL_FALSE) ? 0 : 1);
|
||||
}
|
||||
|
||||
void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
|
||||
void Android_JNI_ShowScreenKeyboard(SDL_Rect *inputRect)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
(*env)->CallStaticBooleanMethod(env, mActivityClass, midShowTextInput,
|
||||
@ -2243,7 +2249,7 @@ void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
|
||||
inputRect->h);
|
||||
}
|
||||
|
||||
void Android_JNI_HideTextInput(void)
|
||||
void Android_JNI_HideScreenKeyboard(void)
|
||||
{
|
||||
/* has to match Activity constant */
|
||||
const int COMMAND_TEXTEDIT_HIDE = 3;
|
||||
@ -2368,7 +2374,7 @@ void *SDL_AndroidGetActivity(void)
|
||||
/* See SDL_system.h for caveats on using this function. */
|
||||
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
if (env == NULL) {
|
||||
if (!env) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -2422,7 +2428,7 @@ const char *SDL_AndroidGetInternalStoragePath(void)
|
||||
{
|
||||
static char *s_AndroidInternalFilesPath = NULL;
|
||||
|
||||
if (s_AndroidInternalFilesPath == NULL) {
|
||||
if (!s_AndroidInternalFilesPath) {
|
||||
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
|
||||
jmethodID mid;
|
||||
jobject context;
|
||||
@ -2521,7 +2527,7 @@ const char *SDL_AndroidGetExternalStoragePath(void)
|
||||
{
|
||||
static char *s_AndroidExternalFilesPath = NULL;
|
||||
|
||||
if (s_AndroidExternalFilesPath == NULL) {
|
||||
if (!s_AndroidExternalFilesPath) {
|
||||
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
|
||||
jmethodID mid;
|
||||
jobject context;
|
||||
@ -2677,16 +2683,16 @@ int Android_JNI_GetLocale(char *buf, size_t buflen)
|
||||
/* Need to re-create the asset manager if locale has changed (SDL_EVENT_LOCALE_CHANGED) */
|
||||
Internal_Android_Destroy_AssetManager();
|
||||
|
||||
if (asset_manager == NULL) {
|
||||
if (!asset_manager) {
|
||||
Internal_Android_Create_AssetManager();
|
||||
}
|
||||
|
||||
if (asset_manager == NULL) {
|
||||
if (!asset_manager) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfg = AConfiguration_new();
|
||||
if (cfg == NULL) {
|
||||
if (!cfg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -32,6 +32,9 @@ extern "C" {
|
||||
|
||||
#include "../../audio/SDL_sysaudio.h"
|
||||
|
||||
// this appears to be broken right now (on Android, not SDL, I think...?).
|
||||
#define ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES 0
|
||||
|
||||
/* Interface from the SDL library into the Android Java activity */
|
||||
extern void Android_JNI_SetActivityTitle(const char *title);
|
||||
extern void Android_JNI_SetWindowStyle(SDL_bool fullscreen);
|
||||
@ -40,8 +43,8 @@ extern void Android_JNI_MinizeWindow(void);
|
||||
extern SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss(void);
|
||||
|
||||
extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);
|
||||
extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect);
|
||||
extern void Android_JNI_HideTextInput(void);
|
||||
extern void Android_JNI_ShowScreenKeyboard(SDL_Rect *inputRect);
|
||||
extern void Android_JNI_HideScreenKeyboard(void);
|
||||
extern SDL_bool Android_JNI_IsScreenKeyboardShown(void);
|
||||
extern ANativeWindow *Android_JNI_GetNativeWindow(void);
|
||||
|
||||
|
@ -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
|
||||
@ -87,7 +87,7 @@ static void kbd_cleanup(void)
|
||||
{
|
||||
struct mouse_info mData;
|
||||
SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state;
|
||||
if (kbd == NULL) {
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_state = NULL;
|
||||
@ -178,7 +178,7 @@ static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
int tabidx;
|
||||
|
||||
if (kbd_cleanup_state != NULL) {
|
||||
if (kbd_cleanup_state) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_state = kbd;
|
||||
@ -230,7 +230,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void)
|
||||
SDL_zero(mData);
|
||||
mData.operation = MOUSE_HIDE;
|
||||
kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(SDL_EVDEV_keyboard_state));
|
||||
if (kbd == NULL) {
|
||||
if (!kbd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -296,7 +296,7 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
|
||||
{
|
||||
struct mouse_info mData;
|
||||
|
||||
if (kbd == NULL) {
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
SDL_zero(mData);
|
||||
@ -320,6 +320,18 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
|
||||
SDL_free(kbd);
|
||||
}
|
||||
|
||||
void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted)
|
||||
{
|
||||
}
|
||||
|
||||
void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data)
|
||||
{
|
||||
}
|
||||
|
||||
void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper Functions.
|
||||
*/
|
||||
@ -474,7 +486,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode,
|
||||
unsigned int final_key_state;
|
||||
unsigned int map_from_key_sym;
|
||||
|
||||
if (kbd == NULL) {
|
||||
if (!kbd) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
2
external/sdl/SDL/src/core/gdk/SDL_gdk.cpp
vendored
2
external/sdl/SDL/src/core/gdk/SDL_gdk.cpp
vendored
@ -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
|
||||
|
2
external/sdl/SDL/src/core/gdk/SDL_gdk.h
vendored
2
external/sdl/SDL/src/core/gdk/SDL_gdk.h
vendored
@ -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
|
||||
|
2
external/sdl/SDL/src/core/haiku/SDL_BApp.h
vendored
2
external/sdl/SDL/src/core/haiku/SDL_BApp.h
vendored
@ -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
|
||||
|
10
external/sdl/SDL/src/core/haiku/SDL_BeApp.cc
vendored
10
external/sdl/SDL/src/core/haiku/SDL_BeApp.cc
vendored
@ -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
|
||||
@ -69,7 +69,7 @@ public:
|
||||
entry_ref entryRef;
|
||||
for (int32 i = 0; message->FindRef("refs", i, &entryRef) == B_OK; i++) {
|
||||
BPath referencePath = BPath(&entryRef);
|
||||
SDL_SendDropFile(NULL, referencePath.Path());
|
||||
SDL_SendDropFile(NULL, NULL, referencePath.Path());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -108,13 +108,13 @@ static int StartBeLooper()
|
||||
{
|
||||
if (!be_app) {
|
||||
SDL_AppThread = SDL_CreateThreadInternal(StartBeApp, "SDLApplication", 0, NULL);
|
||||
if (SDL_AppThread == NULL) {
|
||||
if (!SDL_AppThread) {
|
||||
return SDL_SetError("Couldn't create BApplication thread");
|
||||
}
|
||||
|
||||
do {
|
||||
SDL_Delay(10);
|
||||
} while ((be_app == NULL) || be_app->IsLaunching());
|
||||
} while ((!be_app) || be_app->IsLaunching());
|
||||
}
|
||||
|
||||
/* Change working directory to that of executable */
|
||||
@ -167,7 +167,7 @@ void SDL_QuitBeApp(void)
|
||||
SDL_Looper->Lock();
|
||||
SDL_Looper->Quit();
|
||||
SDL_Looper = NULL;
|
||||
if (SDL_AppThread != NULL) {
|
||||
if (SDL_AppThread) {
|
||||
if (be_app != NULL) { /* Not tested */
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
|
2
external/sdl/SDL/src/core/haiku/SDL_BeApp.h
vendored
2
external/sdl/SDL/src/core/haiku/SDL_BeApp.h
vendored
@ -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
|
||||
|
37
external/sdl/SDL/src/core/linux/SDL_dbus.c
vendored
37
external/sdl/SDL/src/core/linux/SDL_dbus.c
vendored
@ -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
|
||||
@ -96,7 +96,7 @@ static int LoadDBUSSyms(void)
|
||||
|
||||
static void UnloadDBUSLibrary(void)
|
||||
{
|
||||
if (dbus_handle != NULL) {
|
||||
if (dbus_handle) {
|
||||
SDL_UnloadObject(dbus_handle);
|
||||
dbus_handle = NULL;
|
||||
}
|
||||
@ -105,9 +105,9 @@ static void UnloadDBUSLibrary(void)
|
||||
static int LoadDBUSLibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (dbus_handle == NULL) {
|
||||
if (!dbus_handle) {
|
||||
dbus_handle = SDL_LoadObject(dbus_library);
|
||||
if (dbus_handle == NULL) {
|
||||
if (!dbus_handle) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
} else {
|
||||
@ -183,14 +183,13 @@ void SDL_DBus_Quit(void)
|
||||
dbus.connection_close(dbus.session_conn);
|
||||
dbus.connection_unref(dbus.session_conn);
|
||||
}
|
||||
/* Don't do this - bug 3950
|
||||
dbus_shutdown() is a debug feature which closes all global resources in the dbus library. Calling this should be done by the app, not a library, because if there are multiple users of dbus in the process then SDL could shut it down even though another part is using it.
|
||||
*/
|
||||
#if 0
|
||||
if (dbus.shutdown) {
|
||||
dbus.shutdown();
|
||||
|
||||
if (SDL_GetHintBoolean(SDL_HINT_SHUTDOWN_DBUS_ON_QUIT, SDL_FALSE)) {
|
||||
if (dbus.shutdown) {
|
||||
dbus.shutdown();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SDL_zero(dbus);
|
||||
UnloadDBUSLibrary();
|
||||
SDL_free(inhibit_handle);
|
||||
@ -199,7 +198,7 @@ void SDL_DBus_Quit(void)
|
||||
|
||||
SDL_DBusContext *SDL_DBus_GetContext(void)
|
||||
{
|
||||
if (dbus_handle == NULL || !dbus.session_conn) {
|
||||
if (!dbus_handle || !dbus.session_conn) {
|
||||
SDL_DBus_Init();
|
||||
}
|
||||
|
||||
@ -360,7 +359,7 @@ SDL_bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *
|
||||
|
||||
void SDL_DBus_ScreensaverTickle(void)
|
||||
{
|
||||
if (screensaver_cookie == 0 && inhibit_handle == NULL) { /* no need to tickle if we're inhibiting. */
|
||||
if (screensaver_cookie == 0 && !inhibit_handle) { /* no need to tickle if we're inhibiting. */
|
||||
/* org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. */
|
||||
SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
|
||||
SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
|
||||
@ -428,7 +427,7 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
|
||||
{
|
||||
const char *default_inhibit_reason = "Playing a game";
|
||||
|
||||
if ((inhibit && (screensaver_cookie != 0 || inhibit_handle != NULL)) || (!inhibit && (screensaver_cookie == 0 && inhibit_handle == NULL))) {
|
||||
if ((inhibit && (screensaver_cookie != 0 || inhibit_handle)) || (!inhibit && (screensaver_cookie == 0 && !inhibit_handle))) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
@ -452,12 +451,12 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
|
||||
const char *key = "reason";
|
||||
const char *reply = NULL;
|
||||
const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME);
|
||||
if (reason == NULL || !reason[0]) {
|
||||
if (!reason || !reason[0]) {
|
||||
reason = default_inhibit_reason;
|
||||
}
|
||||
|
||||
msg = dbus.message_new_method_call(bus_name, path, interface, "Inhibit");
|
||||
if (msg == NULL) {
|
||||
if (!msg) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
@ -496,10 +495,10 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
|
||||
if (inhibit) {
|
||||
const char *app = SDL_GetHint(SDL_HINT_APP_NAME);
|
||||
const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME);
|
||||
if (app == NULL || !app[0]) {
|
||||
if (!app || !app[0]) {
|
||||
app = "My SDL application";
|
||||
}
|
||||
if (reason == NULL || !reason[0]) {
|
||||
if (!reason || !reason[0]) {
|
||||
reason = default_inhibit_reason;
|
||||
}
|
||||
|
||||
@ -508,7 +507,7 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
|
||||
DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE;
|
||||
return (screensaver_cookie != 0);
|
||||
} else {
|
||||
if (!SDL_DBus_CallVoidMethod(bus_name, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
|
||||
return SDL_FALSE;
|
||||
|
2
external/sdl/SDL/src/core/linux/SDL_dbus.h
vendored
2
external/sdl/SDL/src/core/linux/SDL_dbus.h
vendored
@ -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
|
||||
|
90
external/sdl/SDL/src/core/linux/SDL_evdev.c
vendored
90
external/sdl/SDL/src/core/linux/SDL_evdev.c
vendored
@ -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
|
||||
@ -73,6 +73,7 @@ typedef struct SDL_evdevlist_item
|
||||
{
|
||||
char *path;
|
||||
int fd;
|
||||
int udev_class;
|
||||
|
||||
/* TODO: use this for every device, not just touchscreen */
|
||||
SDL_bool out_of_sync;
|
||||
@ -155,12 +156,21 @@ static int SDL_EVDEV_SetRelativeMouseMode(SDL_bool enabled)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SDL_EVDEV_UpdateKeyboardMute(void)
|
||||
{
|
||||
if (SDL_EVDEV_GetDeviceCount(SDL_UDEV_DEVICE_KEYBOARD) > 0) {
|
||||
SDL_EVDEV_kbd_set_muted(_this->kbd, SDL_TRUE);
|
||||
} else {
|
||||
SDL_EVDEV_kbd_set_muted(_this->kbd, SDL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_EVDEV_Init(void)
|
||||
{
|
||||
if (_this == NULL) {
|
||||
if (!_this) {
|
||||
_this = (SDL_EVDEV_PrivateData *)SDL_calloc(1, sizeof(*_this));
|
||||
if (_this == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!_this) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
@ -208,6 +218,8 @@ int SDL_EVDEV_Init(void)
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
_this->kbd = SDL_EVDEV_kbd_init();
|
||||
|
||||
SDL_EVDEV_UpdateKeyboardMute();
|
||||
}
|
||||
|
||||
SDL_GetMouse()->SetRelativeMouseMode = SDL_EVDEV_SetRelativeMouseMode;
|
||||
@ -219,7 +231,7 @@ int SDL_EVDEV_Init(void)
|
||||
|
||||
void SDL_EVDEV_Quit(void)
|
||||
{
|
||||
if (_this == NULL) {
|
||||
if (!_this) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -231,13 +243,13 @@ void SDL_EVDEV_Quit(void)
|
||||
SDL_UDEV_Quit();
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
SDL_EVDEV_kbd_quit(_this->kbd);
|
||||
|
||||
/* Remove existing devices */
|
||||
while (_this->first != NULL) {
|
||||
while (_this->first) {
|
||||
SDL_EVDEV_device_removed(_this->first->path);
|
||||
}
|
||||
|
||||
SDL_EVDEV_kbd_quit(_this->kbd);
|
||||
|
||||
SDL_assert(_this->first == NULL);
|
||||
SDL_assert(_this->last == NULL);
|
||||
SDL_assert(_this->num_devices == 0);
|
||||
@ -251,7 +263,7 @@ void SDL_EVDEV_Quit(void)
|
||||
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
|
||||
const char *dev_path)
|
||||
{
|
||||
if (dev_path == NULL) {
|
||||
if (!dev_path) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -276,6 +288,27 @@ static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_cl
|
||||
}
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
void SDL_EVDEV_SetVTSwitchCallbacks(void (*release_callback)(void*), void *release_callback_data,
|
||||
void (*acquire_callback)(void*), void *acquire_callback_data)
|
||||
{
|
||||
SDL_EVDEV_kbd_set_vt_switch_callbacks(_this->kbd,
|
||||
release_callback, release_callback_data,
|
||||
acquire_callback, acquire_callback_data);
|
||||
}
|
||||
|
||||
int SDL_EVDEV_GetDeviceCount(int device_class)
|
||||
{
|
||||
SDL_evdevlist_item *item;
|
||||
int count = 0;
|
||||
|
||||
for (item = _this->first; item; item = item->next) {
|
||||
if ((item->udev_class & device_class) == device_class) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void SDL_EVDEV_Poll(void)
|
||||
{
|
||||
struct input_event events[32];
|
||||
@ -294,9 +327,11 @@ void SDL_EVDEV_Poll(void)
|
||||
SDL_UDEV_Poll();
|
||||
#endif
|
||||
|
||||
SDL_EVDEV_kbd_update(_this->kbd);
|
||||
|
||||
mouse = SDL_GetMouse();
|
||||
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
for (item = _this->first; item; item = item->next) {
|
||||
while ((len = read(item->fd, events, sizeof(events))) > 0) {
|
||||
len /= sizeof(events[0]);
|
||||
for (i = 0; i < len; ++i) {
|
||||
@ -608,8 +643,8 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class)
|
||||
}
|
||||
|
||||
item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
|
||||
if (item->touchscreen_data == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!item->touchscreen_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name);
|
||||
@ -619,9 +654,9 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class)
|
||||
}
|
||||
|
||||
item->touchscreen_data->name = SDL_strdup(name);
|
||||
if (item->touchscreen_data->name == NULL) {
|
||||
if (!item->touchscreen_data->name) {
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
||||
@ -674,10 +709,10 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class)
|
||||
item->touchscreen_data->slots = SDL_calloc(
|
||||
item->touchscreen_data->max_slots,
|
||||
sizeof(*item->touchscreen_data->slots));
|
||||
if (item->touchscreen_data->slots == NULL) {
|
||||
if (!item->touchscreen_data->slots) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < item->touchscreen_data->max_slots; i++) {
|
||||
@ -735,7 +770,7 @@ static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
||||
sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
|
||||
|
||||
mt_req_code = SDL_calloc(1, mt_req_size);
|
||||
if (mt_req_code == NULL) {
|
||||
if (!mt_req_code) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -840,15 +875,15 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
||||
unsigned long relbit[NBITS(REL_MAX)] = { 0 };
|
||||
|
||||
/* Check to make sure it's not already in list. */
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
for (item = _this->first; item; item = item->next) {
|
||||
if (SDL_strcmp(dev_path, item->path) == 0) {
|
||||
return -1; /* already have this one */
|
||||
}
|
||||
}
|
||||
|
||||
item = (SDL_evdevlist_item *)SDL_calloc(1, sizeof(SDL_evdevlist_item));
|
||||
if (item == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!item) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
@ -858,12 +893,14 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
||||
}
|
||||
|
||||
item->path = SDL_strdup(dev_path);
|
||||
if (item->path == NULL) {
|
||||
if (!item->path) {
|
||||
close(item->fd);
|
||||
SDL_free(item);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
item->udev_class = udev_class;
|
||||
|
||||
if (ioctl(item->fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) {
|
||||
item->relative_mouse = test_bit(REL_X, relbit) && test_bit(REL_Y, relbit);
|
||||
item->high_res_wheel = test_bit(REL_WHEEL_HI_RES, relbit);
|
||||
@ -891,7 +928,7 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->last == NULL) {
|
||||
if (!_this->last) {
|
||||
_this->first = _this->last = item;
|
||||
} else {
|
||||
_this->last->next = item;
|
||||
@ -900,6 +937,8 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
||||
|
||||
SDL_EVDEV_sync_device(item);
|
||||
|
||||
SDL_EVDEV_UpdateKeyboardMute();
|
||||
|
||||
return _this->num_devices++;
|
||||
}
|
||||
|
||||
@ -908,10 +947,10 @@ static int SDL_EVDEV_device_removed(const char *dev_path)
|
||||
SDL_evdevlist_item *item;
|
||||
SDL_evdevlist_item *prev = NULL;
|
||||
|
||||
for (item = _this->first; item != NULL; item = item->next) {
|
||||
for (item = _this->first; item; item = item->next) {
|
||||
/* found it, remove it. */
|
||||
if (SDL_strcmp(dev_path, item->path) == 0) {
|
||||
if (prev != NULL) {
|
||||
if (prev) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
SDL_assert(_this->first == item);
|
||||
@ -926,6 +965,7 @@ static int SDL_EVDEV_device_removed(const char *dev_path)
|
||||
close(item->fd);
|
||||
SDL_free(item->path);
|
||||
SDL_free(item);
|
||||
SDL_EVDEV_UpdateKeyboardMute();
|
||||
_this->num_devices--;
|
||||
return 0;
|
||||
}
|
||||
|
5
external/sdl/SDL/src/core/linux/SDL_evdev.h
vendored
5
external/sdl/SDL/src/core/linux/SDL_evdev.h
vendored
@ -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
|
||||
@ -30,6 +30,9 @@ struct input_event;
|
||||
|
||||
extern int SDL_EVDEV_Init(void);
|
||||
extern void SDL_EVDEV_Quit(void);
|
||||
extern void SDL_EVDEV_SetVTSwitchCallbacks(void (*release_callback)(void*), void *release_callback_data,
|
||||
void (*acquire_callback)(void*), void *acquire_callback_data);
|
||||
extern int SDL_EVDEV_GetDeviceCount(int device_class);
|
||||
extern void SDL_EVDEV_Poll(void);
|
||||
extern Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event);
|
||||
|
||||
|
@ -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>
|
||||
Copyright (C) 2020 Collabora Ltd.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
|
@ -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>
|
||||
Copyright (C) 2020 Collabora Ltd.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
@ -53,6 +53,7 @@ typedef enum
|
||||
SDL_UDEV_DEVICE_ACCELEROMETER = 0x0020,
|
||||
SDL_UDEV_DEVICE_TOUCHPAD = 0x0040,
|
||||
SDL_UDEV_DEVICE_HAS_KEYS = 0x0080,
|
||||
SDL_UDEV_DEVICE_VIDEO_CAPTURE = 0x0100,
|
||||
} SDL_UDEV_deviceclass;
|
||||
|
||||
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user