mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 15:14:35 +00:00
update sdl to 2.26.5
This commit is contained in:
parent
0d981b62cf
commit
0e44e165bd
1260 changed files with 290370 additions and 124892 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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"
|
||||
|
||||
#if defined(__WIN32__)
|
||||
#if defined(__WIN32__) || defined(__GDK__)
|
||||
#include "core/windows/SDL_windows.h"
|
||||
#elif defined(__OS2__)
|
||||
#include <stdlib.h> /* _exit() */
|
||||
|
|
@ -89,7 +89,7 @@ SDL_COMPILE_TIME_ASSERT(SDL_PATCHLEVEL_max, SDL_PATCHLEVEL <= 99);
|
|||
extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
|
||||
SDL_NORETURN void SDL_ExitProcess(int exitcode)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
#if defined(__WIN32__) || defined(__GDK__)
|
||||
/* "if you do not know the state of all threads in your process, it is
|
||||
better to call TerminateProcess than ExitProcess"
|
||||
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */
|
||||
|
|
@ -124,17 +124,19 @@ static Uint8 SDL_SubsystemRefCount[ 32 ];
|
|||
static void
|
||||
SDL_PrivateSubsystemRefCountIncr(Uint32 subsystem)
|
||||
{
|
||||
int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
|
||||
++SDL_SubsystemRefCount[subsystem_index];
|
||||
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255));
|
||||
if (subsystem_index >= 0) {
|
||||
++SDL_SubsystemRefCount[subsystem_index];
|
||||
}
|
||||
}
|
||||
|
||||
/* Private helper to decrement a subsystem's ref counter. */
|
||||
static void
|
||||
SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem)
|
||||
{
|
||||
int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
if (SDL_SubsystemRefCount[subsystem_index] > 0) {
|
||||
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] > 0)) {
|
||||
--SDL_SubsystemRefCount[subsystem_index];
|
||||
}
|
||||
}
|
||||
|
|
@ -143,23 +145,23 @@ SDL_PrivateSubsystemRefCountDecr(Uint32 subsystem)
|
|||
static SDL_bool
|
||||
SDL_PrivateShouldInitSubsystem(Uint32 subsystem)
|
||||
{
|
||||
int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
SDL_assert(SDL_SubsystemRefCount[subsystem_index] < 255);
|
||||
return (SDL_SubsystemRefCount[subsystem_index] == 0) ? SDL_TRUE : SDL_FALSE;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Private helper to check if a system needs to be quit. */
|
||||
static SDL_bool
|
||||
SDL_PrivateShouldQuitSubsystem(Uint32 subsystem) {
|
||||
int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
if (SDL_SubsystemRefCount[subsystem_index] == 0) {
|
||||
return SDL_FALSE;
|
||||
const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem);
|
||||
if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* If we're in SDL_Quit, we shut down every subsystem, even if refcount
|
||||
* isn't zero.
|
||||
*/
|
||||
return (SDL_SubsystemRefCount[subsystem_index] == 1 || SDL_bInMainQuit) ? SDL_TRUE : SDL_FALSE;
|
||||
return (((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 1)) || SDL_bInMainQuit) ? SDL_TRUE : SDL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -407,6 +409,9 @@ SDL_QuitSubSystem(Uint32 flags)
|
|||
|
||||
#if !SDL_AUDIO_DISABLED
|
||||
if ((flags & SDL_INIT_AUDIO)) {
|
||||
/* audio implies events */
|
||||
flags |= SDL_INIT_EVENTS;
|
||||
|
||||
if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_AUDIO)) {
|
||||
SDL_AudioQuit();
|
||||
}
|
||||
|
|
@ -505,6 +510,8 @@ SDL_Quit(void)
|
|||
*/
|
||||
SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
|
||||
|
||||
SDL_TLSCleanup();
|
||||
|
||||
SDL_bInMainQuit = SDL_FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -512,7 +519,25 @@ SDL_Quit(void)
|
|||
void
|
||||
SDL_GetVersion(SDL_version * ver)
|
||||
{
|
||||
static SDL_bool check_hint = SDL_TRUE;
|
||||
static SDL_bool legacy_version = SDL_FALSE;
|
||||
|
||||
if (!ver) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_VERSION(ver);
|
||||
|
||||
if (check_hint) {
|
||||
check_hint = SDL_FALSE;
|
||||
legacy_version = SDL_GetHintBoolean("SDL_LEGACY_VERSION", SDL_FALSE);
|
||||
}
|
||||
|
||||
if (legacy_version) {
|
||||
/* Prior to SDL 2.24.0, the patch version was incremented with every release */
|
||||
ver->patch = ver->minor;
|
||||
ver->minor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the library source revision */
|
||||
|
|
@ -579,16 +604,26 @@ SDL_GetPlatform(void)
|
|||
return "Windows";
|
||||
#elif __WINRT__
|
||||
return "WinRT";
|
||||
#elif __WINGDK__
|
||||
return "WinGDK";
|
||||
#elif __XBOXONE__
|
||||
return "Xbox One";
|
||||
#elif __XBOXSERIES__
|
||||
return "Xbox Series X|S";
|
||||
#elif __TVOS__
|
||||
return "tvOS";
|
||||
#elif __IPHONEOS__
|
||||
return "iOS";
|
||||
#elif __PS2__
|
||||
return "PlayStation 2";
|
||||
#elif __PSP__
|
||||
return "PlayStation Portable";
|
||||
#elif __VITA__
|
||||
return "PlayStation Vita";
|
||||
#elif __NGAGE__
|
||||
return "Nokia N-Gage";
|
||||
#elif __3DS__
|
||||
return "Nintendo 3DS";
|
||||
#else
|
||||
return "Unknown (see SDL_platform.h)";
|
||||
#endif
|
||||
|
|
@ -628,6 +663,6 @@ _DllMainCRTStartup(HANDLE hModule,
|
|||
}
|
||||
#endif /* Building DLL */
|
||||
|
||||
#endif /* __WIN32__ */
|
||||
#endif /* defined(__WIN32__) || defined(__GDK__) */
|
||||
|
||||
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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"
|
||||
|
||||
#if defined(__WIN32__)
|
||||
#if defined(__WIN32__) || defined(__GDK__)
|
||||
#include "core/windows/SDL_windows.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
#include "SDL_assert_c.h"
|
||||
#include "video/SDL_sysvideo.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
#if defined(__WIN32__) || defined(__GDK__)
|
||||
#ifndef WS_OVERLAPPEDWINDOW
|
||||
#define WS_OVERLAPPEDWINDOW 0
|
||||
#endif
|
||||
|
|
@ -90,7 +90,7 @@ static void SDL_AddAssertionToReport(SDL_assert_data *data)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __WIN32__
|
||||
#if defined(__WIN32__) || defined(__GDK__)
|
||||
#define ENDLINE "\r\n"
|
||||
#else
|
||||
#define ENDLINE "\n"
|
||||
|
|
@ -411,6 +411,7 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
|
|||
|
||||
void SDL_AssertionsQuit(void)
|
||||
{
|
||||
#if SDL_ASSERT_LEVEL > 0
|
||||
SDL_GenerateAssertionReport();
|
||||
#ifndef SDL_THREADS_DISABLED
|
||||
if (assertion_mutex != NULL) {
|
||||
|
|
@ -418,6 +419,7 @@ void SDL_AssertionsQuit(void)
|
|||
assertion_mutex = NULL;
|
||||
}
|
||||
#endif
|
||||
#endif /* SDL_ASSERT_LEVEL > 0 */
|
||||
}
|
||||
|
||||
void SDL_SetAssertionHandler(SDL_AssertionHandler handler, void *userdata)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,22 +25,34 @@
|
|||
#include "SDL_error.h"
|
||||
#include "SDL_error_c.h"
|
||||
|
||||
#define SDL_ERRBUFIZE 1024
|
||||
|
||||
int
|
||||
SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
/* Ignore call if invalid format pointer was passed */
|
||||
if (fmt != NULL) {
|
||||
va_list ap;
|
||||
int result;
|
||||
SDL_error *error = SDL_GetErrBuf();
|
||||
|
||||
error->error = 1; /* mark error as valid */
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_vsnprintf(error->str, ERR_MAX_STRLEN, fmt, ap);
|
||||
result = SDL_vsnprintf(error->str, error->len, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (result >= 0 && (size_t)result >= error->len && error->realloc_func) {
|
||||
size_t len = (size_t)result + 1;
|
||||
char *str = (char *)error->realloc_func(error->str, len);
|
||||
if (str) {
|
||||
error->str = str;
|
||||
error->len = len;
|
||||
va_start(ap, fmt);
|
||||
SDL_vsnprintf(error->str, error->len, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) {
|
||||
/* If we are in debug mode, print out the error message */
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", error->str);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,13 @@
|
|||
#ifndef SDL_error_c_h_
|
||||
#define SDL_error_c_h_
|
||||
|
||||
#define ERR_MAX_STRLEN 128
|
||||
|
||||
typedef struct SDL_error
|
||||
{
|
||||
int error; /* This is a numeric value corresponding to the current error */
|
||||
char str[ERR_MAX_STRLEN];
|
||||
char *str;
|
||||
size_t len;
|
||||
SDL_realloc_func realloc_func;
|
||||
SDL_free_func free_func;
|
||||
} SDL_error;
|
||||
|
||||
/* Defined in SDL_thread.c */
|
||||
|
|
|
|||
91
Engine/lib/sdl/src/SDL_guid.c
Normal file
91
Engine/lib/sdl/src/SDL_guid.c
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 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_guid.h"
|
||||
|
||||
/* convert the guid to a printable string */
|
||||
void SDL_GUIDToString(SDL_GUID guid, char *pszGUID, int cbGUID)
|
||||
{
|
||||
static const char k_rgchHexToASCII[] = "0123456789abcdef";
|
||||
int i;
|
||||
|
||||
if ((pszGUID == NULL) || (cbGUID <= 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
|
||||
/* each input byte writes 2 ascii chars, and might write a null byte. */
|
||||
/* If we don't have room for next input byte, stop */
|
||||
unsigned char c = guid.data[i];
|
||||
|
||||
*pszGUID++ = k_rgchHexToASCII[c >> 4];
|
||||
*pszGUID++ = k_rgchHexToASCII[c & 0x0F];
|
||||
}
|
||||
*pszGUID = '\0';
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Purpose: Returns the 4 bit nibble for a hex character
|
||||
* Input : c -
|
||||
* Output : unsigned char
|
||||
*-----------------------------------------------------------------------------*/
|
||||
static unsigned char nibble(unsigned char c)
|
||||
{
|
||||
if ((c >= '0') && (c <= '9')) {
|
||||
return (c - '0');
|
||||
}
|
||||
|
||||
if ((c >= 'A') && (c <= 'F')) {
|
||||
return (c - 'A' + 0x0a);
|
||||
}
|
||||
|
||||
if ((c >= 'a') && (c <= 'f')) {
|
||||
return (c - 'a' + 0x0a);
|
||||
}
|
||||
|
||||
/* received an invalid character, and no real way to return an error */
|
||||
/* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* convert the string version of a guid to the struct */
|
||||
SDL_GUID SDL_GUIDFromString(const char *pchGUID)
|
||||
{
|
||||
SDL_GUID guid;
|
||||
int maxoutputbytes= sizeof(guid);
|
||||
size_t len = SDL_strlen(pchGUID);
|
||||
Uint8 *p;
|
||||
size_t i;
|
||||
|
||||
/* Make sure it's even */
|
||||
len = (len) & ~0x1;
|
||||
|
||||
SDL_memset(&guid, 0x00, sizeof(guid));
|
||||
|
||||
p = (Uint8 *)&guid;
|
||||
for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
|
||||
*p = (nibble((unsigned char)pchGUID[i]) << 4) | nibble((unsigned char)pchGUID[i+1]);
|
||||
}
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -52,7 +52,7 @@ SDL_SetHintWithPriority(const char *name, const char *value,
|
|||
SDL_Hint *hint;
|
||||
SDL_HintWatch *entry;
|
||||
|
||||
if (!name || !value) {
|
||||
if (!name) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +66,8 @@ SDL_SetHintWithPriority(const char *name, const char *value,
|
|||
if (priority < hint->priority) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
if (!hint->value || !value || SDL_strcmp(hint->value, value) != 0) {
|
||||
if (hint->value != value &&
|
||||
(!value || !hint->value || SDL_strcmp(hint->value, value) != 0)) {
|
||||
for (entry = hint->callbacks; entry; ) {
|
||||
/* Save the next entry in case this one is deleted */
|
||||
SDL_HintWatch *next = entry->next;
|
||||
|
|
@ -95,6 +96,64 @@ SDL_SetHintWithPriority(const char *name, const char *value,
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_ResetHint(const char *name)
|
||||
{
|
||||
const char *env;
|
||||
SDL_Hint *hint;
|
||||
SDL_HintWatch *entry;
|
||||
|
||||
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)) {
|
||||
for (entry = hint->callbacks; entry; ) {
|
||||
/* Save the next entry in case this one is deleted */
|
||||
SDL_HintWatch *next = entry->next;
|
||||
entry->callback(entry->userdata, name, hint->value, env);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
SDL_free(hint->value);
|
||||
hint->value = NULL;
|
||||
hint->priority = SDL_HINT_DEFAULT;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_ResetHints(void)
|
||||
{
|
||||
const char *env;
|
||||
SDL_Hint *hint;
|
||||
SDL_HintWatch *entry;
|
||||
|
||||
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)) {
|
||||
for (entry = hint->callbacks; entry; ) {
|
||||
/* Save the next entry in case this one is deleted */
|
||||
SDL_HintWatch *next = entry->next;
|
||||
entry->callback(entry->userdata, hint->name, hint->value, env);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
SDL_free(hint->value);
|
||||
hint->value = NULL;
|
||||
hint->priority = SDL_HINT_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_SetHint(const char *name, const char *value)
|
||||
{
|
||||
|
|
@ -110,7 +169,7 @@ 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 || hint->priority == SDL_HINT_OVERRIDE) {
|
||||
if (env == NULL || hint->priority == SDL_HINT_OVERRIDE) {
|
||||
return hint->value;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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"
|
||||
|
||||
#if defined(__WIN32__) || defined(__WINRT__)
|
||||
#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
|
||||
#include "core/windows/SDL_windows.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -80,16 +80,20 @@ static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {
|
|||
};
|
||||
|
||||
#ifdef __ANDROID__
|
||||
static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
|
||||
static const char *SDL_category_prefixes[] = {
|
||||
"APP",
|
||||
"ERROR",
|
||||
"ASSERT",
|
||||
"SYSTEM",
|
||||
"AUDIO",
|
||||
"VIDEO",
|
||||
"RENDER",
|
||||
"INPUT"
|
||||
"INPUT",
|
||||
"TEST"
|
||||
};
|
||||
|
||||
SDL_COMPILE_TIME_ASSERT(category_prefixes_enum, SDL_TABLESIZE(SDL_category_prefixes) == SDL_LOG_CATEGORY_RESERVED1);
|
||||
|
||||
static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
|
||||
ANDROID_LOG_UNKNOWN,
|
||||
ANDROID_LOG_VERBOSE,
|
||||
|
|
@ -362,7 +366,7 @@ SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(__WIN32__) && !defined(HAVE_STDIO_H) && !defined(__WINRT__)
|
||||
#if defined(__WIN32__) && !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__)
|
||||
/* Flag tracking the attachment of the console: 0=unattached, 1=attached to a console, 2=attached to a file, -1=error */
|
||||
static int consoleAttached = 0;
|
||||
|
||||
|
|
@ -374,7 +378,7 @@ static void SDLCALL
|
|||
SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
||||
const char *message)
|
||||
{
|
||||
#if defined(__WIN32__) || defined(__WINRT__)
|
||||
#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
|
||||
/* Way too many allocations here, urgh */
|
||||
/* Note: One can't call SDL_SetError here, since that function itself logs. */
|
||||
{
|
||||
|
|
@ -383,7 +387,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
LPTSTR tstr;
|
||||
SDL_bool isstack;
|
||||
|
||||
#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
|
||||
#if !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__)
|
||||
BOOL attachResult;
|
||||
DWORD attachError;
|
||||
DWORD charsWritten;
|
||||
|
|
@ -422,7 +426,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
|
||||
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__) */
|
||||
|
||||
length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
|
||||
output = SDL_small_alloc(char, length, &isstack);
|
||||
|
|
@ -432,7 +436,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
/* Output to debugger */
|
||||
OutputDebugString(tstr);
|
||||
|
||||
#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
|
||||
#if !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__)
|
||||
/* Screen output to stderr, if console was attached. */
|
||||
if (consoleAttached == 1) {
|
||||
if (!WriteConsole(stderrHandle, tstr, (DWORD) SDL_tcslen(tstr), &charsWritten, NULL)) {
|
||||
|
|
@ -447,7 +451,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
OutputDebugString(TEXT("Error calling WriteFile\r\n"));
|
||||
}
|
||||
}
|
||||
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
|
||||
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__) */
|
||||
|
||||
SDL_free(tstr);
|
||||
SDL_small_free(output, isstack);
|
||||
|
|
@ -467,7 +471,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
SDL_NSLog(SDL_priority_prefixes[priority], message);
|
||||
return;
|
||||
}
|
||||
#elif defined(__PSP__)
|
||||
#elif defined(__PSP__) || defined(__PS2__)
|
||||
{
|
||||
FILE* pFile;
|
||||
pFile = fopen ("SDL_Log.txt", "a");
|
||||
|
|
@ -481,8 +485,16 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||
fclose (pFile);
|
||||
}
|
||||
#elif defined(__3DS__)
|
||||
{
|
||||
FILE *pFile;
|
||||
pFile = fopen("sdmc:/3ds/SDL_Log.txt", "a");
|
||||
fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||
fclose(pFile);
|
||||
}
|
||||
#endif
|
||||
#if HAVE_STDIO_H
|
||||
#if HAVE_STDIO_H && \
|
||||
!(defined(__APPLE__) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT)))
|
||||
fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||
#if __NACL__
|
||||
fflush(stderr);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
|
|||
52
Engine/lib/sdl/src/SDL_utils.c
Normal file
52
Engine/lib/sdl/src/SDL_utils.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 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_utils_c.h"
|
||||
|
||||
/* Common utility functions that aren't in the public API */
|
||||
|
||||
int SDL_powerof2(int x)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (x <= 0) {
|
||||
/* Return some sane value - we shouldn't hit this in our use cases */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This trick works for 32-bit values */
|
||||
{
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_powerof2, sizeof(x) == sizeof(Uint32));
|
||||
}
|
||||
value = x;
|
||||
value -= 1;
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
value += 1;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,19 +18,15 @@
|
|||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
#ifndef SDL_utils_h_
|
||||
#define SDL_utils_h_
|
||||
|
||||
/* Useful functions and variables from SDL_sysevents.c */
|
||||
/* Common utility functions that aren't in the public API */
|
||||
|
||||
#if defined(__HAIKU__)
|
||||
/* The Haiku event loops run in a separate thread */
|
||||
#define MUST_THREAD_EVENTS
|
||||
#endif
|
||||
/* Return the smallest power of 2 greater than or equal to 'x' */
|
||||
int SDL_powerof2(int x);
|
||||
|
||||
#ifdef __WIN32__ /* Windows doesn't allow a separate event thread */
|
||||
#define CANT_THREAD_EVENTS
|
||||
#endif
|
||||
#endif /* SDL_utils_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,6 +128,7 @@ SDL_bool
|
|||
SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval)
|
||||
{
|
||||
#ifdef HAVE_MSC_ATOMICS
|
||||
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);
|
||||
|
|
@ -135,10 +136,8 @@ SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval)
|
|||
return (SDL_bool) __sync_bool_compare_and_swap(&a->value, oldval, newval);
|
||||
#elif defined(__MACOSX__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */
|
||||
return (SDL_bool) OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value);
|
||||
#elif defined(__SOLARIS__) && defined(_LP64)
|
||||
return (SDL_bool) ((int) atomic_cas_64((volatile uint64_t*)&a->value, (uint64_t)oldval, (uint64_t)newval) == oldval);
|
||||
#elif defined(__SOLARIS__) && !defined(_LP64)
|
||||
return (SDL_bool) ((int) atomic_cas_32((volatile uint32_t*)&a->value, (uint32_t)oldval, (uint32_t)newval) == oldval);
|
||||
#elif defined(__SOLARIS__)
|
||||
return (SDL_bool) ((int) atomic_cas_uint((volatile uint_t*)&a->value, (uint_t)oldval, (uint_t)newval) == oldval);
|
||||
#elif EMULATE_CAS
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
|
|
@ -158,9 +157,7 @@ SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval)
|
|||
SDL_bool
|
||||
SDL_AtomicCASPtr(void **a, void *oldval, void *newval)
|
||||
{
|
||||
#if defined(HAVE_MSC_ATOMICS) && (_M_IX86)
|
||||
return (_InterlockedCompareExchange((long*)a, (long)newval, (long)oldval) == (long)oldval);
|
||||
#elif defined(HAVE_MSC_ATOMICS) && (!_M_IX86)
|
||||
#if defined(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);
|
||||
|
|
@ -192,15 +189,14 @@ int
|
|||
SDL_AtomicSet(SDL_atomic_t *a, int v)
|
||||
{
|
||||
#ifdef HAVE_MSC_ATOMICS
|
||||
SDL_COMPILE_TIME_ASSERT(atomic_set, sizeof(long) == sizeof(a->value));
|
||||
return _InterlockedExchange((long*)&a->value, v);
|
||||
#elif defined(HAVE_WATCOM_ATOMICS)
|
||||
return _SDL_xchg_watcom(&a->value, v);
|
||||
#elif defined(HAVE_GCC_ATOMICS)
|
||||
return __sync_lock_test_and_set(&a->value, v);
|
||||
#elif defined(__SOLARIS__) && defined(_LP64)
|
||||
return (int) atomic_swap_64((volatile uint64_t*)&a->value, (uint64_t)v);
|
||||
#elif defined(__SOLARIS__) && !defined(_LP64)
|
||||
return (int) atomic_swap_32((volatile uint32_t*)&a->value, (uint32_t)v);
|
||||
#elif defined(__SOLARIS__)
|
||||
return (int) atomic_swap_uint((volatile uint_t*)&a->value, v);
|
||||
#else
|
||||
int value;
|
||||
do {
|
||||
|
|
@ -213,9 +209,7 @@ SDL_AtomicSet(SDL_atomic_t *a, int v)
|
|||
void*
|
||||
SDL_AtomicSetPtr(void **a, void *v)
|
||||
{
|
||||
#if defined(HAVE_MSC_ATOMICS) && (_M_IX86)
|
||||
return (void *) _InterlockedExchange((long *)a, (long) v);
|
||||
#elif defined(HAVE_MSC_ATOMICS) && (!_M_IX86)
|
||||
#if defined(HAVE_MSC_ATOMICS)
|
||||
return _InterlockedExchangePointer(a, v);
|
||||
#elif defined(HAVE_WATCOM_ATOMICS)
|
||||
return (void *) _SDL_xchg_watcom((int *)a, (long)v);
|
||||
|
|
@ -236,6 +230,7 @@ int
|
|||
SDL_AtomicAdd(SDL_atomic_t *a, int v)
|
||||
{
|
||||
#ifdef HAVE_MSC_ATOMICS
|
||||
SDL_COMPILE_TIME_ASSERT(atomic_add, sizeof(long) == sizeof(a->value));
|
||||
return _InterlockedExchangeAdd((long*)&a->value, v);
|
||||
#elif defined(HAVE_WATCOM_ATOMICS)
|
||||
return _SDL_xadd_watcom(&a->value, v);
|
||||
|
|
@ -244,11 +239,7 @@ SDL_AtomicAdd(SDL_atomic_t *a, int v)
|
|||
#elif defined(__SOLARIS__)
|
||||
int pv = a->value;
|
||||
membar_consumer();
|
||||
#if defined(_LP64)
|
||||
atomic_add_64((volatile uint64_t*)&a->value, v);
|
||||
#elif !defined(_LP64)
|
||||
atomic_add_32((volatile uint32_t*)&a->value, v);
|
||||
#endif
|
||||
atomic_add_int((volatile uint_t*)&a->value, v);
|
||||
return pv;
|
||||
#else
|
||||
int value;
|
||||
|
|
@ -264,6 +255,17 @@ SDL_AtomicGet(SDL_atomic_t *a)
|
|||
{
|
||||
#ifdef HAVE_ATOMIC_LOAD_N
|
||||
return __atomic_load_n(&a->value, __ATOMIC_SEQ_CST);
|
||||
#elif defined(HAVE_MSC_ATOMICS)
|
||||
SDL_COMPILE_TIME_ASSERT(atomic_get, sizeof(long) == sizeof(a->value));
|
||||
return _InterlockedOr((long *)&a->value, 0);
|
||||
#elif defined(HAVE_WATCOM_ATOMICS)
|
||||
return _SDL_xadd_watcom(&a->value, 0);
|
||||
#elif defined(HAVE_GCC_ATOMICS)
|
||||
return __sync_or_and_fetch(&a->value, 0);
|
||||
#elif defined(__MACOSX__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */
|
||||
return sizeof(a->value) == sizeof(uint32_t) ? OSAtomicOr32Barrier(0, (volatile uint32_t *)&a->value) : OSAtomicAdd64Barrier(0, (volatile int64_t *)&a->value);
|
||||
#elif defined(__SOLARIS__)
|
||||
return atomic_or_uint((volatile uint_t *)&a->value, 0);
|
||||
#else
|
||||
int value;
|
||||
do {
|
||||
|
|
@ -278,6 +280,12 @@ SDL_AtomicGetPtr(void **a)
|
|||
{
|
||||
#ifdef HAVE_ATOMIC_LOAD_N
|
||||
return __atomic_load_n(a, __ATOMIC_SEQ_CST);
|
||||
#elif defined(HAVE_MSC_ATOMICS)
|
||||
return _InterlockedCompareExchangePointer(a, NULL, NULL);
|
||||
#elif defined(HAVE_GCC_ATOMICS)
|
||||
return __sync_val_compare_and_swap(a, (void *)0, (void *)0);
|
||||
#elif defined(__SOLARIS__)
|
||||
return atomic_cas_ptr(a, (void *)0, (void *)0);
|
||||
#else
|
||||
void *value;
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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"
|
||||
|
||||
#if defined(__WIN32__) || defined(__WINRT__)
|
||||
#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
|
||||
#include "../core/windows/SDL_windows.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -40,6 +40,14 @@
|
|||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(PS2)
|
||||
#include <kernel.h>
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_GCC_ATOMICS) && defined(__MACOSX__)
|
||||
#include <libkern/OSAtomic.h>
|
||||
#endif
|
||||
|
||||
#if defined(__WATCOMC__) && defined(__386__)
|
||||
SDL_COMPILE_TIME_ASSERT(locksize, 4==sizeof(SDL_SpinLock));
|
||||
extern __inline int _SDL_xchg_watcom(volatile int *a, int v);
|
||||
|
|
@ -131,32 +139,25 @@ SDL_AtomicTryLock(SDL_SpinLock *lock)
|
|||
#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);
|
||||
#elif defined(PS2)
|
||||
uint32_t oldintr;
|
||||
SDL_bool res = SDL_FALSE;
|
||||
// disable interuption
|
||||
oldintr = DIntr();
|
||||
|
||||
if (*lock == 0) {
|
||||
*lock = 1;
|
||||
res = SDL_TRUE;
|
||||
}
|
||||
// enable interuption
|
||||
if(oldintr) { EIntr(); }
|
||||
return res;
|
||||
#else
|
||||
#error Please implement for your platform.
|
||||
return SDL_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define PAUSE_INSTRUCTION() __asm__ __volatile__("pause\n") /* Some assemblers can't do REP NOP, so go with PAUSE. */
|
||||
#elif (defined(__arm__) && __ARM_ARCH__ >= 7) || defined(__aarch64__)
|
||||
#define PAUSE_INSTRUCTION() __asm__ __volatile__("yield" ::: "memory")
|
||||
#elif (defined(__powerpc__) || defined(__powerpc64__))
|
||||
#define PAUSE_INSTRUCTION() __asm__ __volatile__("or 27,27,27");
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
#define PAUSE_INSTRUCTION() _mm_pause() /* this is actually "rep nop" and not a SIMD instruction. No inline asm in MSVC x86-64! */
|
||||
#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
#define PAUSE_INSTRUCTION() __yield()
|
||||
#elif defined(__WATCOMC__) && defined(__386__)
|
||||
/* watcom assembler rejects PAUSE if CPU < i686, and it refuses REP NOP as an invalid combination. Hardcode the bytes. */
|
||||
extern __inline void PAUSE_INSTRUCTION(void);
|
||||
#pragma aux PAUSE_INSTRUCTION = "db 0f3h,90h"
|
||||
#else
|
||||
#define PAUSE_INSTRUCTION()
|
||||
#endif
|
||||
|
||||
void
|
||||
SDL_AtomicLock(SDL_SpinLock *lock)
|
||||
{
|
||||
|
|
@ -165,7 +166,7 @@ SDL_AtomicLock(SDL_SpinLock *lock)
|
|||
while (!SDL_AtomicTryLock(lock)) {
|
||||
if (iterations < 32) {
|
||||
iterations++;
|
||||
PAUSE_INSTRUCTION();
|
||||
SDL_CPUPauseInstruction();
|
||||
} else {
|
||||
/* !!! FIXME: this doesn't definitely give up the current timeslice, it does different things on various platforms. */
|
||||
SDL_Delay(0);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,6 +27,7 @@
|
|||
#include "SDL_audio_c.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
#include "../thread/SDL_systhread.h"
|
||||
#include "../SDL_utils_c.h"
|
||||
|
||||
#define _THIS SDL_AudioDevice *_this
|
||||
|
||||
|
|
@ -95,12 +96,18 @@ static const AudioBootStrap *const bootstrap[] = {
|
|||
#if SDL_AUDIO_DRIVER_ANDROID
|
||||
&ANDROIDAUDIO_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_PS2
|
||||
&PS2AUDIO_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_PSP
|
||||
&PSPAUDIO_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_VITA
|
||||
&VITAAUD_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_N3DS
|
||||
&N3DSAUDIO_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_EMSCRIPTEN
|
||||
&EMSCRIPTENAUDIO_bootstrap,
|
||||
#endif
|
||||
|
|
@ -137,6 +144,7 @@ int (*SRC_src_process)(SRC_STATE *state, SRC_DATA *data) = NULL;
|
|||
int (*SRC_src_reset)(SRC_STATE *state) = NULL;
|
||||
SRC_STATE* (*SRC_src_delete)(SRC_STATE *state) = NULL;
|
||||
const char* (*SRC_src_strerror)(int error) = NULL;
|
||||
int (*SRC_src_simple)(SRC_DATA *data, int converter_type, int channels) = NULL;
|
||||
|
||||
static SDL_bool
|
||||
LoadLibSampleRate(void)
|
||||
|
|
@ -171,8 +179,9 @@ LoadLibSampleRate(void)
|
|||
SRC_src_reset = (int(*)(SRC_STATE *state))SDL_LoadFunction(SRC_lib, "src_reset");
|
||||
SRC_src_delete = (SRC_STATE* (*)(SRC_STATE *state))SDL_LoadFunction(SRC_lib, "src_delete");
|
||||
SRC_src_strerror = (const char* (*)(int error))SDL_LoadFunction(SRC_lib, "src_strerror");
|
||||
SRC_src_simple = (int(*)(SRC_DATA *data, int converter_type, int channels))SDL_LoadFunction(SRC_lib, "src_simple");
|
||||
|
||||
if (!SRC_src_new || !SRC_src_process || !SRC_src_reset || !SRC_src_delete || !SRC_src_strerror) {
|
||||
if (!SRC_src_new || !SRC_src_process || !SRC_src_reset || !SRC_src_delete || !SRC_src_strerror || !SRC_src_simple) {
|
||||
SDL_UnloadObject(SRC_lib);
|
||||
SRC_lib = NULL;
|
||||
return SDL_FALSE;
|
||||
|
|
@ -183,6 +192,7 @@ LoadLibSampleRate(void)
|
|||
SRC_src_reset = src_reset;
|
||||
SRC_src_delete = src_delete;
|
||||
SRC_src_strerror = src_strerror;
|
||||
SRC_src_simple = src_simple;
|
||||
#endif
|
||||
|
||||
SRC_available = SDL_TRUE;
|
||||
|
|
@ -382,7 +392,7 @@ add_audio_device(const char *name, SDL_AudioSpec *spec, void *handle, SDL_AudioD
|
|||
item->dupenum = 0;
|
||||
item->name = item->original_name;
|
||||
if (spec != NULL) {
|
||||
SDL_memcpy(&item->spec, spec, sizeof(SDL_AudioSpec));
|
||||
SDL_copyp(&item->spec, spec);
|
||||
} else {
|
||||
SDL_zero(item->spec);
|
||||
}
|
||||
|
|
@ -523,6 +533,7 @@ SDL_RemoveAudioDevice(const SDL_bool iscapture, void *handle)
|
|||
{
|
||||
int device_index;
|
||||
SDL_AudioDevice *device = NULL;
|
||||
SDL_bool device_was_opened = SDL_FALSE;
|
||||
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
if (iscapture) {
|
||||
|
|
@ -535,10 +546,29 @@ SDL_RemoveAudioDevice(const SDL_bool iscapture, void *handle)
|
|||
device = open_devices[device_index];
|
||||
if (device != NULL && device->handle == handle)
|
||||
{
|
||||
device_was_opened = SDL_TRUE;
|
||||
SDL_OpenedAudioDeviceDisconnected(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Devices that aren't opened, as of 2.24.0, will post an
|
||||
SDL_AUDIODEVICEREMOVED event with the `which` field set to zero.
|
||||
Apps can use this to decide if they need to refresh a list of
|
||||
available devices instead of closing an opened one.
|
||||
Note that opened devices will send the non-zero event in
|
||||
SDL_OpenedAudioDeviceDisconnected(). */
|
||||
if (!device_was_opened) {
|
||||
if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.adevice.type = SDL_AUDIODEVICEREMOVED;
|
||||
event.adevice.which = 0;
|
||||
event.adevice.iscapture = iscapture ? 1 : 0;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
|
||||
current_audio.impl.FreeDeviceHandle(handle);
|
||||
|
|
@ -945,6 +975,15 @@ SDL_AudioInit(const char *driver_name)
|
|||
const char *driver_attempt_end = SDL_strchr(driver_attempt, ',');
|
||||
size_t driver_attempt_len = (driver_attempt_end != NULL) ? (driver_attempt_end - driver_attempt)
|
||||
: SDL_strlen(driver_attempt);
|
||||
#if SDL_AUDIO_DRIVER_DSOUND
|
||||
/* SDL 1.2 uses the name "dsound", so we'll support both. */
|
||||
if (driver_attempt_len == SDL_strlen("dsound") &&
|
||||
(SDL_strncasecmp(driver_attempt, "dsound", driver_attempt_len) == 0)) {
|
||||
driver_attempt = "directsound";
|
||||
driver_attempt_len = SDL_strlen("directsound");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SDL_AUDIO_DRIVER_PULSEAUDIO
|
||||
/* SDL 1.2 uses the name "pulse", so we'll support both. */
|
||||
if (driver_attempt_len == SDL_strlen("pulse") &&
|
||||
|
|
@ -1131,7 +1170,7 @@ SDL_GetAudioDeviceSpec(int index, int iscapture, SDL_AudioSpec *spec)
|
|||
SDL_assert(item != NULL);
|
||||
}
|
||||
SDL_assert(item != NULL);
|
||||
SDL_memcpy(spec, &item->spec, sizeof(SDL_AudioSpec));
|
||||
SDL_copyp(spec, &item->spec);
|
||||
retval = 0;
|
||||
} else {
|
||||
retval = SDL_InvalidParamError("index");
|
||||
|
|
@ -1142,6 +1181,24 @@ SDL_GetAudioDeviceSpec(int index, int iscapture, SDL_AudioSpec *spec)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
SDL_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
|
||||
{
|
||||
if (spec == NULL) {
|
||||
return SDL_InvalidParamError("spec");
|
||||
}
|
||||
|
||||
if (!SDL_GetCurrentAudioDriver()) {
|
||||
return SDL_SetError("Audio subsystem is not initialized");
|
||||
}
|
||||
|
||||
if (current_audio.impl.GetDefaultAudioInfo == NULL) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
return current_audio.impl.GetDefaultAudioInfo(name, spec, iscapture);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
close_audio_device(SDL_AudioDevice * device)
|
||||
{
|
||||
|
|
@ -1193,7 +1250,7 @@ close_audio_device(SDL_AudioDevice * device)
|
|||
static int
|
||||
prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
|
||||
{
|
||||
SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
|
||||
SDL_copyp(prepared, orig);
|
||||
|
||||
if (orig->freq == 0) {
|
||||
const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
|
||||
|
|
@ -1209,22 +1266,12 @@ prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
|
|||
}
|
||||
}
|
||||
|
||||
switch (orig->channels) {
|
||||
case 0:{
|
||||
const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
|
||||
if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
|
||||
prepared->channels = 2; /* a reasonable default */
|
||||
break;
|
||||
}
|
||||
if (orig->channels == 0) {
|
||||
const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
|
||||
if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
|
||||
prepared->channels = 2; /* a reasonable default */
|
||||
}
|
||||
case 1: /* Mono */
|
||||
case 2: /* Stereo */
|
||||
case 4: /* Quadrophonic */
|
||||
case 6: /* 5.1 surround */
|
||||
case 7: /* 6.1 surround */
|
||||
case 8: /* 7.1 surround */
|
||||
break;
|
||||
default:
|
||||
} else if (orig->channels > 8) {
|
||||
SDL_SetError("Unsupported number of audio channels.");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1272,7 +1319,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
/* Find an available device ID... */
|
||||
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
|
||||
if (open_devices[id] == NULL) {
|
||||
|
|
@ -1282,6 +1329,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
|
||||
if (id == SDL_arraysize(open_devices)) {
|
||||
SDL_SetError("Too many open audio devices");
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1289,6 +1337,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
obtained = &_obtained;
|
||||
}
|
||||
if (!prepare_audiospec(desired, obtained)) {
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1310,6 +1359,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) {
|
||||
if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
|
||||
SDL_SetError("No such device");
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
devname = NULL;
|
||||
|
|
@ -1317,11 +1367,13 @@ open_audio_device(const char *devname, int iscapture,
|
|||
for (i = 0; i < SDL_arraysize(open_devices); i++) {
|
||||
if ((open_devices[i]) && (open_devices[i]->iscapture)) {
|
||||
SDL_SetError("Audio device already open");
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
|
||||
if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
SDL_SetError("No such device");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1329,6 +1381,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
|
||||
for (i = 0; i < SDL_arraysize(open_devices); i++) {
|
||||
if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
SDL_SetError("Audio device already open");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1341,20 +1394,19 @@ open_audio_device(const char *devname, int iscapture,
|
|||
It might still need to open a device based on the string for,
|
||||
say, a network audio server, but this optimizes some cases. */
|
||||
SDL_AudioDeviceItem *item;
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
|
||||
if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
|
||||
handle = item->handle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
}
|
||||
|
||||
if (!current_audio.impl.AllowsArbitraryDeviceNames) {
|
||||
/* has to be in our device list, or the default device. */
|
||||
if ((handle == NULL) && (devname != NULL)) {
|
||||
SDL_SetError("No such device.");
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1362,6 +1414,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
device = (SDL_AudioDevice *) SDL_calloc(1, sizeof (SDL_AudioDevice));
|
||||
if (device == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
device->id = id + 1;
|
||||
|
|
@ -1378,13 +1431,22 @@ open_audio_device(const char *devname, int iscapture,
|
|||
device->mixer_lock = SDL_CreateMutex();
|
||||
if (device->mixer_lock == NULL) {
|
||||
close_audio_device(device);
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
SDL_SetError("Couldn't create mixer lock");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* For backends that require a power-of-two value for spec.samples, take the
|
||||
* value we got from 'desired' and round up to the nearest value
|
||||
*/
|
||||
if (!current_audio.impl.SupportsNonPow2Samples && device->spec.samples > 0) {
|
||||
device->spec.samples = SDL_powerof2(device->spec.samples);
|
||||
}
|
||||
|
||||
if (current_audio.impl.OpenDevice(device, devname) < 0) {
|
||||
close_audio_device(device);
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1440,6 +1502,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
|
||||
if (!device->stream) {
|
||||
close_audio_device(device);
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1449,6 +1512,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
device->buffer_queue = SDL_NewDataQueue(SDL_AUDIOBUFFERQUEUE_PACKETLEN, obtained->size * 2);
|
||||
if (!device->buffer_queue) {
|
||||
close_audio_device(device);
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
SDL_SetError("Couldn't create audio buffer queue");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1466,6 +1530,7 @@ open_audio_device(const char *devname, int iscapture,
|
|||
device->work_buffer = (Uint8 *) SDL_malloc(device->work_buffer_len);
|
||||
if (device->work_buffer == NULL) {
|
||||
close_audio_device(device);
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1486,9 +1551,11 @@ open_audio_device(const char *devname, int iscapture,
|
|||
if (device->thread == NULL) {
|
||||
close_audio_device(device);
|
||||
SDL_SetError("Couldn't create audio thread");
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
|
||||
return device->id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,7 +29,7 @@
|
|||
#endif
|
||||
|
||||
#if DEBUG_CONVERT
|
||||
#define LOG_DEBUG_CONVERT(from, to) fprintf(stderr, "Converting %s to %s.\n", from, to);
|
||||
#define LOG_DEBUG_CONVERT(from, to) SDL_Log("SDL_AUDIO_CONVERT: Converting %s to %s.\n", from, to);
|
||||
#else
|
||||
#define LOG_DEBUG_CONVERT(from, to)
|
||||
#endif
|
||||
|
|
@ -45,6 +45,7 @@ extern int (*SRC_src_process)(SRC_STATE *state, SRC_DATA *data);
|
|||
extern int (*SRC_src_reset)(SRC_STATE *state);
|
||||
extern SRC_STATE* (*SRC_src_delete)(SRC_STATE *state);
|
||||
extern const char* (*SRC_src_strerror)(int error);
|
||||
extern int (*SRC_src_simple)(SRC_DATA *data, int converter_type, int channels);
|
||||
#endif
|
||||
|
||||
/* Functions to get a list of "close" audio formats */
|
||||
|
|
|
|||
1459
Engine/lib/sdl/src/audio/SDL_audio_channel_converters.h
Normal file
1459
Engine/lib/sdl/src/audio/SDL_audio_channel_converters.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -78,6 +78,7 @@ typedef struct SDL_AudioDriverImpl
|
|||
void (*UnlockDevice) (_THIS);
|
||||
void (*FreeDeviceHandle) (void *handle); /**< SDL is done with handle from SDL_AddAudioDevice() */
|
||||
void (*Deinitialize) (void);
|
||||
int (*GetDefaultAudioInfo) (char **name, SDL_AudioSpec *spec, int iscapture);
|
||||
|
||||
/* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */
|
||||
|
||||
|
|
@ -87,6 +88,7 @@ typedef struct SDL_AudioDriverImpl
|
|||
SDL_bool OnlyHasDefaultOutputDevice;
|
||||
SDL_bool OnlyHasDefaultCaptureDevice;
|
||||
SDL_bool AllowsArbitraryDeviceNames;
|
||||
SDL_bool SupportsNonPow2Samples;
|
||||
} SDL_AudioDriverImpl;
|
||||
|
||||
|
||||
|
|
@ -204,8 +206,10 @@ extern AudioBootStrap FUSIONSOUND_bootstrap;
|
|||
extern AudioBootStrap aaudio_bootstrap;
|
||||
extern AudioBootStrap openslES_bootstrap;
|
||||
extern AudioBootStrap ANDROIDAUDIO_bootstrap;
|
||||
extern AudioBootStrap PS2AUDIO_bootstrap;
|
||||
extern AudioBootStrap PSPAUDIO_bootstrap;
|
||||
extern AudioBootStrap VITAAUD_bootstrap;
|
||||
extern AudioBootStrap N3DSAUDIO_bootstrap;
|
||||
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
|
||||
extern AudioBootStrap OS2AUDIO_bootstrap;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -437,14 +437,17 @@ void aaudio_ResumeDevices(void)
|
|||
*/
|
||||
SDL_bool aaudio_DetectBrokenPlayState( void )
|
||||
{
|
||||
struct SDL_PrivateAudioData *private;
|
||||
int64_t framePosition, timeNanoseconds;
|
||||
aaudio_result_t res;
|
||||
|
||||
if ( !audioDevice || !audioDevice->hidden ) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
struct SDL_PrivateAudioData *private = audioDevice->hidden;
|
||||
private = audioDevice->hidden;
|
||||
|
||||
int64_t framePosition, timeNanoseconds;
|
||||
aaudio_result_t res = ctx.AAudioStream_getTimestamp( private->stream, CLOCK_MONOTONIC, &framePosition, &timeNanoseconds );
|
||||
res = ctx.AAudioStream_getTimestamp( private->stream, CLOCK_MONOTONIC, &framePosition, &timeNanoseconds );
|
||||
if ( res == AAUDIO_ERROR_INVALID_STATE ) {
|
||||
aaudio_stream_state_t currentState = ctx.AAudioStream_getState( private->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. */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright , (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -1009,6 +1009,7 @@ ALSA_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->FlushCapture = ALSA_FlushCapture;
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->SupportsNonPow2Samples = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -318,7 +318,7 @@ ARTS_Init(SDL_AudioDriverImpl * impl)
|
|||
if (LoadARTSLibrary() < 0) {
|
||||
return SDL_FALSE;
|
||||
} else {
|
||||
if (SDL_NAME(arts_init) () != 0) {
|
||||
if (SDL_NAME(arts_init) () != NULL) {
|
||||
UnloadARTSLibrary();
|
||||
SDL_SetError("ARTS: arts_init failed (no audio server?)");
|
||||
return SDL_FALSE;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,6 +39,14 @@
|
|||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
/* Things named "Master" were renamed to "Main" in macOS 12.0's SDK. */
|
||||
#if MACOSX_COREAUDIO
|
||||
#include <AvailabilityMacros.h>
|
||||
#ifndef MAC_OS_VERSION_12_0
|
||||
#define kAudioObjectPropertyElementMain kAudioObjectPropertyElementMaster
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
|
|
@ -54,7 +62,6 @@ struct SDL_PrivateAudioData
|
|||
AudioStreamBasicDescription strdesc;
|
||||
SDL_sem *ready_semaphore;
|
||||
char *thread_error;
|
||||
SDL_atomic_t shutdown;
|
||||
#if MACOSX_COREAUDIO
|
||||
AudioDeviceID deviceID;
|
||||
SDL_atomic_t device_change_flag;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
static const AudioObjectPropertyAddress devlist_address = {
|
||||
kAudioHardwarePropertyDevices,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
|
||||
typedef void (*addDevFn)(const char *name, SDL_AudioSpec *spec, const int iscapture, AudioDeviceID devId, void *data);
|
||||
|
|
@ -131,17 +131,17 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
|
|||
const AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyStreamConfiguration,
|
||||
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
const AudioObjectPropertyAddress nameaddr = {
|
||||
kAudioObjectPropertyName,
|
||||
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
const AudioObjectPropertyAddress freqaddr = {
|
||||
kAudioDevicePropertyNominalSampleRate,
|
||||
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
|
||||
result = AudioObjectGetPropertyDataSize(dev, &addr, 0, NULL, &size);
|
||||
|
|
@ -523,9 +523,16 @@ outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffe
|
|||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) inUserData;
|
||||
|
||||
/* This flag is set before this->mixer_lock is destroyed during
|
||||
shutdown, so check it before grabbing the mutex, and then check it
|
||||
again _after_ in case we blocked waiting on the lock. */
|
||||
if (SDL_AtomicGet(&this->shutdown)) {
|
||||
return; /* don't do anything, since we don't even want to enqueue this buffer again. */
|
||||
}
|
||||
|
||||
SDL_LockMutex(this->mixer_lock);
|
||||
|
||||
if (SDL_AtomicGet(&this->hidden->shutdown)) {
|
||||
if (SDL_AtomicGet(&this->shutdown)) {
|
||||
SDL_UnlockMutex(this->mixer_lock);
|
||||
return; /* don't do anything, since we don't even want to enqueue this buffer again. */
|
||||
}
|
||||
|
|
@ -635,7 +642,7 @@ static const AudioObjectPropertyAddress alive_address =
|
|||
{
|
||||
kAudioDevicePropertyDeviceIsAlive,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
|
||||
static OSStatus
|
||||
|
|
@ -694,6 +701,19 @@ COREAUDIO_CloseDevice(_THIS)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* if callback fires again, feed silence; don't call into the app. */
|
||||
SDL_AtomicSet(&this->paused, 1);
|
||||
|
||||
/* dispose of the audio queue before waiting on the thread, or it might stall for a long time! */
|
||||
if (this->hidden->audioQueue) {
|
||||
AudioQueueDispose(this->hidden->audioQueue, 0);
|
||||
}
|
||||
|
||||
if (this->hidden->thread) {
|
||||
SDL_assert(SDL_AtomicGet(&this->shutdown) != 0); /* should have been set by SDL_audio.c */
|
||||
SDL_WaitThread(this->hidden->thread, NULL);
|
||||
}
|
||||
|
||||
if (iscapture) {
|
||||
open_capture_devices--;
|
||||
} else {
|
||||
|
|
@ -718,18 +738,6 @@ COREAUDIO_CloseDevice(_THIS)
|
|||
open_devices = NULL;
|
||||
}
|
||||
|
||||
/* if callback fires again, feed silence; don't call into the app. */
|
||||
SDL_AtomicSet(&this->paused, 1);
|
||||
|
||||
if (this->hidden->audioQueue) {
|
||||
AudioQueueDispose(this->hidden->audioQueue, 1);
|
||||
}
|
||||
|
||||
if (this->hidden->thread) {
|
||||
SDL_AtomicSet(&this->hidden->shutdown, 1);
|
||||
SDL_WaitThread(this->hidden->thread, NULL);
|
||||
}
|
||||
|
||||
if (this->hidden->ready_semaphore) {
|
||||
SDL_DestroySemaphore(this->hidden->ready_semaphore);
|
||||
}
|
||||
|
|
@ -756,7 +764,7 @@ prepare_device(_THIS)
|
|||
AudioObjectPropertyAddress addr = {
|
||||
0,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
|
||||
if (handle == NULL) {
|
||||
|
|
@ -803,7 +811,7 @@ assign_device_to_audioqueue(_THIS)
|
|||
const AudioObjectPropertyAddress prop = {
|
||||
kAudioDevicePropertyDeviceUID,
|
||||
this->iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
|
||||
OSStatus result;
|
||||
|
|
@ -824,7 +832,10 @@ prepare_audioqueue(_THIS)
|
|||
const AudioStreamBasicDescription *strdesc = &this->hidden->strdesc;
|
||||
const int iscapture = this->iscapture;
|
||||
OSStatus result;
|
||||
int i;
|
||||
int i, numAudioBuffers = 2;
|
||||
AudioChannelLayout layout;
|
||||
double MINIMUM_AUDIO_BUFFER_TIME_MS;
|
||||
const double msecs = (this->spec.samples / ((double) this->spec.freq)) * 1000.0;;
|
||||
|
||||
SDL_assert(CFRunLoopGetCurrent() != NULL);
|
||||
|
||||
|
|
@ -856,7 +867,6 @@ prepare_audioqueue(_THIS)
|
|||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Set the channel layout for the audio queue */
|
||||
AudioChannelLayout layout;
|
||||
SDL_zero(layout);
|
||||
switch (this->spec.channels) {
|
||||
case 1:
|
||||
|
|
@ -901,15 +911,13 @@ prepare_audioqueue(_THIS)
|
|||
}
|
||||
|
||||
/* Make sure we can feed the device a minimum amount of time */
|
||||
double MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
|
||||
MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0;
|
||||
#if defined(__IPHONEOS__)
|
||||
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
|
||||
/* Older iOS hardware, use 40 ms as a minimum time */
|
||||
MINIMUM_AUDIO_BUFFER_TIME_MS = 40.0;
|
||||
}
|
||||
#endif
|
||||
const double msecs = (this->spec.samples / ((double) this->spec.freq)) * 1000.0;
|
||||
int numAudioBuffers = 2;
|
||||
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);
|
||||
}
|
||||
|
|
@ -946,12 +954,13 @@ static int
|
|||
audioqueue_thread(void *arg)
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) arg;
|
||||
int rc;
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
const AudioObjectPropertyAddress default_device_address = {
|
||||
this->iscapture ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
|
||||
if (this->handle == NULL) { /* opened the default device? Register to know if the user picks a new default. */
|
||||
|
|
@ -960,7 +969,7 @@ audioqueue_thread(void *arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
const int rc = prepare_audioqueue(this);
|
||||
rc = prepare_audioqueue(this);
|
||||
if (!rc) {
|
||||
this->hidden->thread_error = SDL_strdup(SDL_GetError());
|
||||
SDL_SemPost(this->hidden->ready_semaphore);
|
||||
|
|
@ -972,11 +981,12 @@ audioqueue_thread(void *arg)
|
|||
/* init was successful, alert parent thread and start running... */
|
||||
SDL_SemPost(this->hidden->ready_semaphore);
|
||||
|
||||
while (!SDL_AtomicGet(&this->hidden->shutdown)) {
|
||||
while (!SDL_AtomicGet(&this->shutdown)) {
|
||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
if ((this->handle == NULL) && SDL_AtomicGet(&this->hidden->device_change_flag)) {
|
||||
const AudioDeviceID prev_devid = this->hidden->deviceID;
|
||||
SDL_AtomicSet(&this->hidden->device_change_flag, 0);
|
||||
|
||||
#if DEBUG_COREAUDIO
|
||||
|
|
@ -986,7 +996,6 @@ audioqueue_thread(void *arg)
|
|||
/* if any of this fails, there's not much to do but wait to see if the user gives up
|
||||
and quits (flagging the audioqueue for shutdown), or toggles to some other system
|
||||
output device (in which case we'll try again). */
|
||||
const AudioDeviceID prev_devid = this->hidden->deviceID;
|
||||
if (prepare_device(this) && (prev_devid != this->hidden->deviceID)) {
|
||||
AudioQueueStop(this->hidden->audioQueue, 1);
|
||||
if (assign_device_to_audioqueue(this)) {
|
||||
|
|
@ -1122,7 +1131,6 @@ COREAUDIO_OpenDevice(_THIS, const char *devname)
|
|||
#endif
|
||||
|
||||
/* This has to init in a new thread so it can get its own CFRunLoop. :/ */
|
||||
SDL_AtomicSet(&this->hidden->shutdown, 0);
|
||||
this->hidden->ready_semaphore = SDL_CreateSemaphore(0);
|
||||
if (!this->hidden->ready_semaphore) {
|
||||
return -1; /* oh well. */
|
||||
|
|
@ -1144,6 +1152,142 @@ COREAUDIO_OpenDevice(_THIS, const char *devname)
|
|||
return (this->hidden->thread != NULL) ? 0 : -1;
|
||||
}
|
||||
|
||||
#if !MACOSX_COREAUDIO
|
||||
static int
|
||||
COREAUDIO_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
|
||||
{
|
||||
AVAudioSession* session = [AVAudioSession sharedInstance];
|
||||
|
||||
if (name != NULL) {
|
||||
*name = NULL;
|
||||
}
|
||||
SDL_zerop(spec);
|
||||
spec->freq = [session sampleRate];
|
||||
spec->channels = [session outputNumberOfChannels];
|
||||
return 0;
|
||||
}
|
||||
#else /* MACOSX_COREAUDIO */
|
||||
static int
|
||||
COREAUDIO_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
|
||||
{
|
||||
AudioDeviceID devid;
|
||||
AudioBufferList *buflist;
|
||||
OSStatus result;
|
||||
UInt32 size;
|
||||
CFStringRef cfstr;
|
||||
char *devname;
|
||||
int usable;
|
||||
double sampleRate;
|
||||
CFIndex len;
|
||||
|
||||
AudioObjectPropertyAddress addr = {
|
||||
iscapture ? kAudioHardwarePropertyDefaultInputDevice
|
||||
: kAudioHardwarePropertyDefaultOutputDevice,
|
||||
iscapture ? kAudioDevicePropertyScopeInput
|
||||
: kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
AudioObjectPropertyAddress nameaddr = {
|
||||
kAudioObjectPropertyName,
|
||||
iscapture ? kAudioDevicePropertyScopeInput
|
||||
: kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
AudioObjectPropertyAddress freqaddr = {
|
||||
kAudioDevicePropertyNominalSampleRate,
|
||||
iscapture ? kAudioDevicePropertyScopeInput
|
||||
: kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
AudioObjectPropertyAddress bufaddr = {
|
||||
kAudioDevicePropertyStreamConfiguration,
|
||||
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMain
|
||||
};
|
||||
|
||||
/* Get the Device ID */
|
||||
cfstr = NULL;
|
||||
size = sizeof (AudioDeviceID);
|
||||
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
|
||||
0, NULL, &size, &devid);
|
||||
|
||||
if (result != noErr) {
|
||||
return SDL_SetError("%s: Default Device ID not found", "coreaudio");
|
||||
}
|
||||
|
||||
if (name != NULL) {
|
||||
/* Use the Device ID to get the name */
|
||||
size = sizeof (CFStringRef);
|
||||
result = AudioObjectGetPropertyData(devid, &nameaddr, 0, NULL, &size, &cfstr);
|
||||
|
||||
if (result != noErr) {
|
||||
return SDL_SetError("%s: Default Device Name not found", "coreaudio");
|
||||
}
|
||||
|
||||
len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr),
|
||||
kCFStringEncodingUTF8);
|
||||
devname = (char *) SDL_malloc(len + 1);
|
||||
usable = ((devname != NULL) &&
|
||||
(CFStringGetCString(cfstr, devname, len + 1, kCFStringEncodingUTF8)));
|
||||
CFRelease(cfstr);
|
||||
|
||||
if (usable) {
|
||||
usable = 0;
|
||||
len = strlen(devname);
|
||||
/* Some devices have whitespace at the end...trim it. */
|
||||
while ((len > 0) && (devname[len - 1] == ' ')) {
|
||||
len--;
|
||||
usable = len;
|
||||
}
|
||||
}
|
||||
|
||||
if (usable) {
|
||||
devname[len] = '\0';
|
||||
}
|
||||
*name = devname;
|
||||
}
|
||||
|
||||
/* Uses the Device ID to get the spec */
|
||||
SDL_zerop(spec);
|
||||
|
||||
sampleRate = 0;
|
||||
size = sizeof(sampleRate);
|
||||
result = AudioObjectGetPropertyData(devid, &freqaddr, 0, NULL, &size, &sampleRate);
|
||||
|
||||
if (result != noErr) {
|
||||
return SDL_SetError("%s: Default Device Sample Rate not found", "coreaudio");
|
||||
}
|
||||
|
||||
spec->freq = (int) sampleRate;
|
||||
|
||||
result = AudioObjectGetPropertyDataSize(devid, &bufaddr, 0, NULL, &size);
|
||||
if (result != noErr)
|
||||
return SDL_SetError("%s: Default Device Data Size not found", "coreaudio");
|
||||
|
||||
buflist = (AudioBufferList *) SDL_malloc(size);
|
||||
if (buflist == NULL)
|
||||
return SDL_SetError("%s: Default Device Buffer List not found", "coreaudio");
|
||||
|
||||
result = AudioObjectGetPropertyData(devid, &bufaddr, 0, NULL,
|
||||
&size, buflist);
|
||||
|
||||
if (result == noErr) {
|
||||
UInt32 j;
|
||||
for (j = 0; j < buflist->mNumberBuffers; j++) {
|
||||
spec->channels += buflist->mBuffers[j].mNumberChannels;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(buflist);
|
||||
|
||||
if (spec->channels == 0) {
|
||||
return SDL_SetError("%s: Default Device has no channels!", "coreaudio");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MACOSX_COREAUDIO */
|
||||
|
||||
static void
|
||||
COREAUDIO_Deinitialize(void)
|
||||
{
|
||||
|
|
@ -1161,6 +1305,7 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->OpenDevice = COREAUDIO_OpenDevice;
|
||||
impl->CloseDevice = COREAUDIO_CloseDevice;
|
||||
impl->Deinitialize = COREAUDIO_Deinitialize;
|
||||
impl->GetDefaultAudioInfo = COREAUDIO_GetDefaultAudioInfo;
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
impl->DetectDevices = COREAUDIO_DetectDevices;
|
||||
|
|
@ -1172,6 +1317,7 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|||
|
||||
impl->ProvidesOwnCallbackThread = SDL_TRUE;
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->SupportsNonPow2Samples = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,11 +29,20 @@
|
|||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_directsound.h"
|
||||
#include <mmreg.h>
|
||||
#if HAVE_MMDEVICEAPI_H
|
||||
#include "../../core/windows/SDL_immdevice.h"
|
||||
#endif /* HAVE_MMDEVICEAPI_H */
|
||||
|
||||
#ifndef WAVE_FORMAT_IEEE_FLOAT
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
|
||||
#endif
|
||||
|
||||
/* For Vista+, we can enumerate DSound devices with IMMDevice */
|
||||
#if HAVE_MMDEVICEAPI_H
|
||||
static SDL_bool SupportsIMMDevice = SDL_FALSE;
|
||||
#endif /* HAVE_MMDEVICEAPI_H */
|
||||
|
||||
/* DirectX function pointers for audio */
|
||||
static void* DSoundDLL = NULL;
|
||||
typedef HRESULT (WINAPI *fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
|
||||
|
|
@ -45,6 +54,9 @@ static fnDirectSoundEnumerateW pDirectSoundEnumerateW = NULL;
|
|||
static fnDirectSoundCaptureCreate8 pDirectSoundCaptureCreate8 = NULL;
|
||||
static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL;
|
||||
|
||||
static const GUID SDL_KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
static const GUID SDL_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
|
||||
static void
|
||||
DSOUND_Unload(void)
|
||||
{
|
||||
|
|
@ -148,6 +160,17 @@ DSOUND_FreeDeviceHandle(void *handle)
|
|||
SDL_free(handle);
|
||||
}
|
||||
|
||||
static int
|
||||
DSOUND_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
|
||||
{
|
||||
#if HAVE_MMDEVICEAPI_H
|
||||
if (SupportsIMMDevice) {
|
||||
return SDL_IMMDevice_GetDefaultAudioInfo(name, spec, iscapture);
|
||||
}
|
||||
#endif /* HAVE_MMDEVICEAPI_H */
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
static BOOL CALLBACK
|
||||
FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
|
||||
{
|
||||
|
|
@ -172,8 +195,16 @@ FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
|
|||
static void
|
||||
DSOUND_DetectDevices(void)
|
||||
{
|
||||
pDirectSoundCaptureEnumerateW(FindAllDevs, (void *) ((size_t) 1));
|
||||
pDirectSoundEnumerateW(FindAllDevs, (void *) ((size_t) 0));
|
||||
#if HAVE_MMDEVICEAPI_H
|
||||
if (SupportsIMMDevice) {
|
||||
SDL_IMMDevice_EnumerateEndpoints(SDL_TRUE);
|
||||
} else {
|
||||
#endif /* HAVE_MMDEVICEAPI_H */
|
||||
pDirectSoundCaptureEnumerateW(FindAllDevs, (void *)((size_t)1));
|
||||
pDirectSoundEnumerateW(FindAllDevs, (void *)((size_t)0));
|
||||
#if HAVE_MMDEVICEAPI_H
|
||||
}
|
||||
#endif /* HAVE_MMDEVICEAPI_H*/
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -524,21 +555,56 @@ DSOUND_OpenDevice(_THIS, const char *devname)
|
|||
(int) (DSBSIZE_MAX / numchunks));
|
||||
} else {
|
||||
int rc;
|
||||
WAVEFORMATEX wfmt;
|
||||
WAVEFORMATEXTENSIBLE wfmt;
|
||||
SDL_zero(wfmt);
|
||||
if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
|
||||
wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
if (this->spec.channels > 2) {
|
||||
wfmt.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfmt.Format.cbSize = sizeof(wfmt) - sizeof(WAVEFORMATEX);
|
||||
|
||||
if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
|
||||
SDL_memcpy(&wfmt.SubFormat, &SDL_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID));
|
||||
} else {
|
||||
SDL_memcpy(&wfmt.SubFormat, &SDL_KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID));
|
||||
}
|
||||
wfmt.Samples.wValidBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
|
||||
switch (this->spec.channels)
|
||||
{
|
||||
case 3: /* 3.0 (or 2.1) */
|
||||
wfmt.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER;
|
||||
break;
|
||||
case 4: /* 4.0 */
|
||||
wfmt.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
break;
|
||||
case 5: /* 5.0 (or 4.1) */
|
||||
wfmt.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
break;
|
||||
case 6: /* 5.1 */
|
||||
wfmt.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
break;
|
||||
case 7: /* 6.1 */
|
||||
wfmt.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_BACK_CENTER;
|
||||
break;
|
||||
case 8: /* 7.1 */
|
||||
wfmt.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
|
||||
break;
|
||||
default:
|
||||
SDL_assert(0 && "Unsupported channel count!");
|
||||
break;
|
||||
}
|
||||
} else if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
|
||||
wfmt.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
} else {
|
||||
wfmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfmt.Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
}
|
||||
|
||||
wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
wfmt.nChannels = this->spec.channels;
|
||||
wfmt.nSamplesPerSec = this->spec.freq;
|
||||
wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
|
||||
wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
|
||||
wfmt.Format.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
wfmt.Format.nChannels = this->spec.channels;
|
||||
wfmt.Format.nSamplesPerSec = this->spec.freq;
|
||||
wfmt.Format.nBlockAlign = wfmt.Format.nChannels * (wfmt.Format.wBitsPerSample / 8);
|
||||
wfmt.Format.nAvgBytesPerSec = wfmt.Format.nSamplesPerSec * wfmt.Format.nBlockAlign;
|
||||
|
||||
rc = iscapture ? CreateCaptureBuffer(this, bufsize, &wfmt) : CreateSecondary(this, bufsize, &wfmt);
|
||||
rc = iscapture ? CreateCaptureBuffer(this, bufsize, (WAVEFORMATEX*) &wfmt) : CreateSecondary(this, bufsize, (WAVEFORMATEX*) &wfmt);
|
||||
if (rc == 0) {
|
||||
this->hidden->num_buffers = numchunks;
|
||||
break;
|
||||
|
|
@ -567,6 +633,12 @@ DSOUND_OpenDevice(_THIS, const char *devname)
|
|||
static void
|
||||
DSOUND_Deinitialize(void)
|
||||
{
|
||||
#if HAVE_MMDEVICEAPI_H
|
||||
if (SupportsIMMDevice) {
|
||||
SDL_IMMDevice_Quit();
|
||||
SupportsIMMDevice = SDL_FALSE;
|
||||
}
|
||||
#endif /* HAVE_MMDEVICEAPI_H */
|
||||
DSOUND_Unload();
|
||||
}
|
||||
|
||||
|
|
@ -578,6 +650,10 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
|
|||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#if HAVE_MMDEVICEAPI_H
|
||||
SupportsIMMDevice = !(SDL_IMMDevice_Init() < 0);
|
||||
#endif /* HAVE_MMDEVICEAPI_H */
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = DSOUND_DetectDevices;
|
||||
impl->OpenDevice = DSOUND_OpenDevice;
|
||||
|
|
@ -589,8 +665,10 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->CloseDevice = DSOUND_CloseDevice;
|
||||
impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
|
||||
impl->Deinitialize = DSOUND_Deinitialize;
|
||||
impl->GetDefaultAudioInfo = DSOUND_GetDefaultAudioInfo;
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->SupportsNonPow2Samples = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -195,6 +195,7 @@ DISKAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|||
|
||||
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->SupportsNonPow2Samples = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,13 +34,7 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
|
||||
/* This is installed on some systems */
|
||||
#include <soundcard.h>
|
||||
#else
|
||||
/* This is recommended by OSS */
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
|
|||
363
Engine/lib/sdl/src/audio/n3ds/SDL_n3dsaudio.c
Normal file
363
Engine/lib/sdl/src/audio/n3ds/SDL_n3dsaudio.c
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 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"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_N3DS
|
||||
|
||||
#include "SDL_audio.h"
|
||||
|
||||
/* N3DS Audio driver */
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_n3dsaudio.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#define N3DSAUDIO_DRIVER_NAME "n3ds"
|
||||
|
||||
static dspHookCookie dsp_hook;
|
||||
static SDL_AudioDevice *audio_device;
|
||||
|
||||
static void FreePrivateData(_THIS);
|
||||
static int FindAudioFormat(_THIS);
|
||||
|
||||
static SDL_INLINE void
|
||||
contextLock(_THIS)
|
||||
{
|
||||
LightLock_Lock(&this->hidden->lock);
|
||||
}
|
||||
|
||||
static SDL_INLINE void
|
||||
contextUnlock(_THIS)
|
||||
{
|
||||
LightLock_Unlock(&this->hidden->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
N3DSAUD_LockAudio(_THIS)
|
||||
{
|
||||
contextLock(this);
|
||||
}
|
||||
|
||||
static void
|
||||
N3DSAUD_UnlockAudio(_THIS)
|
||||
{
|
||||
contextUnlock(this);
|
||||
}
|
||||
|
||||
static void
|
||||
N3DSAUD_DspHook(DSP_HookType hook)
|
||||
{
|
||||
if (hook == DSPHOOK_ONCANCEL) {
|
||||
contextLock(audio_device);
|
||||
audio_device->hidden->isCancelled = SDL_TRUE;
|
||||
SDL_AtomicSet(&audio_device->enabled, SDL_FALSE);
|
||||
CondVar_Broadcast(&audio_device->hidden->cv);
|
||||
contextUnlock(audio_device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AudioFrameFinished(void *device)
|
||||
{
|
||||
bool shouldBroadcast = false;
|
||||
unsigned i;
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) device;
|
||||
|
||||
contextLock(this);
|
||||
|
||||
for (i = 0; i < NUM_BUFFERS; i++) {
|
||||
if (this->hidden->waveBuf[i].status == NDSP_WBUF_DONE) {
|
||||
this->hidden->waveBuf[i].status = NDSP_WBUF_FREE;
|
||||
shouldBroadcast = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldBroadcast) {
|
||||
CondVar_Broadcast(&this->hidden->cv);
|
||||
}
|
||||
|
||||
contextUnlock(this);
|
||||
}
|
||||
|
||||
static int
|
||||
N3DSAUDIO_OpenDevice(_THIS, const char *devname)
|
||||
{
|
||||
Result ndsp_init_res;
|
||||
Uint8 *data_vaddr;
|
||||
float mix[12];
|
||||
this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof *this->hidden);
|
||||
|
||||
if (this->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
/* Initialise the DSP service */
|
||||
ndsp_init_res = ndspInit();
|
||||
if (R_FAILED(ndsp_init_res)) {
|
||||
if ((R_SUMMARY(ndsp_init_res) == RS_NOTFOUND) && (R_MODULE(ndsp_init_res) == RM_DSP)) {
|
||||
SDL_SetError("DSP init failed: dspfirm.cdc missing!");
|
||||
} else {
|
||||
SDL_SetError("DSP init failed. Error code: 0x%lX", ndsp_init_res);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialise internal state */
|
||||
LightLock_Init(&this->hidden->lock);
|
||||
CondVar_Init(&this->hidden->cv);
|
||||
|
||||
if (this->spec.channels > 2) {
|
||||
this->spec.channels = 2;
|
||||
}
|
||||
|
||||
/* Should not happen but better be safe. */
|
||||
if (FindAudioFormat(this) < 0) {
|
||||
return SDL_SetError("No supported audio format found.");
|
||||
}
|
||||
|
||||
/* Update the fragment size as size in bytes */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
if (this->spec.size >= SDL_MAX_UINT32 / 2) {
|
||||
return SDL_SetError("Mixing buffer is too large.");
|
||||
}
|
||||
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
data_vaddr = (Uint8 *) linearAlloc(this->hidden->mixlen * NUM_BUFFERS);
|
||||
if (data_vaddr == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
SDL_memset(data_vaddr, 0, this->hidden->mixlen * NUM_BUFFERS);
|
||||
DSP_FlushDataCache(data_vaddr, this->hidden->mixlen * NUM_BUFFERS);
|
||||
|
||||
this->hidden->nextbuf = 0;
|
||||
this->hidden->channels = this->spec.channels;
|
||||
this->hidden->samplerate = this->spec.freq;
|
||||
|
||||
ndspChnReset(0);
|
||||
|
||||
ndspChnSetInterp(0, NDSP_INTERP_LINEAR);
|
||||
ndspChnSetRate(0, this->spec.freq);
|
||||
ndspChnSetFormat(0, this->hidden->format);
|
||||
|
||||
SDL_memset(mix, 0, sizeof(mix));
|
||||
mix[0] = 1.0;
|
||||
mix[1] = 1.0;
|
||||
ndspChnSetMix(0, mix);
|
||||
|
||||
SDL_memset(this->hidden->waveBuf, 0, sizeof(ndspWaveBuf) * NUM_BUFFERS);
|
||||
|
||||
for (unsigned i = 0; i < NUM_BUFFERS; i++) {
|
||||
this->hidden->waveBuf[i].data_vaddr = data_vaddr;
|
||||
this->hidden->waveBuf[i].nsamples = this->hidden->mixlen / this->hidden->bytePerSample;
|
||||
data_vaddr += this->hidden->mixlen;
|
||||
}
|
||||
|
||||
/* Setup callback */
|
||||
audio_device = this;
|
||||
ndspSetCallback(AudioFrameFinished, this);
|
||||
dspHook(&dsp_hook, N3DSAUD_DspHook);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
N3DSAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
|
||||
{
|
||||
/* Delay to make this sort of simulate real audio input. */
|
||||
SDL_Delay((this->spec.samples * 1000) / this->spec.freq);
|
||||
|
||||
/* always return a full buffer of silence. */
|
||||
SDL_memset(buffer, this->spec.silence, buflen);
|
||||
return buflen;
|
||||
}
|
||||
|
||||
static void
|
||||
N3DSAUDIO_PlayDevice(_THIS)
|
||||
{
|
||||
size_t nextbuf;
|
||||
size_t sampleLen;
|
||||
contextLock(this);
|
||||
|
||||
nextbuf = this->hidden->nextbuf;
|
||||
sampleLen = this->hidden->mixlen;
|
||||
|
||||
if (this->hidden->isCancelled ||
|
||||
this->hidden->waveBuf[nextbuf].status != NDSP_WBUF_FREE) {
|
||||
contextUnlock(this);
|
||||
return;
|
||||
}
|
||||
|
||||
this->hidden->nextbuf = (nextbuf + 1) % NUM_BUFFERS;
|
||||
|
||||
contextUnlock(this);
|
||||
|
||||
memcpy((void *) this->hidden->waveBuf[nextbuf].data_vaddr,
|
||||
this->hidden->mixbuf, sampleLen);
|
||||
DSP_FlushDataCache(this->hidden->waveBuf[nextbuf].data_vaddr, sampleLen);
|
||||
|
||||
ndspChnWaveBufAdd(0, &this->hidden->waveBuf[nextbuf]);
|
||||
}
|
||||
|
||||
static void
|
||||
N3DSAUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
contextLock(this);
|
||||
while (!this->hidden->isCancelled &&
|
||||
this->hidden->waveBuf[this->hidden->nextbuf].status != NDSP_WBUF_FREE) {
|
||||
CondVar_Wait(&this->hidden->cv, &this->hidden->lock);
|
||||
}
|
||||
contextUnlock(this);
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
N3DSAUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return this->hidden->mixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
N3DSAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
contextLock(this);
|
||||
|
||||
dspUnhook(&dsp_hook);
|
||||
ndspSetCallback(NULL, NULL);
|
||||
|
||||
if (!this->hidden->isCancelled) {
|
||||
ndspChnReset(0);
|
||||
memset(this->hidden->waveBuf, 0, sizeof(ndspWaveBuf) * NUM_BUFFERS);
|
||||
CondVar_Broadcast(&this->hidden->cv);
|
||||
}
|
||||
|
||||
contextUnlock(this);
|
||||
|
||||
ndspExit();
|
||||
|
||||
FreePrivateData(this);
|
||||
}
|
||||
|
||||
static void
|
||||
N3DSAUDIO_ThreadInit(_THIS)
|
||||
{
|
||||
s32 current_priority;
|
||||
svcGetThreadPriority(¤t_priority, CUR_THREAD_HANDLE);
|
||||
current_priority--;
|
||||
/* 0x18 is reserved for video, 0x30 is the default for main thread */
|
||||
current_priority = SDL_clamp(current_priority, 0x19, 0x2F);
|
||||
svcSetThreadPriority(CUR_THREAD_HANDLE, current_priority);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
N3DSAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = N3DSAUDIO_OpenDevice;
|
||||
impl->PlayDevice = N3DSAUDIO_PlayDevice;
|
||||
impl->WaitDevice = N3DSAUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = N3DSAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = N3DSAUDIO_CloseDevice;
|
||||
impl->ThreadInit = N3DSAUDIO_ThreadInit;
|
||||
impl->LockDevice = N3DSAUD_LockAudio;
|
||||
impl->UnlockDevice = N3DSAUD_UnlockAudio;
|
||||
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
|
||||
|
||||
/* Should be possible, but micInit would fail */
|
||||
impl->HasCaptureSupport = SDL_FALSE;
|
||||
impl->CaptureFromDevice = N3DSAUDIO_CaptureFromDevice;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap N3DSAUDIO_bootstrap = {
|
||||
N3DSAUDIO_DRIVER_NAME,
|
||||
"SDL N3DS audio driver",
|
||||
N3DSAUDIO_Init,
|
||||
0
|
||||
};
|
||||
|
||||
/**
|
||||
* Cleans up all allocated memory, safe to call with null pointers
|
||||
*/
|
||||
static void
|
||||
FreePrivateData(_THIS)
|
||||
{
|
||||
if (!this->hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->hidden->waveBuf[0].data_vaddr) {
|
||||
linearFree((void *) this->hidden->waveBuf[0].data_vaddr);
|
||||
}
|
||||
|
||||
if (this->hidden->mixbuf) {
|
||||
SDL_free(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
FindAudioFormat(_THIS)
|
||||
{
|
||||
SDL_bool found_valid_format = SDL_FALSE;
|
||||
Uint16 test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
|
||||
while (!found_valid_format && test_format) {
|
||||
this->spec.format = test_format;
|
||||
switch (test_format) {
|
||||
case AUDIO_S8:
|
||||
/* Signed 8-bit audio supported */
|
||||
this->hidden->format = (this->spec.channels == 2) ? NDSP_FORMAT_STEREO_PCM8 : NDSP_FORMAT_MONO_PCM8;
|
||||
this->hidden->isSigned = 1;
|
||||
this->hidden->bytePerSample = this->spec.channels;
|
||||
found_valid_format = SDL_TRUE;
|
||||
break;
|
||||
case AUDIO_S16:
|
||||
/* Signed 16-bit audio supported */
|
||||
this->hidden->format = (this->spec.channels == 2) ? NDSP_FORMAT_STEREO_PCM16 : NDSP_FORMAT_MONO_PCM16;
|
||||
this->hidden->isSigned = 1;
|
||||
this->hidden->bytePerSample = this->spec.channels * 2;
|
||||
found_valid_format = SDL_TRUE;
|
||||
break;
|
||||
default:
|
||||
test_format = SDL_NextAudioFormat();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found_valid_format ? 0 : -1;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_N3DS */
|
||||
|
||||
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
||||
50
Engine/lib/sdl/src/audio/n3ds/SDL_n3dsaudio.h
Normal file
50
Engine/lib/sdl/src/audio/n3ds/SDL_n3dsaudio.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 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_n3dsaudio_h_
|
||||
#define _SDL_n3dsaudio_h_
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
#define NUM_BUFFERS 2 /* -- Don't lower this! */
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* Speaker data */
|
||||
Uint8 *mixbuf;
|
||||
Uint32 mixlen;
|
||||
Uint32 format;
|
||||
Uint32 samplerate;
|
||||
Uint32 channels;
|
||||
Uint8 bytePerSample;
|
||||
Uint32 isSigned;
|
||||
Uint32 nextbuf;
|
||||
ndspWaveBuf waveBuf[NUM_BUFFERS];
|
||||
LightLock lock;
|
||||
CondVar cv;
|
||||
SDL_bool isCancelled;
|
||||
};
|
||||
|
||||
#endif /* _SDL_n3dsaudio_h_ */
|
||||
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -131,6 +131,8 @@ static void openslES_DestroyEngine(void)
|
|||
static int
|
||||
openslES_CreateEngine(void)
|
||||
{
|
||||
const SLInterfaceID ids[1] = { SL_IID_VOLUME };
|
||||
const SLboolean req[1] = { SL_BOOLEAN_FALSE };
|
||||
SLresult result;
|
||||
|
||||
LOGI("openSLES_CreateEngine()");
|
||||
|
|
@ -160,8 +162,6 @@ openslES_CreateEngine(void)
|
|||
LOGI("EngineGetInterface OK");
|
||||
|
||||
/* create output mix */
|
||||
const SLInterfaceID ids[1] = { SL_IID_VOLUME };
|
||||
const SLboolean req[1] = { SL_BOOLEAN_FALSE };
|
||||
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("CreateOutputMix failed: %d", result);
|
||||
|
|
@ -229,6 +229,12 @@ openslES_CreatePCMRecorder(_THIS)
|
|||
{
|
||||
struct SDL_PrivateAudioData *audiodata = this->hidden;
|
||||
SLDataFormat_PCM format_pcm;
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
|
||||
SLDataSink audioSnk;
|
||||
SLDataLocator_IODevice loc_dev;
|
||||
SLDataSource audioSrc;
|
||||
const SLInterfaceID ids[1] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE };
|
||||
const SLboolean req[1] = { SL_BOOLEAN_TRUE };
|
||||
SLresult result;
|
||||
int i;
|
||||
|
||||
|
|
@ -250,11 +256,16 @@ openslES_CreatePCMRecorder(_THIS)
|
|||
this->spec.channels, (this->spec.format & 0x1000) ? "BE" : "LE", this->spec.samples);
|
||||
|
||||
/* configure audio source */
|
||||
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
|
||||
SLDataSource audioSrc = {&loc_dev, NULL};
|
||||
loc_dev.locatorType = SL_DATALOCATOR_IODEVICE;
|
||||
loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT;
|
||||
loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
|
||||
loc_dev.device = NULL;
|
||||
audioSrc.pLocator = &loc_dev;
|
||||
audioSrc.pFormat = NULL;
|
||||
|
||||
/* configure audio sink */
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
|
||||
loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
|
||||
loc_bufq.numBuffers = NUM_BUFFERS;
|
||||
|
||||
format_pcm.formatType = SL_DATAFORMAT_PCM;
|
||||
format_pcm.numChannels = this->spec.channels;
|
||||
|
|
@ -264,17 +275,11 @@ openslES_CreatePCMRecorder(_THIS)
|
|||
format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
|
||||
format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
|
||||
|
||||
SLDataSink audioSnk = { &loc_bufq, &format_pcm };
|
||||
audioSnk.pLocator = &loc_bufq;
|
||||
audioSnk.pFormat = &format_pcm;
|
||||
|
||||
/* create audio recorder */
|
||||
/* (requires the RECORD_AUDIO permission) */
|
||||
const SLInterfaceID ids[1] = {
|
||||
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
};
|
||||
const SLboolean req[1] = {
|
||||
SL_BOOLEAN_TRUE,
|
||||
};
|
||||
|
||||
result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc, &audioSnk, 1, ids, req);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("CreateAudioRecorder failed: %d", result);
|
||||
|
|
@ -354,7 +359,6 @@ openslES_CreatePCMRecorder(_THIS)
|
|||
return 0;
|
||||
|
||||
failed:
|
||||
|
||||
return SDL_SetError("Open device failed!");
|
||||
}
|
||||
|
||||
|
|
@ -384,7 +388,6 @@ openslES_DestroyPCMPlayer(_THIS)
|
|||
|
||||
/* destroy buffer queue audio player object, and invalidate all associated interfaces */
|
||||
if (bqPlayerObject != NULL) {
|
||||
|
||||
(*bqPlayerObject)->Destroy(bqPlayerObject);
|
||||
|
||||
bqPlayerObject = NULL;
|
||||
|
|
@ -406,8 +409,14 @@ static int
|
|||
openslES_CreatePCMPlayer(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = this->hidden;
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
|
||||
SLDataFormat_PCM format_pcm;
|
||||
SLAndroidDataFormat_PCM_EX format_pcm_ex;
|
||||
SLDataSource audioSrc;
|
||||
SLDataSink audioSnk;
|
||||
SLDataLocator_OutputMix loc_outmix;
|
||||
const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME };
|
||||
const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE };
|
||||
SLresult result;
|
||||
int i;
|
||||
|
||||
|
|
@ -442,7 +451,8 @@ openslES_CreatePCMPlayer(_THIS)
|
|||
this->spec.channels, (this->spec.format & 0x1000) ? "BE" : "LE", this->spec.samples);
|
||||
|
||||
/* configure audio source */
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
|
||||
loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
|
||||
loc_bufq.numBuffers = NUM_BUFFERS;
|
||||
|
||||
format_pcm.formatType = SL_DATAFORMAT_PCM;
|
||||
format_pcm.numChannels = this->spec.channels;
|
||||
|
|
@ -501,23 +511,16 @@ openslES_CreatePCMPlayer(_THIS)
|
|||
format_pcm_ex.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
|
||||
}
|
||||
|
||||
SLDataSource audioSrc = { &loc_bufq, SDL_AUDIO_ISFLOAT(this->spec.format) ? (void*)&format_pcm_ex : (void*)&format_pcm };
|
||||
audioSrc.pLocator = &loc_bufq;
|
||||
audioSrc.pFormat = SDL_AUDIO_ISFLOAT(this->spec.format) ? (void*)&format_pcm_ex : (void*)&format_pcm;
|
||||
|
||||
/* configure audio sink */
|
||||
SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
|
||||
SLDataSink audioSnk = { &loc_outmix, NULL };
|
||||
loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
|
||||
loc_outmix.outputMix = outputMixObject;
|
||||
audioSnk.pLocator = &loc_outmix;
|
||||
audioSnk.pFormat = NULL;
|
||||
|
||||
/* create audio player */
|
||||
const SLInterfaceID ids[2] = {
|
||||
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
SL_IID_VOLUME
|
||||
};
|
||||
|
||||
const SLboolean req[2] = {
|
||||
SL_BOOLEAN_TRUE,
|
||||
SL_BOOLEAN_FALSE,
|
||||
};
|
||||
|
||||
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("CreateAudioPlayer failed: %d", result);
|
||||
|
|
@ -590,7 +593,6 @@ openslES_CreatePCMPlayer(_THIS)
|
|||
return 0;
|
||||
|
||||
failed:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -477,7 +477,7 @@ PAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|||
/* Set the function pointers */
|
||||
impl->OpenDevice = PAUDIO_OpenDevice;
|
||||
impl->PlayDevice = PAUDIO_PlayDevice;
|
||||
impl->PlayDevice = PAUDIO_WaitDevice;
|
||||
impl->WaitDevice = PAUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = PAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = PAUDIO_CloseDevice;
|
||||
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; /* !!! FIXME: add device enum! */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,11 +30,12 @@
|
|||
|
||||
#include <pipewire/extensions/metadata.h>
|
||||
#include <spa/param/audio/format-utils.h>
|
||||
#include <spa/utils/json.h>
|
||||
|
||||
/*
|
||||
* The following keys are defined for compatability when building against older versions of Pipewire
|
||||
* prior to their introduction and can be removed if the minimum required Pipewire version is increased
|
||||
* to or beyond their point of introduction.
|
||||
* prior to their introduction and can be removed if the minimum required Pipewire build version is
|
||||
* increased to or beyond their point of introduction.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -53,6 +54,14 @@
|
|||
#define PW_KEY_NODE_RATE "node.rate"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Introduced in 0.3.44
|
||||
* Taken from src/pipewire/keys.h
|
||||
*/
|
||||
#ifndef PW_KEY_TARGET_OBJECT
|
||||
#define PW_KEY_TARGET_OBJECT "target.object"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This seems to be a sane lower limit as Pipewire
|
||||
* uses it in several of it's own modules.
|
||||
|
|
@ -62,6 +71,7 @@
|
|||
|
||||
#define PW_POD_BUFFER_LENGTH 1024
|
||||
#define PW_THREAD_NAME_BUFFER_LENGTH 128
|
||||
#define PW_MAX_IDENTIFIER_LENGTH 256
|
||||
|
||||
enum PW_READY_FLAGS
|
||||
{
|
||||
|
|
@ -76,7 +86,8 @@ enum PW_READY_FLAGS
|
|||
static SDL_bool pipewire_initialized = SDL_FALSE;
|
||||
|
||||
/* Pipewire entry points */
|
||||
static void (*PIPEWIRE_pw_init)(int *, char **);
|
||||
static const char *(*PIPEWIRE_pw_get_library_version)(void);
|
||||
static void (*PIPEWIRE_pw_init)(int *, char ***);
|
||||
static void (*PIPEWIRE_pw_deinit)(void);
|
||||
static struct pw_thread_loop *(*PIPEWIRE_pw_thread_loop_new)(const char *, const struct spa_dict *);
|
||||
static void (*PIPEWIRE_pw_thread_loop_destroy)(struct pw_thread_loop *);
|
||||
|
|
@ -106,6 +117,10 @@ static struct pw_properties *(*PIPEWIRE_pw_properties_new)(const char *, ...)SPA
|
|||
static int (*PIPEWIRE_pw_properties_set)(struct pw_properties *, const char *, const char *);
|
||||
static int (*PIPEWIRE_pw_properties_setf)(struct pw_properties *, const char *, const char *, ...) SPA_PRINTF_FUNC(3, 4);
|
||||
|
||||
static int pipewire_version_major;
|
||||
static int pipewire_version_minor;
|
||||
static int pipewire_version_patch;
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC
|
||||
|
||||
static const char *pipewire_library = SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC;
|
||||
|
|
@ -167,6 +182,7 @@ unload_pipewire_library()
|
|||
static int
|
||||
load_pipewire_syms()
|
||||
{
|
||||
SDL_PIPEWIRE_SYM(pw_get_library_version);
|
||||
SDL_PIPEWIRE_SYM(pw_init);
|
||||
SDL_PIPEWIRE_SYM(pw_deinit);
|
||||
SDL_PIPEWIRE_SYM(pw_thread_loop_new);
|
||||
|
|
@ -198,13 +214,31 @@ load_pipewire_syms()
|
|||
return 0;
|
||||
}
|
||||
|
||||
SDL_FORCE_INLINE SDL_bool
|
||||
pipewire_version_at_least(int major, int minor, int patch)
|
||||
{
|
||||
return (pipewire_version_major >= major) &&
|
||||
(pipewire_version_major > major || pipewire_version_minor >= minor) &&
|
||||
(pipewire_version_major > major || pipewire_version_minor > minor || pipewire_version_patch >= patch);
|
||||
}
|
||||
|
||||
static int
|
||||
init_pipewire_library()
|
||||
{
|
||||
if (!load_pipewire_library()) {
|
||||
if (!load_pipewire_syms()) {
|
||||
PIPEWIRE_pw_init(NULL, NULL);
|
||||
return 0;
|
||||
int nargs;
|
||||
const char *version = PIPEWIRE_pw_get_library_version();
|
||||
nargs = SDL_sscanf(version, "%d.%d.%d", &pipewire_version_major, &pipewire_version_minor, &pipewire_version_patch);
|
||||
if (nargs < 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -223,8 +257,9 @@ struct node_object
|
|||
{
|
||||
struct spa_list link;
|
||||
|
||||
Uint32 id;
|
||||
int seq;
|
||||
Uint32 id;
|
||||
int seq;
|
||||
SDL_bool persist;
|
||||
|
||||
/*
|
||||
* NOTE: If used, this is *must* be allocated with SDL_malloc() or similar
|
||||
|
|
@ -249,7 +284,10 @@ struct io_node
|
|||
SDL_bool is_capture;
|
||||
SDL_AudioSpec spec;
|
||||
|
||||
char name[];
|
||||
const char *name; /* Friendly name */
|
||||
const char *path; /* OS identifier (i.e. ALSA endpoint) */
|
||||
|
||||
char buf[]; /* Buffer to hold the name and path strings. */
|
||||
};
|
||||
|
||||
/* The global hotplug thread and associated objects. */
|
||||
|
|
@ -265,8 +303,8 @@ static int hotplug_init_seq_val;
|
|||
static SDL_bool hotplug_init_complete;
|
||||
static SDL_bool hotplug_events_enabled;
|
||||
|
||||
static Uint32 pipewire_default_sink_id = SPA_ID_INVALID;
|
||||
static Uint32 pipewire_default_source_id = SPA_ID_INVALID;
|
||||
static char *pipewire_default_sink_id = NULL;
|
||||
static char *pipewire_default_source_id = NULL;
|
||||
|
||||
/* The active node list */
|
||||
static SDL_bool
|
||||
|
|
@ -324,10 +362,10 @@ io_list_sort()
|
|||
|
||||
/* Find and move the default nodes to the beginning of the list */
|
||||
spa_list_for_each_safe (n, temp, &hotplug_io_list, link) {
|
||||
if (n->id == pipewire_default_sink_id) {
|
||||
if (pipewire_default_sink_id != NULL && SDL_strcmp(n->path, pipewire_default_sink_id) == 0) {
|
||||
default_sink = n;
|
||||
spa_list_remove(&n->link);
|
||||
} else if (n->id == pipewire_default_source_id) {
|
||||
} else if (pipewire_default_source_id != NULL && SDL_strcmp(n->path, pipewire_default_source_id) == 0) {
|
||||
default_source = n;
|
||||
spa_list_remove(&n->link);
|
||||
}
|
||||
|
|
@ -353,6 +391,30 @@ io_list_clear()
|
|||
}
|
||||
}
|
||||
|
||||
static struct io_node*
|
||||
io_list_get_by_id(Uint32 id)
|
||||
{
|
||||
struct io_node *n, *temp;
|
||||
spa_list_for_each_safe (n, temp, &hotplug_io_list, link) {
|
||||
if (n->id == id) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct io_node*
|
||||
io_list_get_by_path(char *path)
|
||||
{
|
||||
struct io_node *n, *temp;
|
||||
spa_list_for_each_safe (n, temp, &hotplug_io_list, link) {
|
||||
if (SDL_strcmp(n->path, path) == 0) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
node_object_destroy(struct node_object *node)
|
||||
{
|
||||
|
|
@ -462,7 +524,7 @@ core_events_metadata_callback(void *object, uint32_t id, int seq)
|
|||
{
|
||||
struct node_object *node = object;
|
||||
|
||||
if (id == PW_ID_CORE && seq == node->seq) {
|
||||
if (id == PW_ID_CORE && seq == node->seq && !node->persist) {
|
||||
node_object_destroy(node);
|
||||
}
|
||||
}
|
||||
|
|
@ -591,17 +653,47 @@ node_event_param(void *object, int seq, uint32_t id, uint32_t index, uint32_t ne
|
|||
static const struct pw_node_events interface_node_events = { PW_VERSION_NODE_EVENTS, .info = node_event_info,
|
||||
.param = node_event_param };
|
||||
|
||||
static char*
|
||||
get_name_from_json(const char *json)
|
||||
{
|
||||
struct spa_json parser[2];
|
||||
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 */
|
||||
return NULL;
|
||||
}
|
||||
if (spa_json_get_string(&parser[1], key, sizeof(key)) <= 0) {
|
||||
/* 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? */
|
||||
return NULL;
|
||||
}
|
||||
return SDL_strdup(value);
|
||||
}
|
||||
|
||||
/* Metadata node callback */
|
||||
static int
|
||||
metadata_property(void *object, Uint32 subject, const char *key, const char *type, const char *value)
|
||||
{
|
||||
if (subject == PW_ID_CORE && key != NULL && value != NULL) {
|
||||
Uint32 val = SDL_atoi(value);
|
||||
struct node_object *node = object;
|
||||
|
||||
if (subject == PW_ID_CORE && key != NULL && value != NULL) {
|
||||
if (!SDL_strcmp(key, "default.audio.sink")) {
|
||||
pipewire_default_sink_id = val;
|
||||
if (pipewire_default_sink_id != NULL) {
|
||||
SDL_free(pipewire_default_sink_id);
|
||||
}
|
||||
pipewire_default_sink_id = get_name_from_json(value);
|
||||
node->persist = SDL_TRUE;
|
||||
} else if (!SDL_strcmp(key, "default.audio.source")) {
|
||||
pipewire_default_source_id = val;
|
||||
if (pipewire_default_source_id != NULL) {
|
||||
SDL_free(pipewire_default_source_id);
|
||||
}
|
||||
pipewire_default_source_id = get_name_from_json(value);
|
||||
node->persist = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -623,9 +715,11 @@ registry_event_global_callback(void *object, uint32_t id, uint32_t permissions,
|
|||
|
||||
if (media_class) {
|
||||
const char *node_desc;
|
||||
const char *node_path;
|
||||
struct io_node *io;
|
||||
SDL_bool is_capture;
|
||||
int str_buffer_len;
|
||||
int desc_buffer_len;
|
||||
int path_buffer_len;
|
||||
|
||||
/* Just want sink and capture */
|
||||
if (!SDL_strcasecmp(media_class, "Audio/Sink")) {
|
||||
|
|
@ -637,8 +731,9 @@ registry_event_global_callback(void *object, uint32_t id, uint32_t permissions,
|
|||
}
|
||||
|
||||
node_desc = spa_dict_lookup(props, PW_KEY_NODE_DESCRIPTION);
|
||||
node_path = spa_dict_lookup(props, PW_KEY_NODE_NAME);
|
||||
|
||||
if (node_desc) {
|
||||
if (node_desc && node_path) {
|
||||
node = node_object_new(id, type, version, &interface_node_events, &interface_core_events);
|
||||
if (node == NULL) {
|
||||
SDL_SetError("Pipewire: Failed to allocate interface node");
|
||||
|
|
@ -646,8 +741,9 @@ registry_event_global_callback(void *object, uint32_t id, uint32_t permissions,
|
|||
}
|
||||
|
||||
/* Allocate and initialize the I/O node information struct */
|
||||
str_buffer_len = SDL_strlen(node_desc) + 1;
|
||||
node->userdata = io = SDL_calloc(1, sizeof(struct io_node) + str_buffer_len);
|
||||
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) {
|
||||
node_object_destroy(node);
|
||||
SDL_OutOfMemory();
|
||||
|
|
@ -658,7 +754,10 @@ registry_event_global_callback(void *object, uint32_t id, uint32_t permissions,
|
|||
io->id = id;
|
||||
io->is_capture = is_capture;
|
||||
io->spec.format = AUDIO_F32; /* Pipewire uses floats internally, other formats require conversion. */
|
||||
SDL_strlcpy(io->name, node_desc, str_buffer_len);
|
||||
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 */
|
||||
hotplug_core_sync(node);
|
||||
|
|
@ -744,8 +843,14 @@ hotplug_loop_destroy()
|
|||
hotplug_init_complete = SDL_FALSE;
|
||||
hotplug_events_enabled = SDL_FALSE;
|
||||
|
||||
pipewire_default_sink_id = SPA_ID_INVALID;
|
||||
pipewire_default_source_id = SPA_ID_INVALID;
|
||||
if (pipewire_default_sink_id != NULL) {
|
||||
SDL_free(pipewire_default_sink_id);
|
||||
pipewire_default_sink_id = NULL;
|
||||
}
|
||||
if (pipewire_default_source_id != NULL) {
|
||||
SDL_free(pipewire_default_source_id);
|
||||
pipewire_default_source_id = NULL;
|
||||
}
|
||||
|
||||
if (hotplug_registry) {
|
||||
PIPEWIRE_pw_proxy_destroy((struct pw_proxy *)hotplug_registry);
|
||||
|
|
@ -1075,7 +1180,7 @@ PIPEWIRE_OpenDevice(_THIS, const char *devname)
|
|||
struct SDL_PrivateAudioData *priv;
|
||||
struct pw_properties *props;
|
||||
const char *app_name, *stream_name, *stream_role, *error;
|
||||
const Uint32 node_id = this->handle == NULL ? PW_ID_ANY : PW_HANDLE_TO_ID(this->handle);
|
||||
Uint32 node_id = this->handle == NULL ? PW_ID_ANY : PW_HANDLE_TO_ID(this->handle);
|
||||
SDL_bool iscapture = this->iscapture;
|
||||
int res;
|
||||
|
||||
|
|
@ -1130,17 +1235,8 @@ PIPEWIRE_OpenDevice(_THIS, const char *devname)
|
|||
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.
|
||||
*
|
||||
* NOTE: Pipewire versions 0.3.22 or higher require the PW_KEY_CONFIG_NAME property (with client-rt.conf),
|
||||
* lower versions require explicitly specifying the 'rtkit' module.
|
||||
*
|
||||
* PW_KEY_CONTEXT_PROFILE_MODULES is deprecated and can be safely removed if the minimum required
|
||||
* Pipewire version is increased to 0.3.22 or higher at some point.
|
||||
*/
|
||||
props = PIPEWIRE_pw_properties_new(PW_KEY_CONFIG_NAME, "client-rt.conf",
|
||||
PW_KEY_CONTEXT_PROFILE_MODULES, "default,rtkit", NULL);
|
||||
/* 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) {
|
||||
return SDL_SetError("Pipewire: Failed to create stream context properties (%i)", errno);
|
||||
}
|
||||
|
|
@ -1165,6 +1261,26 @@ PIPEWIRE_OpenDevice(_THIS, const char *devname)
|
|||
PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", this->spec.freq);
|
||||
PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true");
|
||||
|
||||
/*
|
||||
* Pipewire 0.3.44 introduced PW_KEY_TARGET_OBJECT that takes either a path
|
||||
* (PW_KEY_NODE_NAME) or node serial number (PE_KEY_OBJECT_SERIAL) to connect
|
||||
* the stream to its target. The target_id parameter in pw_stream_connect() is
|
||||
* now deprecated and should always be PW_ID_ANY.
|
||||
*/
|
||||
if (pipewire_version_at_least(0, 3, 44)) {
|
||||
if (node_id != PW_ID_ANY) {
|
||||
const struct io_node *node;
|
||||
|
||||
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
|
||||
if ((node = io_list_get_by_id(node_id))) {
|
||||
PIPEWIRE_pw_properties_set(props, PW_KEY_TARGET_OBJECT, node->path);
|
||||
}
|
||||
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
|
||||
|
||||
node_id = PW_ID_ANY;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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, this);
|
||||
|
|
@ -1228,6 +1344,45 @@ static void PIPEWIRE_CloseDevice(_THIS)
|
|||
SDL_free(this->hidden);
|
||||
}
|
||||
|
||||
static int
|
||||
PIPEWIRE_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
|
||||
{
|
||||
struct io_node *node;
|
||||
char *target;
|
||||
int ret = 0;
|
||||
|
||||
PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
|
||||
|
||||
if (iscapture) {
|
||||
if (pipewire_default_source_id == NULL) {
|
||||
ret = SDL_SetError("PipeWire could not find a default source");
|
||||
goto failed;
|
||||
}
|
||||
target = pipewire_default_source_id;
|
||||
} else {
|
||||
if (pipewire_default_sink_id == NULL) {
|
||||
ret = SDL_SetError("PipeWire could not find a default sink");
|
||||
goto failed;
|
||||
}
|
||||
target = pipewire_default_sink_id;
|
||||
}
|
||||
|
||||
node = io_list_get_by_path(target);
|
||||
if (node == NULL) {
|
||||
ret = SDL_SetError("PipeWire device list is out of sync with defaults");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (name != NULL) {
|
||||
*name = SDL_strdup(node->name);
|
||||
}
|
||||
SDL_copyp(spec, &node->spec);
|
||||
|
||||
failed:
|
||||
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
PIPEWIRE_Deinitialize()
|
||||
{
|
||||
|
|
@ -1255,13 +1410,15 @@ PIPEWIRE_Init(SDL_AudioDriverImpl *impl)
|
|||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = PIPEWIRE_DetectDevices;
|
||||
impl->OpenDevice = PIPEWIRE_OpenDevice;
|
||||
impl->CloseDevice = PIPEWIRE_CloseDevice;
|
||||
impl->Deinitialize = PIPEWIRE_Deinitialize;
|
||||
impl->DetectDevices = PIPEWIRE_DetectDevices;
|
||||
impl->OpenDevice = PIPEWIRE_OpenDevice;
|
||||
impl->CloseDevice = PIPEWIRE_CloseDevice;
|
||||
impl->Deinitialize = PIPEWIRE_Deinitialize;
|
||||
impl->GetDefaultAudioInfo = PIPEWIRE_GetDefaultAudioInfo;
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->ProvidesOwnCallbackThread = SDL_TRUE;
|
||||
impl->SupportsNonPow2Samples = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
|
|||
178
Engine/lib/sdl/src/audio/ps2/SDL_ps2audio.c
Normal file
178
Engine/lib/sdl/src/audio/ps2/SDL_ps2audio.c
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 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"
|
||||
|
||||
/* Output audio to nowhere... */
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_ps2audio.h"
|
||||
|
||||
#include <kernel.h>
|
||||
#include <malloc.h>
|
||||
#include <audsrv.h>
|
||||
#include <ps2_audio_driver.h>
|
||||
|
||||
/* The tag name used by PS2 audio */
|
||||
#define PS2AUDIO_DRIVER_NAME "ps2"
|
||||
|
||||
static int
|
||||
PS2AUDIO_OpenDevice(_THIS, const char *devname)
|
||||
{
|
||||
int i, mixlen;
|
||||
struct audsrv_fmt_t format;
|
||||
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc(sizeof(*this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_zerop(this->hidden);
|
||||
|
||||
|
||||
/* These are the native supported audio PS2 configs */
|
||||
switch (this->spec.freq) {
|
||||
case 11025:
|
||||
case 12000:
|
||||
case 22050:
|
||||
case 24000:
|
||||
case 32000:
|
||||
case 44100:
|
||||
case 48000:
|
||||
this->spec.freq = this->spec.freq;
|
||||
break;
|
||||
default:
|
||||
this->spec.freq = 48000;
|
||||
break;
|
||||
}
|
||||
|
||||
this->spec.samples = 512;
|
||||
this->spec.channels = this->spec.channels == 1 ? 1 : 2;
|
||||
this->spec.format = this->spec.format == AUDIO_S8 ? AUDIO_S8 : AUDIO_S16;
|
||||
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
format.bits = this->spec.format == AUDIO_S8 ? 8 : 16;
|
||||
format.freq = this->spec.freq;
|
||||
format.channels = this->spec.channels;
|
||||
|
||||
this->hidden->channel = audsrv_set_format(&format);
|
||||
audsrv_set_volume(MAX_VOLUME);
|
||||
|
||||
if (this->hidden->channel < 0) {
|
||||
free(this->hidden->rawbuf);
|
||||
this->hidden->rawbuf = NULL;
|
||||
return SDL_SetError("Couldn't reserve hardware channel");
|
||||
}
|
||||
|
||||
/* Update the fragment size as size in bytes. */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Allocate the mixing buffer. Its size and starting address must
|
||||
be a multiple of 64 bytes. Our sample count is already a multiple of
|
||||
64, so spec->size should be a multiple of 64 as well. */
|
||||
mixlen = this->spec.size * NUM_BUFFERS;
|
||||
this->hidden->rawbuf = (Uint8 *) memalign(64, mixlen);
|
||||
if (this->hidden->rawbuf == NULL) {
|
||||
return SDL_SetError("Couldn't allocate mixing buffer");
|
||||
}
|
||||
|
||||
SDL_memset(this->hidden->rawbuf, 0, mixlen);
|
||||
for (i = 0; i < NUM_BUFFERS; i++) {
|
||||
this->hidden->mixbufs[i] = &this->hidden->rawbuf[i * this->spec.size];
|
||||
}
|
||||
|
||||
this->hidden->next_buffer = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PS2AUDIO_PlayDevice(_THIS)
|
||||
{
|
||||
uint8_t *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
|
||||
audsrv_play_audio((char *)mixbuf, this->spec.size);
|
||||
|
||||
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
|
||||
}
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void PS2AUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
audsrv_wait_audio(this->spec.size);
|
||||
}
|
||||
|
||||
static Uint8 *PS2AUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return this->hidden->mixbufs[this->hidden->next_buffer];
|
||||
}
|
||||
|
||||
static void PS2AUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden->channel >= 0) {
|
||||
audsrv_stop_audio();
|
||||
this->hidden->channel = -1;
|
||||
}
|
||||
|
||||
if (this->hidden->rawbuf != NULL) {
|
||||
free(this->hidden->rawbuf);
|
||||
this->hidden->rawbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void PS2AUDIO_ThreadInit(_THIS)
|
||||
{
|
||||
/* Increase the priority of this audio thread by 1 to put it
|
||||
ahead of other SDL threads. */
|
||||
int32_t thid;
|
||||
ee_thread_status_t status;
|
||||
thid = GetThreadId();
|
||||
if (ReferThreadStatus(GetThreadId(), &status) == 0) {
|
||||
ChangeThreadPriority(thid, status.current_priority - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void PS2AUDIO_Deinitialize(void)
|
||||
{
|
||||
deinit_audio_driver();
|
||||
}
|
||||
|
||||
static SDL_bool PS2AUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
if(init_audio_driver() < 0)
|
||||
return SDL_FALSE;
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = PS2AUDIO_OpenDevice;
|
||||
impl->PlayDevice = PS2AUDIO_PlayDevice;
|
||||
impl->WaitDevice = PS2AUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = PS2AUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = PS2AUDIO_CloseDevice;
|
||||
impl->ThreadInit = PS2AUDIO_ThreadInit;
|
||||
impl->Deinitialize = PS2AUDIO_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap PS2AUDIO_bootstrap = {
|
||||
"ps2", "PS2 audio driver", PS2AUDIO_Init, SDL_FALSE
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
46
Engine/lib/sdl/src/audio/ps2/SDL_ps2audio.h
Normal file
46
Engine/lib/sdl/src/audio/ps2/SDL_ps2audio.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 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_ps2audio_h_
|
||||
#define SDL_ps2audio_h_
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
#define NUM_BUFFERS 2
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The hardware output channel. */
|
||||
int channel;
|
||||
/* The raw allocated mixing buffer. */
|
||||
Uint8 *rawbuf;
|
||||
/* Individual mixing buffers. */
|
||||
Uint8 *mixbufs[NUM_BUFFERS];
|
||||
/* Index of the next available mixing buffer. */
|
||||
int next_buffer;
|
||||
};
|
||||
|
||||
#endif /* SDL_ps2audio_h_ */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -118,6 +118,7 @@ static pa_operation * (*PULSEAUDIO_pa_stream_flush) (pa_stream *,
|
|||
static int (*PULSEAUDIO_pa_stream_disconnect) (pa_stream *);
|
||||
static void (*PULSEAUDIO_pa_stream_unref) (pa_stream *);
|
||||
static void (*PULSEAUDIO_pa_stream_set_write_callback)(pa_stream *, pa_stream_request_cb_t, void *);
|
||||
static pa_operation * (*PULSEAUDIO_pa_context_get_server_info)(pa_context *, pa_server_info_cb_t, void *);
|
||||
|
||||
static int load_pulseaudio_syms(void);
|
||||
|
||||
|
|
@ -230,6 +231,7 @@ load_pulseaudio_syms(void)
|
|||
SDL_PULSEAUDIO_SYM(pa_channel_map_init_auto);
|
||||
SDL_PULSEAUDIO_SYM(pa_strerror);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_set_write_callback);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_get_server_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -527,7 +529,7 @@ SourceDeviceNameCallback(pa_context *c, const pa_source_info *i, int is_last, vo
|
|||
static SDL_bool
|
||||
FindDeviceName(struct SDL_PrivateAudioData *h, const SDL_bool iscapture, void *handle)
|
||||
{
|
||||
const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1;
|
||||
const uint32_t idx = ((uint32_t) ((intptr_t) handle)) - 1;
|
||||
|
||||
if (handle == NULL) { /* NULL == default device. */
|
||||
return SDL_TRUE;
|
||||
|
|
@ -691,6 +693,13 @@ static pa_mainloop *hotplug_mainloop = NULL;
|
|||
static pa_context *hotplug_context = NULL;
|
||||
static SDL_Thread *hotplug_thread = NULL;
|
||||
|
||||
/* These are the OS identifiers (i.e. ALSA strings)... */
|
||||
static char *default_sink_path = NULL;
|
||||
static char *default_source_path = NULL;
|
||||
/* ... and these are the descriptions we use in GetDefaultAudioInfo. */
|
||||
static char *default_sink_name = NULL;
|
||||
static char *default_source_name = NULL;
|
||||
|
||||
/* device handles are device index + 1, cast to void*, so we never pass a NULL. */
|
||||
|
||||
static SDL_AudioFormat
|
||||
|
|
@ -721,6 +730,7 @@ static void
|
|||
SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
|
||||
{
|
||||
SDL_AudioSpec spec;
|
||||
SDL_bool add = (SDL_bool) ((intptr_t) data);
|
||||
if (i) {
|
||||
spec.freq = i->sample_spec.rate;
|
||||
spec.channels = i->sample_spec.channels;
|
||||
|
|
@ -731,7 +741,16 @@ SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
|
|||
spec.callback = NULL;
|
||||
spec.userdata = NULL;
|
||||
|
||||
SDL_AddAudioDevice(SDL_FALSE, i->description, &spec, (void *) ((size_t) i->index+1));
|
||||
if (add) {
|
||||
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) {
|
||||
if (default_sink_name != NULL) {
|
||||
SDL_free(default_sink_name);
|
||||
}
|
||||
default_sink_name = SDL_strdup(i->description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -740,6 +759,7 @@ static void
|
|||
SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
|
||||
{
|
||||
SDL_AudioSpec spec;
|
||||
SDL_bool add = (SDL_bool) ((intptr_t) data);
|
||||
if (i) {
|
||||
/* Maybe skip "monitor" sources. These are just output from other sinks. */
|
||||
if (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX)) {
|
||||
|
|
@ -752,30 +772,59 @@ SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *da
|
|||
spec.callback = NULL;
|
||||
spec.userdata = NULL;
|
||||
|
||||
SDL_AddAudioDevice(SDL_TRUE, i->description, &spec, (void *) ((size_t) i->index+1));
|
||||
if (add) {
|
||||
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) {
|
||||
if (default_source_name != NULL) {
|
||||
SDL_free(default_source_name);
|
||||
}
|
||||
default_source_name = SDL_strdup(i->description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ServerInfoCallback(pa_context *c, const pa_server_info *i, void *data)
|
||||
{
|
||||
if (default_sink_path != NULL) {
|
||||
SDL_free(default_sink_path);
|
||||
}
|
||||
if (default_source_path != NULL) {
|
||||
SDL_free(default_source_path);
|
||||
}
|
||||
default_sink_path = SDL_strdup(i->default_sink_name);
|
||||
default_source_path = SDL_strdup(i->default_source_name);
|
||||
}
|
||||
|
||||
/* 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) { /* 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);
|
||||
|
||||
/* adds need sink details from the PulseAudio server. Another callback... */
|
||||
if (added && sink) {
|
||||
PULSEAUDIO_pa_context_get_sink_info_by_index(hotplug_context, idx, SinkInfoCallback, NULL);
|
||||
} else if (added && source) {
|
||||
PULSEAUDIO_pa_context_get_source_info_by_index(hotplug_context, idx, SourceInfoCallback, NULL);
|
||||
if ((added || changed) && sink) {
|
||||
if (changed) {
|
||||
PULSEAUDIO_pa_context_get_server_info(hotplug_context, ServerInfoCallback, NULL);
|
||||
}
|
||||
PULSEAUDIO_pa_context_get_sink_info_by_index(hotplug_context, idx, SinkInfoCallback, (void*) ((intptr_t) added));
|
||||
} else if ((added || changed) && source) {
|
||||
if (changed) {
|
||||
PULSEAUDIO_pa_context_get_server_info(hotplug_context, ServerInfoCallback, NULL);
|
||||
}
|
||||
PULSEAUDIO_pa_context_get_source_info_by_index(hotplug_context, idx, SourceInfoCallback, (void*) ((intptr_t) added));
|
||||
} else if (removed && (sink || source)) {
|
||||
/* removes we can handle just with the device index. */
|
||||
SDL_RemoveAudioDevice(source != 0, (void *) ((size_t) idx+1));
|
||||
SDL_RemoveAudioDevice(source != 0, (void *) ((intptr_t) idx+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -796,13 +845,46 @@ HotplugThread(void *data)
|
|||
static void
|
||||
PULSEAUDIO_DetectDevices()
|
||||
{
|
||||
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_sink_info_list(hotplug_context, SinkInfoCallback, NULL));
|
||||
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_source_info_list(hotplug_context, SourceInfoCallback, NULL));
|
||||
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_server_info(hotplug_context, ServerInfoCallback, NULL));
|
||||
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_sink_info_list(hotplug_context, SinkInfoCallback, (void*) ((intptr_t) SDL_TRUE)));
|
||||
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_source_info_list(hotplug_context, SourceInfoCallback, (void*) ((intptr_t) SDL_TRUE)));
|
||||
|
||||
/* ok, we have a sane list, let's set up hotplug notifications now... */
|
||||
hotplug_thread = SDL_CreateThreadInternal(HotplugThread, "PulseHotplug", 256 * 1024, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
PULSEAUDIO_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
|
||||
{
|
||||
int i;
|
||||
int numdevices;
|
||||
|
||||
char *target;
|
||||
if (iscapture) {
|
||||
if (default_source_name == NULL) {
|
||||
return SDL_SetError("PulseAudio could not find a default source");
|
||||
}
|
||||
target = default_source_name;
|
||||
} else {
|
||||
if (default_sink_name == NULL) {
|
||||
return SDL_SetError("PulseAudio could not find a default sink");
|
||||
}
|
||||
target = default_sink_name;
|
||||
}
|
||||
|
||||
numdevices = SDL_GetNumAudioDevices(iscapture);
|
||||
for (i = 0; i < numdevices; i += 1) {
|
||||
if (SDL_strcmp(SDL_GetAudioDeviceName(i, iscapture), target) == 0) {
|
||||
if (name != NULL) {
|
||||
*name = SDL_strdup(target);
|
||||
}
|
||||
SDL_GetAudioDeviceSpec(i, iscapture, spec);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return SDL_SetError("Could not find default PulseAudio device");
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_Deinitialize(void)
|
||||
{
|
||||
|
|
@ -816,6 +898,23 @@ PULSEAUDIO_Deinitialize(void)
|
|||
hotplug_mainloop = NULL;
|
||||
hotplug_context = NULL;
|
||||
|
||||
if (default_sink_path != NULL) {
|
||||
SDL_free(default_sink_path);
|
||||
default_sink_path = NULL;
|
||||
}
|
||||
if (default_source_path != NULL) {
|
||||
SDL_free(default_source_path);
|
||||
default_source_path = NULL;
|
||||
}
|
||||
if (default_sink_name != NULL) {
|
||||
SDL_free(default_sink_name);
|
||||
default_sink_name = NULL;
|
||||
}
|
||||
if (default_source_name != NULL) {
|
||||
SDL_free(default_source_name);
|
||||
default_source_name = NULL;
|
||||
}
|
||||
|
||||
UnloadPulseAudioLibrary();
|
||||
}
|
||||
|
||||
|
|
@ -843,8 +942,10 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->Deinitialize = PULSEAUDIO_Deinitialize;
|
||||
impl->CaptureFromDevice = PULSEAUDIO_CaptureFromDevice;
|
||||
impl->FlushCapture = PULSEAUDIO_FlushCapture;
|
||||
impl->GetDefaultAudioInfo = PULSEAUDIO_GetDefaultAudioInfo;
|
||||
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->SupportsNonPow2Samples = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -117,7 +117,7 @@ QSA_WaitDevice(_THIS)
|
|||
int result;
|
||||
|
||||
/* Setup timeout for playing one fragment equal to 2 seconds */
|
||||
/* If timeout occured than something wrong with hardware or driver */
|
||||
/* 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(this->hidden->audio_fd,
|
||||
|
|
@ -128,7 +128,7 @@ QSA_WaitDevice(_THIS)
|
|||
SDL_SetError("QSA: SDL_IOReady() failed: %s", strerror(errno));
|
||||
break;
|
||||
case 0:
|
||||
SDL_SetError("QSA: timeout on buffer waiting occured");
|
||||
SDL_SetError("QSA: timeout on buffer waiting occurred");
|
||||
this->hidden->timeout_on_wait = 1;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -260,7 +260,7 @@ static int
|
|||
QSA_OpenDevice(_THIS, const char *devname)
|
||||
{
|
||||
const QSA_Device *device = (const QSA_Device *) this->handle;
|
||||
SDL_Bool iscapture = this->iscapture;
|
||||
SDL_bool iscapture = this->iscapture;
|
||||
int status = 0;
|
||||
int format = 0;
|
||||
SDL_AudioFormat test_format;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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 @@
|
|||
#if SDL_AUDIO_DRIVER_WASAPI
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../../core/windows/SDL_immdevice.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
#define COBJMACROS
|
||||
#include <mmdeviceapi.h>
|
||||
#include <audioclient.h>
|
||||
|
||||
#include "SDL_wasapi.h"
|
||||
|
|
@ -45,109 +45,9 @@
|
|||
#define AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000
|
||||
#endif
|
||||
|
||||
/* these increment as default devices change. Opened default devices pick up changes in their threads. */
|
||||
SDL_atomic_t WASAPI_DefaultPlaybackGeneration;
|
||||
SDL_atomic_t WASAPI_DefaultCaptureGeneration;
|
||||
|
||||
/* This is a list of device id strings we have inflight, so we have consistent pointers to the same device. */
|
||||
typedef struct DevIdList
|
||||
{
|
||||
WCHAR *str;
|
||||
struct DevIdList *next;
|
||||
} DevIdList;
|
||||
|
||||
static DevIdList *deviceid_list = NULL;
|
||||
|
||||
/* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */
|
||||
static const IID SDL_IID_IAudioRenderClient = { 0xf294acfc, 0x3146, 0x4483,{ 0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2 } };
|
||||
static const IID SDL_IID_IAudioCaptureClient = { 0xc8adbd64, 0xe71e, 0x48a0,{ 0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17 } };
|
||||
static const GUID SDL_KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
static const GUID SDL_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
|
||||
|
||||
void
|
||||
WASAPI_RemoveDevice(const SDL_bool iscapture, LPCWSTR devid)
|
||||
{
|
||||
DevIdList *i;
|
||||
DevIdList *next;
|
||||
DevIdList *prev = NULL;
|
||||
for (i = deviceid_list; i; i = next) {
|
||||
next = i->next;
|
||||
if (SDL_wcscmp(i->str, devid) == 0) {
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
} else {
|
||||
deviceid_list = next;
|
||||
}
|
||||
SDL_RemoveAudioDevice(iscapture, i->str);
|
||||
SDL_free(i->str);
|
||||
SDL_free(i);
|
||||
}
|
||||
prev = i;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_AudioFormat
|
||||
WaveFormatToSDLFormat(WAVEFORMATEX *waveformat)
|
||||
{
|
||||
if ((waveformat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) && (waveformat->wBitsPerSample == 32)) {
|
||||
return AUDIO_F32SYS;
|
||||
} else if ((waveformat->wFormatTag == WAVE_FORMAT_PCM) && (waveformat->wBitsPerSample == 16)) {
|
||||
return AUDIO_S16SYS;
|
||||
} else if ((waveformat->wFormatTag == WAVE_FORMAT_PCM) && (waveformat->wBitsPerSample == 32)) {
|
||||
return AUDIO_S32SYS;
|
||||
} else if (waveformat->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
||||
const WAVEFORMATEXTENSIBLE *ext = (const WAVEFORMATEXTENSIBLE *) waveformat;
|
||||
if ((SDL_memcmp(&ext->SubFormat, &SDL_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof (GUID)) == 0) && (waveformat->wBitsPerSample == 32)) {
|
||||
return AUDIO_F32SYS;
|
||||
} else if ((SDL_memcmp(&ext->SubFormat, &SDL_KSDATAFORMAT_SUBTYPE_PCM, sizeof (GUID)) == 0) && (waveformat->wBitsPerSample == 16)) {
|
||||
return AUDIO_S16SYS;
|
||||
} else if ((SDL_memcmp(&ext->SubFormat, &SDL_KSDATAFORMAT_SUBTYPE_PCM, sizeof (GUID)) == 0) && (waveformat->wBitsPerSample == 32)) {
|
||||
return AUDIO_S32SYS;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_AddDevice(const SDL_bool iscapture, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid)
|
||||
{
|
||||
DevIdList *devidlist;
|
||||
SDL_AudioSpec spec;
|
||||
|
||||
/* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever).
|
||||
In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for
|
||||
phones and tablets, where you might have an internal speaker and a headphone jack and expect both to be
|
||||
available and switch automatically. (!!! FIXME...?) */
|
||||
|
||||
/* see if we already have this one. */
|
||||
for (devidlist = deviceid_list; devidlist; devidlist = devidlist->next) {
|
||||
if (SDL_wcscmp(devidlist->str, devid) == 0) {
|
||||
return; /* we already have this. */
|
||||
}
|
||||
}
|
||||
|
||||
devidlist = (DevIdList *) SDL_malloc(sizeof (*devidlist));
|
||||
if (!devidlist) {
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
devid = SDL_wcsdup(devid);
|
||||
if (!devid) {
|
||||
SDL_free(devidlist);
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
devidlist->str = (WCHAR *) devid;
|
||||
devidlist->next = deviceid_list;
|
||||
deviceid_list = devidlist;
|
||||
|
||||
SDL_zero(spec);
|
||||
spec.channels = (Uint8)fmt->Format.nChannels;
|
||||
spec.freq = fmt->Format.nSamplesPerSec;
|
||||
spec.format = WaveFormatToSDLFormat((WAVEFORMATEX *) fmt);
|
||||
SDL_AddAudioDevice(iscapture, devname, &spec, (void *) devid);
|
||||
}
|
||||
|
||||
static void
|
||||
WASAPI_DetectDevices(void)
|
||||
|
|
@ -235,7 +135,7 @@ RecoverWasapiDevice(_THIS)
|
|||
ReleaseWasapiDevice(this); /* dump the lost device's handles. */
|
||||
|
||||
if (this->hidden->default_device_generation) {
|
||||
this->hidden->default_device_generation = SDL_AtomicGet(this->iscapture ? &WASAPI_DefaultCaptureGeneration : &WASAPI_DefaultPlaybackGeneration);
|
||||
this->hidden->default_device_generation = SDL_AtomicGet(this->iscapture ? &SDL_IMMDevice_DefaultCaptureGeneration : &SDL_IMMDevice_DefaultPlaybackGeneration);
|
||||
}
|
||||
|
||||
/* this can fail for lots of reasons, but the most likely is we had a
|
||||
|
|
@ -268,7 +168,7 @@ RecoverWasapiIfLost(_THIS)
|
|||
}
|
||||
|
||||
if (!lost && (generation > 0)) { /* is a default device? */
|
||||
const int newgen = SDL_AtomicGet(this->iscapture ? &WASAPI_DefaultCaptureGeneration : &WASAPI_DefaultPlaybackGeneration);
|
||||
const int newgen = SDL_AtomicGet(this->iscapture ? &SDL_IMMDevice_DefaultCaptureGeneration : &SDL_IMMDevice_DefaultPlaybackGeneration);
|
||||
if (generation != newgen) { /* the desired default device was changed, jump over to it. */
|
||||
lost = SDL_TRUE;
|
||||
}
|
||||
|
|
@ -519,7 +419,7 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
|
|||
|
||||
SDL_assert(client != NULL);
|
||||
|
||||
#ifdef __WINRT__ /* CreateEventEx() arrived in Vista, so we need an #ifdef for XP. */
|
||||
#if defined(__WINRT__) || defined(__GDK__) /* CreateEventEx() arrived in Vista, so we need an #ifdef for XP. */
|
||||
this->hidden->event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
|
||||
#else
|
||||
this->hidden->event = CreateEventW(NULL, 0, 0, NULL);
|
||||
|
|
@ -558,7 +458,10 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
|
|||
return WIN_SetErrorFromHRESULT("WASAPI can't determine minimum device period", ret);
|
||||
}
|
||||
|
||||
#if 1 /* we're getting reports that WASAPI's resampler introduces distortions, so it's disabled for now. --ryan. */
|
||||
/* we've gotten reports that WASAPI's resampler introduces distortions, but in the short term
|
||||
it fixes some other WASAPI-specific quirks we haven't quite tracked down.
|
||||
Refer to bug #6326 for the immediate concern. */
|
||||
#if 0
|
||||
this->spec.freq = waveformat->nSamplesPerSec; /* force sampling rate so our resampler kicks in, if necessary. */
|
||||
#else
|
||||
/* favor WASAPI's resampler over our own */
|
||||
|
|
@ -655,7 +558,7 @@ WASAPI_OpenDevice(_THIS, const char *devname)
|
|||
WASAPI_RefDevice(this); /* so CloseDevice() will unref to zero. */
|
||||
|
||||
if (!devid) { /* is default device? */
|
||||
this->hidden->default_device_generation = SDL_AtomicGet(this->iscapture ? &WASAPI_DefaultCaptureGeneration : &WASAPI_DefaultPlaybackGeneration);
|
||||
this->hidden->default_device_generation = SDL_AtomicGet(this->iscapture ? &SDL_IMMDevice_DefaultCaptureGeneration : &SDL_IMMDevice_DefaultPlaybackGeneration);
|
||||
} else {
|
||||
this->hidden->devid = SDL_wcsdup(devid);
|
||||
if (!this->hidden->devid) {
|
||||
|
|
@ -693,25 +596,12 @@ WASAPI_ThreadDeinit(_THIS)
|
|||
static void
|
||||
WASAPI_Deinitialize(void)
|
||||
{
|
||||
DevIdList *devidlist;
|
||||
DevIdList *next;
|
||||
|
||||
WASAPI_PlatformDeinit();
|
||||
|
||||
for (devidlist = deviceid_list; devidlist; devidlist = next) {
|
||||
next = devidlist->next;
|
||||
SDL_free(devidlist->str);
|
||||
SDL_free(devidlist);
|
||||
}
|
||||
deviceid_list = NULL;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
WASAPI_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
SDL_AtomicSet(&WASAPI_DefaultPlaybackGeneration, 1);
|
||||
SDL_AtomicSet(&WASAPI_DefaultCaptureGeneration, 1);
|
||||
|
||||
if (WASAPI_PlatformInit() == -1) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
|
@ -728,7 +618,9 @@ WASAPI_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->FlushCapture = WASAPI_FlushCapture;
|
||||
impl->CloseDevice = WASAPI_CloseDevice;
|
||||
impl->Deinitialize = WASAPI_Deinitialize;
|
||||
impl->GetDefaultAudioInfo = WASAPI_GetDefaultAudioInfo;
|
||||
impl->HasCaptureSupport = SDL_TRUE;
|
||||
impl->SupportsNonPow2Samples = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -55,21 +55,16 @@ struct SDL_PrivateAudioData
|
|||
SDL_atomic_t just_activated;
|
||||
};
|
||||
|
||||
/* these increment as default devices change. Opened default devices pick up changes in their threads. */
|
||||
extern SDL_atomic_t WASAPI_DefaultPlaybackGeneration;
|
||||
extern SDL_atomic_t WASAPI_DefaultCaptureGeneration;
|
||||
|
||||
/* win32 and winrt implementations call into these. */
|
||||
int WASAPI_PrepDevice(_THIS, const SDL_bool updatestream);
|
||||
void WASAPI_RefDevice(_THIS);
|
||||
void WASAPI_UnrefDevice(_THIS);
|
||||
void WASAPI_AddDevice(const SDL_bool iscapture, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid);
|
||||
void WASAPI_RemoveDevice(const SDL_bool iscapture, LPCWSTR devid);
|
||||
|
||||
/* These are functions that are implemented differently for Windows vs WinRT. */
|
||||
int WASAPI_PlatformInit(void);
|
||||
void WASAPI_PlatformDeinit(void);
|
||||
void WASAPI_EnumerateEndpoints(void);
|
||||
int WASAPI_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture);
|
||||
int WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery);
|
||||
void WASAPI_PlatformThreadInit(_THIS);
|
||||
void WASAPI_PlatformThreadDeinit(_THIS);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,28 +29,16 @@
|
|||
#if SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__)
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../../core/windows/SDL_immdevice.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
#define COBJMACROS
|
||||
#include <mmdeviceapi.h>
|
||||
#include <audioclient.h>
|
||||
|
||||
#include "SDL_wasapi.h"
|
||||
|
||||
static const ERole SDL_WASAPI_role = eConsole; /* !!! FIXME: should this be eMultimedia? Should be a hint? */
|
||||
|
||||
/* This is global to the WASAPI target, to handle hotplug and default device lookup. */
|
||||
static IMMDeviceEnumerator *enumerator = NULL;
|
||||
|
||||
/* PropVariantInit() is an inline function/macro in PropIdl.h that calls the C runtime's memset() directly. Use ours instead, to avoid dependency. */
|
||||
#ifdef PropVariantInit
|
||||
#undef PropVariantInit
|
||||
#endif
|
||||
#define PropVariantInit(p) SDL_zerop(p)
|
||||
|
||||
/* 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);
|
||||
|
|
@ -59,203 +47,13 @@ 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 const CLSID SDL_CLSID_MMDeviceEnumerator = { 0xbcde0395, 0xe52f, 0x467c,{ 0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e } };
|
||||
static const IID SDL_IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35,{ 0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6 } };
|
||||
static const IID SDL_IID_IMMNotificationClient = { 0x7991eec9, 0x7e89, 0x4d85,{ 0x83, 0x90, 0x6c, 0x70, 0x3c, 0xec, 0x60, 0xc0 } };
|
||||
static const IID SDL_IID_IMMEndpoint = { 0x1be09788, 0x6894, 0x4089,{ 0x85, 0x86, 0x9a, 0x2a, 0x6c, 0x26, 0x5a, 0xc5 } };
|
||||
static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32,{ 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
|
||||
static const PROPERTYKEY SDL_PKEY_Device_FriendlyName = { { 0xa45c254e, 0xdf1c, 0x4efd,{ 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, } }, 14 };
|
||||
static const PROPERTYKEY SDL_PKEY_AudioEngine_DeviceFormat = { { 0xf19f064d, 0x82c, 0x4e27,{ 0xbc, 0x73, 0x68, 0x82, 0xa1, 0xbb, 0x8e, 0x4c, } }, 0 };
|
||||
|
||||
|
||||
static void
|
||||
GetWasapiDeviceInfo(IMMDevice *device, char **utf8dev, WAVEFORMATEXTENSIBLE *fmt)
|
||||
{
|
||||
/* PKEY_Device_FriendlyName gives you "Speakers (SoundBlaster Pro)" which drives me nuts. I'd rather it be
|
||||
"SoundBlaster Pro (Speakers)" but I guess that's developers vs users. Windows uses the FriendlyName in
|
||||
its own UIs, like Volume Control, etc. */
|
||||
IPropertyStore *props = NULL;
|
||||
*utf8dev = NULL;
|
||||
SDL_zerop(fmt);
|
||||
if (SUCCEEDED(IMMDevice_OpenPropertyStore(device, STGM_READ, &props))) {
|
||||
PROPVARIANT var;
|
||||
PropVariantInit(&var);
|
||||
if (SUCCEEDED(IPropertyStore_GetValue(props, &SDL_PKEY_Device_FriendlyName, &var))) {
|
||||
*utf8dev = WIN_StringToUTF8W(var.pwszVal);
|
||||
}
|
||||
PropVariantClear(&var);
|
||||
if (SUCCEEDED(IPropertyStore_GetValue(props, &SDL_PKEY_AudioEngine_DeviceFormat, &var))) {
|
||||
SDL_memcpy(fmt, var.blob.pBlobData, SDL_min(var.blob.cbSize, sizeof(WAVEFORMATEXTENSIBLE)));
|
||||
}
|
||||
PropVariantClear(&var);
|
||||
IPropertyStore_Release(props);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We need a COM subclass of IMMNotificationClient for hotplug support, which is
|
||||
easy in C++, but we have to tapdance more to make work in C.
|
||||
Thanks to this page for coaching on how to make this work:
|
||||
https://www.codeproject.com/Articles/13601/COM-in-plain-C */
|
||||
|
||||
typedef struct SDLMMNotificationClient
|
||||
{
|
||||
const IMMNotificationClientVtbl *lpVtbl;
|
||||
SDL_atomic_t refcount;
|
||||
} SDLMMNotificationClient;
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
SDLMMNotificationClient_QueryInterface(IMMNotificationClient *this, REFIID iid, void **ppv)
|
||||
{
|
||||
if ((WIN_IsEqualIID(iid, &IID_IUnknown)) || (WIN_IsEqualIID(iid, &SDL_IID_IMMNotificationClient)))
|
||||
{
|
||||
*ppv = this;
|
||||
this->lpVtbl->AddRef(this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
SDLMMNotificationClient_AddRef(IMMNotificationClient *ithis)
|
||||
{
|
||||
SDLMMNotificationClient *this = (SDLMMNotificationClient *) ithis;
|
||||
return (ULONG) (SDL_AtomicIncRef(&this->refcount) + 1);
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
SDLMMNotificationClient_Release(IMMNotificationClient *ithis)
|
||||
{
|
||||
/* this is a static object; we don't ever free it. */
|
||||
SDLMMNotificationClient *this = (SDLMMNotificationClient *) ithis;
|
||||
const ULONG retval = SDL_AtomicDecRef(&this->refcount);
|
||||
if (retval == 0) {
|
||||
SDL_AtomicSet(&this->refcount, 0); /* uhh... */
|
||||
return 0;
|
||||
}
|
||||
return retval - 1;
|
||||
}
|
||||
|
||||
/* These are the entry points called when WASAPI device endpoints change. */
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
SDLMMNotificationClient_OnDefaultDeviceChanged(IMMNotificationClient *ithis, EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId)
|
||||
{
|
||||
if (role != SDL_WASAPI_role) {
|
||||
return S_OK; /* ignore it. */
|
||||
}
|
||||
|
||||
/* Increment the "generation," so opened devices will pick this up in their threads. */
|
||||
switch (flow) {
|
||||
case eRender:
|
||||
SDL_AtomicAdd(&WASAPI_DefaultPlaybackGeneration, 1);
|
||||
break;
|
||||
|
||||
case eCapture:
|
||||
SDL_AtomicAdd(&WASAPI_DefaultCaptureGeneration, 1);
|
||||
break;
|
||||
|
||||
case eAll:
|
||||
SDL_AtomicAdd(&WASAPI_DefaultPlaybackGeneration, 1);
|
||||
SDL_AtomicAdd(&WASAPI_DefaultCaptureGeneration, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
SDL_assert(!"uhoh, unexpected OnDefaultDeviceChange flow!");
|
||||
break;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
SDLMMNotificationClient_OnDeviceAdded(IMMNotificationClient *ithis, LPCWSTR pwstrDeviceId)
|
||||
{
|
||||
/* we ignore this; devices added here then progress to ACTIVE, if appropriate, in
|
||||
OnDeviceStateChange, making that a better place to deal with device adds. More
|
||||
importantly: the first time you plug in a USB audio device, this callback will
|
||||
fire, but when you unplug it, it isn't removed (it's state changes to NOTPRESENT).
|
||||
Plugging it back in won't fire this callback again. */
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
SDLMMNotificationClient_OnDeviceRemoved(IMMNotificationClient *ithis, LPCWSTR pwstrDeviceId)
|
||||
{
|
||||
/* See notes in OnDeviceAdded handler about why we ignore this. */
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
SDLMMNotificationClient_OnDeviceStateChanged(IMMNotificationClient *ithis, LPCWSTR pwstrDeviceId, DWORD dwNewState)
|
||||
{
|
||||
IMMDevice *device = NULL;
|
||||
|
||||
if (SUCCEEDED(IMMDeviceEnumerator_GetDevice(enumerator, pwstrDeviceId, &device))) {
|
||||
IMMEndpoint *endpoint = NULL;
|
||||
if (SUCCEEDED(IMMDevice_QueryInterface(device, &SDL_IID_IMMEndpoint, (void **) &endpoint))) {
|
||||
EDataFlow flow;
|
||||
if (SUCCEEDED(IMMEndpoint_GetDataFlow(endpoint, &flow))) {
|
||||
const SDL_bool iscapture = (flow == eCapture);
|
||||
if (dwNewState == DEVICE_STATE_ACTIVE) {
|
||||
char *utf8dev;
|
||||
WAVEFORMATEXTENSIBLE fmt;
|
||||
GetWasapiDeviceInfo(device, &utf8dev, &fmt);
|
||||
if (utf8dev) {
|
||||
WASAPI_AddDevice(iscapture, utf8dev, &fmt, pwstrDeviceId);
|
||||
SDL_free(utf8dev);
|
||||
}
|
||||
} else {
|
||||
WASAPI_RemoveDevice(iscapture, pwstrDeviceId);
|
||||
}
|
||||
}
|
||||
IMMEndpoint_Release(endpoint);
|
||||
}
|
||||
IMMDevice_Release(device);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
SDLMMNotificationClient_OnPropertyValueChanged(IMMNotificationClient *this, LPCWSTR pwstrDeviceId, const PROPERTYKEY key)
|
||||
{
|
||||
return S_OK; /* we don't care about these. */
|
||||
}
|
||||
|
||||
static const IMMNotificationClientVtbl notification_client_vtbl = {
|
||||
SDLMMNotificationClient_QueryInterface,
|
||||
SDLMMNotificationClient_AddRef,
|
||||
SDLMMNotificationClient_Release,
|
||||
SDLMMNotificationClient_OnDeviceStateChanged,
|
||||
SDLMMNotificationClient_OnDeviceAdded,
|
||||
SDLMMNotificationClient_OnDeviceRemoved,
|
||||
SDLMMNotificationClient_OnDefaultDeviceChanged,
|
||||
SDLMMNotificationClient_OnPropertyValueChanged
|
||||
};
|
||||
|
||||
static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 } };
|
||||
|
||||
|
||||
int
|
||||
WASAPI_PlatformInit(void)
|
||||
{
|
||||
HRESULT ret;
|
||||
|
||||
/* just skip the discussion with COM here. */
|
||||
if (!WIN_IsWindowsVistaOrGreater()) {
|
||||
return SDL_SetError("WASAPI support requires Windows Vista or later");
|
||||
}
|
||||
|
||||
if (FAILED(WIN_CoInitialize())) {
|
||||
return SDL_SetError("WASAPI: CoInitialize() failed");
|
||||
}
|
||||
|
||||
ret = CoCreateInstance(&SDL_CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &SDL_IID_IMMDeviceEnumerator, (LPVOID *) &enumerator);
|
||||
if (FAILED(ret)) {
|
||||
WIN_CoUninitialize();
|
||||
return WIN_SetErrorFromHRESULT("WASAPI CoCreateInstance(MMDeviceEnumerator)", ret);
|
||||
if (SDL_IMMDevice_Init() < 0) {
|
||||
return -1; /* This 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! */
|
||||
|
|
@ -270,12 +68,6 @@ WASAPI_PlatformInit(void)
|
|||
void
|
||||
WASAPI_PlatformDeinit(void)
|
||||
{
|
||||
if (enumerator) {
|
||||
IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *) ¬ification_client);
|
||||
IMMDeviceEnumerator_Release(enumerator);
|
||||
enumerator = NULL;
|
||||
}
|
||||
|
||||
if (libavrt) {
|
||||
FreeLibrary(libavrt);
|
||||
libavrt = NULL;
|
||||
|
|
@ -284,7 +76,7 @@ WASAPI_PlatformDeinit(void)
|
|||
pAvSetMmThreadCharacteristicsW = NULL;
|
||||
pAvRevertMmThreadCharacteristics = NULL;
|
||||
|
||||
WIN_CoUninitialize();
|
||||
SDL_IMMDevice_Quit();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -320,21 +112,12 @@ WASAPI_PlatformThreadDeinit(_THIS)
|
|||
int
|
||||
WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
|
||||
{
|
||||
LPCWSTR devid = this->hidden->devid;
|
||||
IMMDevice *device = NULL;
|
||||
HRESULT ret;
|
||||
|
||||
if (devid == NULL) {
|
||||
const EDataFlow dataflow = this->iscapture ? eCapture : eRender;
|
||||
ret = IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, dataflow, SDL_WASAPI_role, &device);
|
||||
} else {
|
||||
ret = IMMDeviceEnumerator_GetDevice(enumerator, devid, &device);
|
||||
}
|
||||
|
||||
if (FAILED(ret)) {
|
||||
SDL_assert(device == NULL);
|
||||
if (SDL_IMMDevice_Get(this->hidden->devid, &device, this->iscapture) < 0) {
|
||||
this->hidden->client = NULL;
|
||||
return WIN_SetErrorFromHRESULT("WASAPI can't find requested audio endpoint", ret);
|
||||
return -1; /* This is already set by SDL_IMMDevice_Get */
|
||||
}
|
||||
|
||||
/* this is not async in standard win32, yay! */
|
||||
|
|
@ -354,99 +137,16 @@ WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
|
|||
return 0; /* good to go. */
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPWSTR devid;
|
||||
char *devname;
|
||||
WAVEFORMATEXTENSIBLE fmt;
|
||||
} EndpointItem;
|
||||
|
||||
static int SDLCALL sort_endpoints(const void *_a, const void *_b)
|
||||
{
|
||||
LPWSTR a = ((const EndpointItem *) _a)->devid;
|
||||
LPWSTR b = ((const EndpointItem *) _b)->devid;
|
||||
if (!a && b) {
|
||||
return -1;
|
||||
} else if (a && !b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (SDL_TRUE) {
|
||||
if (*a < *b) {
|
||||
return -1;
|
||||
} else if (*a > *b) {
|
||||
return 1;
|
||||
} else if (*a == 0) {
|
||||
break;
|
||||
}
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
WASAPI_EnumerateEndpointsForFlow(const SDL_bool iscapture)
|
||||
{
|
||||
IMMDeviceCollection *collection = NULL;
|
||||
EndpointItem *items;
|
||||
UINT i, total;
|
||||
|
||||
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
|
||||
...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */
|
||||
|
||||
if (FAILED(IMMDeviceEnumerator_EnumAudioEndpoints(enumerator, iscapture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &collection))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(IMMDeviceCollection_GetCount(collection, &total))) {
|
||||
IMMDeviceCollection_Release(collection);
|
||||
return;
|
||||
}
|
||||
|
||||
items = (EndpointItem *) SDL_calloc(total, sizeof (EndpointItem));
|
||||
if (!items) {
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
for (i = 0; i < total; i++) {
|
||||
EndpointItem *item = items + i;
|
||||
IMMDevice *device = NULL;
|
||||
if (SUCCEEDED(IMMDeviceCollection_Item(collection, i, &device))) {
|
||||
if (SUCCEEDED(IMMDevice_GetId(device, &item->devid))) {
|
||||
GetWasapiDeviceInfo(device, &item->devname, &item->fmt);
|
||||
}
|
||||
IMMDevice_Release(device);
|
||||
}
|
||||
}
|
||||
|
||||
/* sort the list of devices by their guid so list is consistent between runs */
|
||||
SDL_qsort(items, total, sizeof (*items), sort_endpoints);
|
||||
|
||||
/* Send the sorted list on to the SDL's higher level. */
|
||||
for (i = 0; i < total; i++) {
|
||||
EndpointItem *item = items + i;
|
||||
if ((item->devid) && (item->devname)) {
|
||||
WASAPI_AddDevice(iscapture, item->devname, &item->fmt, item->devid);
|
||||
}
|
||||
SDL_free(item->devname);
|
||||
CoTaskMemFree(item->devid);
|
||||
}
|
||||
|
||||
SDL_free(items);
|
||||
IMMDeviceCollection_Release(collection);
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_EnumerateEndpoints(void)
|
||||
{
|
||||
WASAPI_EnumerateEndpointsForFlow(SDL_FALSE); /* playback */
|
||||
WASAPI_EnumerateEndpointsForFlow(SDL_TRUE); /* capture */
|
||||
SDL_IMMDevice_EnumerateEndpoints(SDL_FALSE);
|
||||
}
|
||||
|
||||
/* if this fails, we just won't get hotplug events. Carry on anyhow. */
|
||||
IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *) ¬ification_client);
|
||||
int
|
||||
WASAPI_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
|
||||
{
|
||||
return SDL_IMMDevice_GetDefaultAudioInfo(name, spec, iscapture);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
@ -55,6 +55,22 @@ using namespace Microsoft::WRL;
|
|||
|
||||
static Platform::String^ SDL_PKEY_AudioEngine_DeviceFormat = L"{f19f064d-082c-4e27-bc73-6882a1bb8e4c} 0";
|
||||
|
||||
static void WASAPI_AddDevice(const SDL_bool iscapture, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid);
|
||||
static void WASAPI_RemoveDevice(const SDL_bool iscapture, LPCWSTR devid);
|
||||
extern "C" {
|
||||
SDL_atomic_t SDL_IMMDevice_DefaultPlaybackGeneration;
|
||||
SDL_atomic_t SDL_IMMDevice_DefaultCaptureGeneration;
|
||||
}
|
||||
|
||||
/* This is a list of device id strings we have inflight, so we have consistent pointers to the same device. */
|
||||
typedef struct DevIdList
|
||||
{
|
||||
WCHAR *str;
|
||||
struct DevIdList *next;
|
||||
} DevIdList;
|
||||
|
||||
static DevIdList *deviceid_list = NULL;
|
||||
|
||||
class SDL_WasapiDeviceEventHandler
|
||||
{
|
||||
public:
|
||||
|
|
@ -173,15 +189,15 @@ SDL_WasapiDeviceEventHandler::OnEnumerationCompleted(DeviceWatcher^ sender, Plat
|
|||
void
|
||||
SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args)
|
||||
{
|
||||
SDL_assert(this->iscapture);
|
||||
SDL_AtomicAdd(&WASAPI_DefaultPlaybackGeneration, 1);
|
||||
SDL_assert(!this->iscapture);
|
||||
SDL_AtomicAdd(&SDL_IMMDevice_DefaultPlaybackGeneration, 1);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_WasapiDeviceEventHandler::OnDefaultCaptureDeviceChanged(Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args)
|
||||
{
|
||||
SDL_assert(!this->iscapture);
|
||||
SDL_AtomicAdd(&WASAPI_DefaultCaptureGeneration, 1);
|
||||
SDL_assert(this->iscapture);
|
||||
SDL_AtomicAdd(&SDL_IMMDevice_DefaultCaptureGeneration, 1);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -190,15 +206,27 @@ static SDL_WasapiDeviceEventHandler *capture_device_event_handler;
|
|||
|
||||
int WASAPI_PlatformInit(void)
|
||||
{
|
||||
SDL_AtomicSet(&SDL_IMMDevice_DefaultPlaybackGeneration, 1);
|
||||
SDL_AtomicSet(&SDL_IMMDevice_DefaultCaptureGeneration, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WASAPI_PlatformDeinit(void)
|
||||
{
|
||||
DevIdList *devidlist;
|
||||
DevIdList *next;
|
||||
|
||||
delete playback_device_event_handler;
|
||||
playback_device_event_handler = nullptr;
|
||||
delete capture_device_event_handler;
|
||||
capture_device_event_handler = nullptr;
|
||||
|
||||
for (devidlist = deviceid_list; devidlist; devidlist = next) {
|
||||
next = devidlist->next;
|
||||
SDL_free(devidlist->str);
|
||||
SDL_free(devidlist);
|
||||
}
|
||||
deviceid_list = NULL;
|
||||
}
|
||||
|
||||
void WASAPI_EnumerateEndpoints(void)
|
||||
|
|
@ -234,6 +262,12 @@ WASAPI_PlatformDeleteActivationHandler(void *handler)
|
|||
((SDL_WasapiActivationHandler *) handler)->Release();
|
||||
}
|
||||
|
||||
int
|
||||
WASAPI_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
|
||||
{
|
||||
|
|
@ -317,6 +351,97 @@ WASAPI_PlatformThreadDeinit(_THIS)
|
|||
// !!! FIXME: set this thread to "Pro Audio" priority.
|
||||
}
|
||||
|
||||
/* Everything below was copied from SDL_wasapi.c, before it got moved to SDL_immdevice.c! */
|
||||
|
||||
static const GUID SDL_KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
static const GUID SDL_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
|
||||
extern "C" SDL_AudioFormat
|
||||
WaveFormatToSDLFormat(WAVEFORMATEX *waveformat)
|
||||
{
|
||||
if ((waveformat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) && (waveformat->wBitsPerSample == 32)) {
|
||||
return AUDIO_F32SYS;
|
||||
} else if ((waveformat->wFormatTag == WAVE_FORMAT_PCM) && (waveformat->wBitsPerSample == 16)) {
|
||||
return AUDIO_S16SYS;
|
||||
} else if ((waveformat->wFormatTag == WAVE_FORMAT_PCM) && (waveformat->wBitsPerSample == 32)) {
|
||||
return AUDIO_S32SYS;
|
||||
} else if (waveformat->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
||||
const WAVEFORMATEXTENSIBLE *ext = (const WAVEFORMATEXTENSIBLE *)waveformat;
|
||||
if ((SDL_memcmp(&ext->SubFormat, &SDL_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID)) == 0) && (waveformat->wBitsPerSample == 32)) {
|
||||
return AUDIO_F32SYS;
|
||||
} else if ((SDL_memcmp(&ext->SubFormat, &SDL_KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)) == 0) && (waveformat->wBitsPerSample == 16)) {
|
||||
return AUDIO_S16SYS;
|
||||
} else if ((SDL_memcmp(&ext->SubFormat, &SDL_KSDATAFORMAT_SUBTYPE_PCM, sizeof(GUID)) == 0) && (waveformat->wBitsPerSample == 32)) {
|
||||
return AUDIO_S32SYS;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
WASAPI_RemoveDevice(const SDL_bool iscapture, LPCWSTR devid)
|
||||
{
|
||||
DevIdList *i;
|
||||
DevIdList *next;
|
||||
DevIdList *prev = NULL;
|
||||
for (i = deviceid_list; i; i = next) {
|
||||
next = i->next;
|
||||
if (SDL_wcscmp(i->str, devid) == 0) {
|
||||
if (prev) {
|
||||
prev->next = next;
|
||||
}
|
||||
else {
|
||||
deviceid_list = next;
|
||||
}
|
||||
SDL_RemoveAudioDevice(iscapture, i->str);
|
||||
SDL_free(i->str);
|
||||
SDL_free(i);
|
||||
} else {
|
||||
prev = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
WASAPI_AddDevice(const SDL_bool iscapture, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid)
|
||||
{
|
||||
DevIdList *devidlist;
|
||||
SDL_AudioSpec spec;
|
||||
|
||||
/* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever).
|
||||
In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for
|
||||
phones and tablets, where you might have an internal speaker and a headphone jack and expect both to be
|
||||
available and switch automatically. (!!! FIXME...?) */
|
||||
|
||||
/* see if we already have this one. */
|
||||
for (devidlist = deviceid_list; devidlist; devidlist = devidlist->next) {
|
||||
if (SDL_wcscmp(devidlist->str, devid) == 0) {
|
||||
return; /* we already have this. */
|
||||
}
|
||||
}
|
||||
|
||||
devidlist = (DevIdList *)SDL_malloc(sizeof(*devidlist));
|
||||
if (!devidlist) {
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
devid = SDL_wcsdup(devid);
|
||||
if (!devid) {
|
||||
SDL_free(devidlist);
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
devidlist->str = (WCHAR *)devid;
|
||||
devidlist->next = deviceid_list;
|
||||
deviceid_list = devidlist;
|
||||
|
||||
SDL_zero(spec);
|
||||
spec.channels = (Uint8)fmt->Format.nChannels;
|
||||
spec.freq = fmt->Format.nSamplesPerSec;
|
||||
spec.format = WaveFormatToSDLFormat((WAVEFORMATEX *)fmt);
|
||||
SDL_AddAudioDevice(iscapture, devname, &spec, (void *)devid);
|
||||
}
|
||||
|
||||
#endif // SDL_AUDIO_DRIVER_WASAPI && defined(__WINRT__)
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,13 @@
|
|||
#include "SDL_hints.h"
|
||||
#include "SDL_main.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_version.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
#include "SDL_system.h"
|
||||
#include "SDL_android.h"
|
||||
|
||||
#include "keyinfotable.h"
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../video/android/SDL_androidkeyboard.h"
|
||||
#include "../../video/android/SDL_androidmouse.h"
|
||||
|
|
@ -65,6 +64,9 @@
|
|||
#define ENCODING_PCM_FLOAT 4
|
||||
|
||||
/* Java class SDLActivity */
|
||||
JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetVersion)(
|
||||
JNIEnv *env, jclass cls);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(
|
||||
JNIEnv *env, jclass cls);
|
||||
|
||||
|
|
@ -169,6 +171,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePermissionResult)(
|
|||
jint requestCode, jboolean result);
|
||||
|
||||
static JNINativeMethod SDLActivity_tab[] = {
|
||||
{ "nativeGetVersion", "()Ljava/lang/String;", SDL_JAVA_INTERFACE(nativeGetVersion) },
|
||||
{ "nativeSetupJNI", "()I", SDL_JAVA_INTERFACE(nativeSetupJNI) },
|
||||
{ "nativeRunMain", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)I", SDL_JAVA_INTERFACE(nativeRunMain) },
|
||||
{ "onNativeDropFile", "(Ljava/lang/String;)V", SDL_JAVA_INTERFACE(onNativeDropFile) },
|
||||
|
|
@ -209,14 +212,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeGenerateScancod
|
|||
JNIEnv *env, jclass cls,
|
||||
jchar chUnicode);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
|
||||
JNIEnv *env, jclass cls,
|
||||
jstring text, jint newCursorPosition);
|
||||
|
||||
static JNINativeMethod SDLInputConnection_tab[] = {
|
||||
{ "nativeCommitText", "(Ljava/lang/String;I)V", SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText) },
|
||||
{ "nativeGenerateScancodeForUnichar", "(C)V", SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeGenerateScancodeForUnichar) },
|
||||
{ "nativeSetComposingText", "(Ljava/lang/String;I)V", SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText) }
|
||||
{ "nativeGenerateScancodeForUnichar", "(C)V", SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeGenerateScancodeForUnichar) }
|
||||
};
|
||||
|
||||
/* Java class SDLAudioManager */
|
||||
|
|
@ -511,9 +509,10 @@ register_methods(JNIEnv *env, const char *classname, JNINativeMethod *methods, i
|
|||
/* Library init */
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
mJavaVM = vm;
|
||||
JNIEnv *env = NULL;
|
||||
|
||||
mJavaVM = vm;
|
||||
|
||||
if ((*mJavaVM)->GetEnv(mJavaVM, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed to get JNI Env");
|
||||
return JNI_VERSION_1_4;
|
||||
|
|
@ -537,6 +536,16 @@ void checkJNIReady(void)
|
|||
SDL_SetMainReady();
|
||||
}
|
||||
|
||||
/* Get SDL version -- called before SDL_main() to verify JNI bindings */
|
||||
JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetVersion)(JNIEnv *env, jclass cls)
|
||||
{
|
||||
char version[128];
|
||||
|
||||
SDL_snprintf(version, sizeof(version), "%d.%d.%d", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);
|
||||
|
||||
return (*env)->NewStringUTF(env, version);
|
||||
}
|
||||
|
||||
/* Activity initialization -- called before SDL_main() to initialize JNI bindings */
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cls)
|
||||
{
|
||||
|
|
@ -1269,40 +1278,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeGenerateScancod
|
|||
JNIEnv *env, jclass cls,
|
||||
jchar chUnicode)
|
||||
{
|
||||
SDL_Scancode code = SDL_SCANCODE_UNKNOWN;
|
||||
uint16_t mod = 0;
|
||||
|
||||
/* We do not care about bigger than 127. */
|
||||
if (chUnicode < 127) {
|
||||
AndroidKeyInfo info = unicharToAndroidKeyInfoTable[chUnicode];
|
||||
code = info.code;
|
||||
mod = info.mod;
|
||||
}
|
||||
|
||||
if (mod & KMOD_SHIFT) {
|
||||
/* If character uses shift, press shift down */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
|
||||
}
|
||||
|
||||
/* send a keydown and keyup even for the character */
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, code);
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, code);
|
||||
|
||||
if (mod & KMOD_SHIFT) {
|
||||
/* If character uses shift, press shift back up */
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
|
||||
JNIEnv *env, jclass cls,
|
||||
jstring text, jint newCursorPosition)
|
||||
{
|
||||
const char *utftext = (*env)->GetStringUTFChars(env, text, NULL);
|
||||
|
||||
SDL_SendEditingText(utftext, 0, 0);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, text, utftext);
|
||||
SDL_SendKeyboardUnicodeKey(chUnicode);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
|
||||
|
|
@ -2553,6 +2529,7 @@ SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled)
|
|||
SDL_bool Android_JNI_RequestPermission(const char *permission)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
jstring jpermission;
|
||||
const int requestCode = 1;
|
||||
|
||||
/* Wait for any pending request on another thread */
|
||||
|
|
@ -2561,7 +2538,7 @@ SDL_bool Android_JNI_RequestPermission(const char *permission)
|
|||
}
|
||||
SDL_AtomicSet(&bPermissionRequestPending, SDL_TRUE);
|
||||
|
||||
jstring jpermission = (*env)->NewStringUTF(env, permission);
|
||||
jpermission = (*env)->NewStringUTF(env, permission);
|
||||
(*env)->CallStaticVoidMethod(env, mActivityClass, midRequestPermission, jpermission, requestCode);
|
||||
(*env)->DeleteLocalRef(env, jpermission);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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,175 +0,0 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 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 _ANDROID_KeyInfo
|
||||
#define _ANDROID_KeyInfo
|
||||
|
||||
#include "SDL_scancode.h"
|
||||
#include "SDL_keycode.h"
|
||||
|
||||
/*
|
||||
This file is used by the keyboard code in SDL_uikitview.m to convert between characters
|
||||
passed in from the iPhone's virtual keyboard, and tuples of SDL_Scancode and SDL_keymods.
|
||||
For example unicharToUIKeyInfoTable['a'] would give you the scan code and keymod for lower
|
||||
case a.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_Scancode code;
|
||||
uint16_t mod;
|
||||
} AndroidKeyInfo;
|
||||
|
||||
/* So far only ASCII characters here */
|
||||
static AndroidKeyInfo unicharToAndroidKeyInfoTable[] = {
|
||||
/* 0 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 1 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 2 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 3 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 4 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 5 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 6 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 7 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 8 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 9 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 10 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 11 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 12 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 13 */ { SDL_SCANCODE_RETURN, 0 },
|
||||
/* 14 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 15 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 16 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 17 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 18 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 19 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 20 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 21 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 22 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 23 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 24 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 25 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 26 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 27 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 28 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 29 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 30 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 31 */ { SDL_SCANCODE_UNKNOWN, 0 },
|
||||
/* 32 */ { SDL_SCANCODE_SPACE, 0 },
|
||||
/* 33 */ { SDL_SCANCODE_1, KMOD_SHIFT }, /* plus shift modifier '!' */
|
||||
/* 34 */ { SDL_SCANCODE_APOSTROPHE, KMOD_SHIFT }, /* plus shift modifier '"' */
|
||||
/* 35 */ { SDL_SCANCODE_3, KMOD_SHIFT }, /* plus shift modifier '#' */
|
||||
/* 36 */ { SDL_SCANCODE_4, KMOD_SHIFT }, /* plus shift modifier '$' */
|
||||
/* 37 */ { SDL_SCANCODE_5, KMOD_SHIFT }, /* plus shift modifier '%' */
|
||||
/* 38 */ { SDL_SCANCODE_7, KMOD_SHIFT }, /* plus shift modifier '&' */
|
||||
/* 39 */ { SDL_SCANCODE_APOSTROPHE, 0 }, /* ''' */
|
||||
/* 40 */ { SDL_SCANCODE_9, KMOD_SHIFT }, /* plus shift modifier '(' */
|
||||
/* 41 */ { SDL_SCANCODE_0, KMOD_SHIFT }, /* plus shift modifier ')' */
|
||||
/* 42 */ { SDL_SCANCODE_8, KMOD_SHIFT }, /* '*' */
|
||||
/* 43 */ { SDL_SCANCODE_EQUALS, KMOD_SHIFT }, /* plus shift modifier '+' */
|
||||
/* 44 */ { SDL_SCANCODE_COMMA, 0 }, /* ',' */
|
||||
/* 45 */ { SDL_SCANCODE_MINUS, 0 }, /* '-' */
|
||||
/* 46 */ { SDL_SCANCODE_PERIOD, 0 }, /* '.' */
|
||||
/* 47 */ { SDL_SCANCODE_SLASH, 0 }, /* '/' */
|
||||
/* 48 */ { SDL_SCANCODE_0, 0 },
|
||||
/* 49 */ { SDL_SCANCODE_1, 0 },
|
||||
/* 50 */ { SDL_SCANCODE_2, 0 },
|
||||
/* 51 */ { SDL_SCANCODE_3, 0 },
|
||||
/* 52 */ { SDL_SCANCODE_4, 0 },
|
||||
/* 53 */ { SDL_SCANCODE_5, 0 },
|
||||
/* 54 */ { SDL_SCANCODE_6, 0 },
|
||||
/* 55 */ { SDL_SCANCODE_7, 0 },
|
||||
/* 56 */ { SDL_SCANCODE_8, 0 },
|
||||
/* 57 */ { SDL_SCANCODE_9, 0 },
|
||||
/* 58 */ { SDL_SCANCODE_SEMICOLON, KMOD_SHIFT }, /* plus shift modifier ';' */
|
||||
/* 59 */ { SDL_SCANCODE_SEMICOLON, 0 },
|
||||
/* 60 */ { SDL_SCANCODE_COMMA, KMOD_SHIFT }, /* plus shift modifier '<' */
|
||||
/* 61 */ { SDL_SCANCODE_EQUALS, 0 },
|
||||
/* 62 */ { SDL_SCANCODE_PERIOD, KMOD_SHIFT }, /* plus shift modifier '>' */
|
||||
/* 63 */ { SDL_SCANCODE_SLASH, KMOD_SHIFT }, /* plus shift modifier '?' */
|
||||
/* 64 */ { SDL_SCANCODE_2, KMOD_SHIFT }, /* plus shift modifier '@' */
|
||||
/* 65 */ { SDL_SCANCODE_A, KMOD_SHIFT }, /* all the following need shift modifiers */
|
||||
/* 66 */ { SDL_SCANCODE_B, KMOD_SHIFT },
|
||||
/* 67 */ { SDL_SCANCODE_C, KMOD_SHIFT },
|
||||
/* 68 */ { SDL_SCANCODE_D, KMOD_SHIFT },
|
||||
/* 69 */ { SDL_SCANCODE_E, KMOD_SHIFT },
|
||||
/* 70 */ { SDL_SCANCODE_F, KMOD_SHIFT },
|
||||
/* 71 */ { SDL_SCANCODE_G, KMOD_SHIFT },
|
||||
/* 72 */ { SDL_SCANCODE_H, KMOD_SHIFT },
|
||||
/* 73 */ { SDL_SCANCODE_I, KMOD_SHIFT },
|
||||
/* 74 */ { SDL_SCANCODE_J, KMOD_SHIFT },
|
||||
/* 75 */ { SDL_SCANCODE_K, KMOD_SHIFT },
|
||||
/* 76 */ { SDL_SCANCODE_L, KMOD_SHIFT },
|
||||
/* 77 */ { SDL_SCANCODE_M, KMOD_SHIFT },
|
||||
/* 78 */ { SDL_SCANCODE_N, KMOD_SHIFT },
|
||||
/* 79 */ { SDL_SCANCODE_O, KMOD_SHIFT },
|
||||
/* 80 */ { SDL_SCANCODE_P, KMOD_SHIFT },
|
||||
/* 81 */ { SDL_SCANCODE_Q, KMOD_SHIFT },
|
||||
/* 82 */ { SDL_SCANCODE_R, KMOD_SHIFT },
|
||||
/* 83 */ { SDL_SCANCODE_S, KMOD_SHIFT },
|
||||
/* 84 */ { SDL_SCANCODE_T, KMOD_SHIFT },
|
||||
/* 85 */ { SDL_SCANCODE_U, KMOD_SHIFT },
|
||||
/* 86 */ { SDL_SCANCODE_V, KMOD_SHIFT },
|
||||
/* 87 */ { SDL_SCANCODE_W, KMOD_SHIFT },
|
||||
/* 88 */ { SDL_SCANCODE_X, KMOD_SHIFT },
|
||||
/* 89 */ { SDL_SCANCODE_Y, KMOD_SHIFT },
|
||||
/* 90 */ { SDL_SCANCODE_Z, KMOD_SHIFT },
|
||||
/* 91 */ { SDL_SCANCODE_LEFTBRACKET, 0 },
|
||||
/* 92 */ { SDL_SCANCODE_BACKSLASH, 0 },
|
||||
/* 93 */ { SDL_SCANCODE_RIGHTBRACKET, 0 },
|
||||
/* 94 */ { SDL_SCANCODE_6, KMOD_SHIFT }, /* plus shift modifier '^' */
|
||||
/* 95 */ { SDL_SCANCODE_MINUS, KMOD_SHIFT }, /* plus shift modifier '_' */
|
||||
/* 96 */ { SDL_SCANCODE_GRAVE, KMOD_SHIFT }, /* '`' */
|
||||
/* 97 */ { SDL_SCANCODE_A, 0 },
|
||||
/* 98 */ { SDL_SCANCODE_B, 0 },
|
||||
/* 99 */ { SDL_SCANCODE_C, 0 },
|
||||
/* 100 */{ SDL_SCANCODE_D, 0 },
|
||||
/* 101 */{ SDL_SCANCODE_E, 0 },
|
||||
/* 102 */{ SDL_SCANCODE_F, 0 },
|
||||
/* 103 */{ SDL_SCANCODE_G, 0 },
|
||||
/* 104 */{ SDL_SCANCODE_H, 0 },
|
||||
/* 105 */{ SDL_SCANCODE_I, 0 },
|
||||
/* 106 */{ SDL_SCANCODE_J, 0 },
|
||||
/* 107 */{ SDL_SCANCODE_K, 0 },
|
||||
/* 108 */{ SDL_SCANCODE_L, 0 },
|
||||
/* 109 */{ SDL_SCANCODE_M, 0 },
|
||||
/* 110 */{ SDL_SCANCODE_N, 0 },
|
||||
/* 111 */{ SDL_SCANCODE_O, 0 },
|
||||
/* 112 */{ SDL_SCANCODE_P, 0 },
|
||||
/* 113 */{ SDL_SCANCODE_Q, 0 },
|
||||
/* 114 */{ SDL_SCANCODE_R, 0 },
|
||||
/* 115 */{ SDL_SCANCODE_S, 0 },
|
||||
/* 116 */{ SDL_SCANCODE_T, 0 },
|
||||
/* 117 */{ SDL_SCANCODE_U, 0 },
|
||||
/* 118 */{ SDL_SCANCODE_V, 0 },
|
||||
/* 119 */{ SDL_SCANCODE_W, 0 },
|
||||
/* 120 */{ SDL_SCANCODE_X, 0 },
|
||||
/* 121 */{ SDL_SCANCODE_Y, 0 },
|
||||
/* 122 */{ SDL_SCANCODE_Z, 0 },
|
||||
/* 123 */{ SDL_SCANCODE_LEFTBRACKET, KMOD_SHIFT }, /* plus shift modifier '{' */
|
||||
/* 124 */{ SDL_SCANCODE_BACKSLASH, KMOD_SHIFT }, /* plus shift modifier '|' */
|
||||
/* 125 */{ SDL_SCANCODE_RIGHTBRACKET, KMOD_SHIFT }, /* plus shift modifier '}' */
|
||||
/* 126 */{ SDL_SCANCODE_GRAVE, KMOD_SHIFT }, /* plus shift modifier '~' */
|
||||
/* 127 */{ SDL_SCANCODE_BACKSPACE, KMOD_SHIFT }
|
||||
};
|
||||
|
||||
#endif /* _ANDROID_KeyInfo */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2023 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
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue