Merge branch 'main' into em-webgl-selector-hint

This commit is contained in:
Ryan C. Gordon
2022-11-23 13:22:23 -05:00
committed by GitHub
790 changed files with 241663 additions and 156407 deletions

View File

@@ -22,17 +22,9 @@
#if defined(__WIN32__) || defined(__GDK__)
#include "core/windows/SDL_windows.h"
#elif defined(__OS2__)
#include <stdlib.h> /* _exit() */
#elif !defined(__WINRT__)
#else
#include <unistd.h> /* _exit(), etc. */
#endif
#if defined(__OS2__)
#include "core/os2/SDL_os2.h"
#if SDL_THREAD_OS2
#include "thread/os2/SDL_systls_c.h"
#endif
#endif
/* this checks for HAVE_DBUS_DBUS_H internally. */
#include "core/linux/SDL_dbus.h"
@@ -124,17 +116,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 +137,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
@@ -196,10 +190,6 @@ SDL_InitSubSystem(Uint32 flags)
flags |= SDL_INIT_EVENTS;
}
#if SDL_THREAD_OS2
SDL_OS2TLSAlloc(); /* thread/os2/SDL_systls.c */
#endif
#if SDL_VIDEO_DRIVER_WINDOWS
if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
if (SDL_HelperWindowCreate() < 0) {
@@ -357,13 +347,6 @@ SDL_Init(Uint32 flags)
void
SDL_QuitSubSystem(Uint32 flags)
{
#if defined(__OS2__)
#if SDL_THREAD_OS2
SDL_OS2TLSFree(); /* thread/os2/SDL_systls.c */
#endif
SDL_OS2Quit();
#endif
/* Shut down requested initialized subsystems */
#if !SDL_SENSOR_DISABLED
if ((flags & SDL_INIT_SENSOR)) {
@@ -407,6 +390,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 +491,8 @@ SDL_Quit(void)
*/
SDL_memset( SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount) );
SDL_TLSCleanup();
SDL_bInMainQuit = SDL_FALSE;
}
@@ -512,7 +500,17 @@ SDL_Quit(void)
void
SDL_GetVersion(SDL_version * ver)
{
if (!ver) {
return;
}
SDL_VERSION(ver);
if (SDL_GetHintBoolean("SDL_LEGACY_VERSION", SDL_FALSE)) {
/* 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 */
@@ -577,14 +575,12 @@ SDL_GetPlatform(void)
return "Solaris";
#elif __WIN32__
return "Windows";
#elif __WINRT__
return "WinRT";
#elif __WINGDK__
return "WinGDK";
#elif __XBOXONE__
return "Xbox One";
#elif __XBOXSERIES__
return "Xbox Series";
return "Xbox Series X|S";
#elif __TVOS__
return "tvOS";
#elif __IPHONEOS__
@@ -597,6 +593,8 @@ SDL_GetPlatform(void)
return "PlayStation Vita";
#elif __NGAGE__
return "Nokia N-Gage";
#elif __3DS__
return "Nintendo 3DS";
#else
return "Unknown (see SDL_platform.h)";
#endif

View File

@@ -100,7 +100,7 @@ SDL_bool
SDL_ResetHint(const char *name)
{
const char *env;
SDL_Hint *hint, *prev;
SDL_Hint *hint;
SDL_HintWatch *entry;
if (!name) {
@@ -108,11 +108,11 @@ SDL_ResetHint(const char *name)
}
env = SDL_getenv(name);
for (prev = NULL, hint = SDL_hints; hint; prev = hint, hint = hint->next) {
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 && SDL_strcmp(env, hint->value) != 0)) {
(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;
@@ -120,19 +120,40 @@ SDL_ResetHint(const char *name)
entry = next;
}
}
if (prev) {
prev->next = hint->next;
} else {
SDL_hints = hint->next;
}
SDL_free(hint->value);
SDL_free(hint);
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)
{
@@ -148,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;

View File

@@ -55,7 +55,7 @@
#define O_CLOEXEC 0
#endif
/* A few #defines to reduce SDL2 footprint.
/* A few #defines to reduce SDL footprint.
Only effective when library is statically linked.
You have to manually edit this file. */
#ifndef SDL_LEAN_AND_MEAN

View File

@@ -20,7 +20,7 @@
*/
#include "./SDL_internal.h"
#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
#if defined(__WIN32__) || defined(__GDK__)
#include "core/windows/SDL_windows.h"
#endif
@@ -366,7 +366,7 @@ SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list
}
}
#if defined(__WIN32__) && !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__)
#if defined(__WIN32__) && !defined(HAVE_STDIO_H) && !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;
@@ -378,7 +378,7 @@ static void SDLCALL
SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
const char *message)
{
#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
#if defined(__WIN32__) || defined(__GDK__)
/* Way too many allocations here, urgh */
/* Note: One can't call SDL_SetError here, since that function itself logs. */
{
@@ -387,7 +387,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
LPTSTR tstr;
SDL_bool isstack;
#if !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__)
#if !defined(HAVE_STDIO_H) && !defined(__GDK__)
BOOL attachResult;
DWORD attachError;
DWORD charsWritten;
@@ -426,7 +426,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
}
}
}
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__) */
#endif /* !defined(HAVE_STDIO_H) && !defined(__GDK__) */
length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
output = SDL_small_alloc(char, length, &isstack);
@@ -436,7 +436,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
/* Output to debugger */
OutputDebugString(tstr);
#if !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__)
#if !defined(HAVE_STDIO_H) && !defined(__GDK__)
/* Screen output to stderr, if console was attached. */
if (consoleAttached == 1) {
if (!WriteConsole(stderrHandle, tstr, (DWORD) SDL_tcslen(tstr), &charsWritten, NULL)) {
@@ -451,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__) && !defined(__GDK__) */
#endif /* !defined(HAVE_STDIO_H) && !defined(__GDK__) */
SDL_free(tstr);
SDL_small_free(output, isstack);
@@ -485,12 +485,17 @@ 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);
#endif
#endif
}

View File

@@ -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,19 +230,16 @@ 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);
#elif defined(HAVE_GCC_ATOMICS)
return __sync_fetch_and_add(&a->value, 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
int pv = a->value;
membar_consumer();
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 {

View File

@@ -20,7 +20,7 @@
*/
#include "../SDL_internal.h"
#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
#if defined(__WIN32__) || defined(__GDK__)
#include "../core/windows/SDL_windows.h"
#endif

View File

@@ -48,45 +48,18 @@ static const AudioBootStrap *const bootstrap[] = {
#if SDL_AUDIO_DRIVER_NETBSD
&NETBSDAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_QSA
&QSAAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_SUNAUDIO
&SUNAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_ARTS
&ARTS_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_ESD
&ESD_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_NACL
&NACLAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_NAS
&NAS_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_WASAPI
&WASAPI_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_DSOUND
&DSOUND_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_WINMM
&WINMM_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_PAUDIO
&PAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_HAIKU
&HAIKUAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_COREAUDIO
&COREAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_FUSIONSOUND
&FUSIONSOUND_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_AAUDIO
&aaudio_bootstrap,
#endif
@@ -105,6 +78,9 @@ static const AudioBootStrap *const bootstrap[] = {
#if SDL_AUDIO_DRIVER_VITA
&VITAAUD_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_N3DS
&N3DSAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_EMSCRIPTEN
&EMSCRIPTENAUDIO_bootstrap,
#endif
@@ -117,9 +93,6 @@ static const AudioBootStrap *const bootstrap[] = {
#if SDL_AUDIO_DRIVER_OSS
&DSP_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_OS2
&OS2AUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_DISK
&DISKAUDIO_bootstrap,
#endif
@@ -141,6 +114,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)
@@ -175,8 +149,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;
@@ -187,6 +162,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;
@@ -1313,7 +1289,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) {
@@ -1323,6 +1299,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;
}
@@ -1330,6 +1307,7 @@ open_audio_device(const char *devname, int iscapture,
obtained = &_obtained;
}
if (!prepare_audiospec(desired, obtained)) {
SDL_UnlockMutex(current_audio.detectionLock);
return 0;
}
@@ -1351,6 +1329,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;
@@ -1358,11 +1337,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;
}
@@ -1370,6 +1351,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;
}
@@ -1382,20 +1364,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;
}
}
@@ -1403,6 +1384,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;
@@ -1419,6 +1401,7 @@ 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;
}
@@ -1433,6 +1416,7 @@ open_audio_device(const char *devname, int iscapture,
if (current_audio.impl.OpenDevice(device, devname) < 0) {
close_audio_device(device);
SDL_UnlockMutex(current_audio.detectionLock);
return 0;
}
@@ -1488,6 +1472,7 @@ open_audio_device(const char *devname, int iscapture,
if (!device->stream) {
close_audio_device(device);
SDL_UnlockMutex(current_audio.detectionLock);
return 0;
}
}
@@ -1497,6 +1482,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;
}
@@ -1514,6 +1500,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;
}
@@ -1534,9 +1521,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;
}

View File

@@ -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 */

View File

@@ -247,7 +247,7 @@ SDL_ResampleAudio(const int chans, const int inrate, const int outrate,
*(dst++) = outsample;
}
outtime += outtimeincr;
outtime = outtimeincr * i;
}
return outframes * chans * sizeof (float);
@@ -403,7 +403,8 @@ SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
cvt->len_mult *= mult;
cvt->len_ratio *= mult;
} else if (src_bitsize > dst_bitsize) {
cvt->len_ratio /= (src_bitsize / dst_bitsize);
const int div = (src_bitsize / dst_bitsize);
cvt->len_ratio /= div;
}
retval = 1; /* added a converter. */
}
@@ -418,6 +419,48 @@ SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
return retval;
}
#ifdef HAVE_LIBSAMPLERATE_H
static void
SDL_ResampleCVT_SRC(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
{
const float *src = (const float *) cvt->buf;
const int srclen = cvt->len_cvt;
float *dst = (float *) (cvt->buf + srclen);
const int dstlen = (cvt->len * cvt->len_mult) - srclen;
const int framelen = sizeof(float) * chans;
int result = 0;
SRC_DATA data;
SDL_zero(data);
data.data_in = (float *)src; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
data.input_frames = srclen / framelen;
data.data_out = dst;
data.output_frames = dstlen / framelen;
data.src_ratio = cvt->rate_incr;
result = SRC_src_simple(&data, SRC_converter, chans); /* Simple API converts the whole buffer at once. No need for initialization. */
/* !!! FIXME: Handle library failures? */
#ifdef DEBUG_CONVERT
if (result != 0) {
SDL_Log("src_simple() failed: %s", SRC_src_strerror(result));
}
#endif
cvt->len_cvt = data.output_frames_gen * framelen;
SDL_memmove(cvt->buf, dst, cvt->len_cvt);
if (cvt->filters[++cvt->filter_index]) {
cvt->filters[cvt->filter_index](cvt, format);
}
}
#endif /* HAVE_LIBSAMPLERATE_H */
static void
SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
{
@@ -478,9 +521,36 @@ RESAMPLER_FUNCS(6)
RESAMPLER_FUNCS(8)
#undef RESAMPLER_FUNCS
#ifdef HAVE_LIBSAMPLERATE_H
#define RESAMPLER_FUNCS(chans) \
static void SDLCALL \
SDL_ResampleCVT_SRC_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
SDL_ResampleCVT_SRC(cvt, chans, format); \
}
RESAMPLER_FUNCS(1)
RESAMPLER_FUNCS(2)
RESAMPLER_FUNCS(4)
RESAMPLER_FUNCS(6)
RESAMPLER_FUNCS(8)
#undef RESAMPLER_FUNCS
#endif /* HAVE_LIBSAMPLERATE_H */
static SDL_AudioFilter
ChooseCVTResampler(const int dst_channels)
{
#ifdef HAVE_LIBSAMPLERATE_H
if (SRC_available) {
switch (dst_channels) {
case 1: return SDL_ResampleCVT_SRC_c1;
case 2: return SDL_ResampleCVT_SRC_c2;
case 4: return SDL_ResampleCVT_SRC_c4;
case 6: return SDL_ResampleCVT_SRC_c6;
case 8: return SDL_ResampleCVT_SRC_c8;
default: break;
}
}
#endif /* HAVE_LIBSAMPLERATE_H */
switch (dst_channels) {
case 1: return SDL_ResampleCVT_c1;
case 2: return SDL_ResampleCVT_c2;

View File

@@ -188,29 +188,21 @@ extern AudioBootStrap JACK_bootstrap;
extern AudioBootStrap SNDIO_bootstrap;
extern AudioBootStrap NETBSDAUDIO_bootstrap;
extern AudioBootStrap DSP_bootstrap;
extern AudioBootStrap QSAAUDIO_bootstrap;
extern AudioBootStrap SUNAUDIO_bootstrap;
extern AudioBootStrap ARTS_bootstrap;
extern AudioBootStrap ESD_bootstrap;
extern AudioBootStrap NACLAUDIO_bootstrap;
extern AudioBootStrap NAS_bootstrap;
extern AudioBootStrap WASAPI_bootstrap;
extern AudioBootStrap DSOUND_bootstrap;
extern AudioBootStrap WINMM_bootstrap;
extern AudioBootStrap PAUDIO_bootstrap;
extern AudioBootStrap HAIKUAUDIO_bootstrap;
extern AudioBootStrap COREAUDIO_bootstrap;
extern AudioBootStrap DISKAUDIO_bootstrap;
extern AudioBootStrap DUMMYAUDIO_bootstrap;
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;
#endif /* SDL_sysaudio_h_ */

View File

@@ -1,357 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_ARTS
/* Allow access to a raw mixing buffer */
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <unistd.h>
#include <errno.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_artsaudio.h"
#ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
#include "SDL_name.h"
#include "SDL_loadso.h"
#else
#define SDL_NAME(X) X
#endif
#ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
static const char *arts_library = SDL_AUDIO_DRIVER_ARTS_DYNAMIC;
static void *arts_handle = NULL;
/* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */
static int (*SDL_NAME(arts_init)) (void);
static void (*SDL_NAME(arts_free)) (void);
static arts_stream_t(*SDL_NAME(arts_play_stream)) (int rate, int bits,
int channels,
const char *name);
static int (*SDL_NAME(arts_stream_set)) (arts_stream_t s,
arts_parameter_t param, int value);
static int (*SDL_NAME(arts_stream_get)) (arts_stream_t s,
arts_parameter_t param);
static int (*SDL_NAME(arts_write)) (arts_stream_t s, const void *buffer,
int count);
static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
static int (*SDL_NAME(arts_suspend))(void);
static int (*SDL_NAME(arts_suspended)) (void);
static const char *(*SDL_NAME(arts_error_text)) (int errorcode);
#define SDL_ARTS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
static struct
{
const char *name;
void **func;
} arts_functions[] = {
/* *INDENT-OFF* */
SDL_ARTS_SYM(arts_init),
SDL_ARTS_SYM(arts_free),
SDL_ARTS_SYM(arts_play_stream),
SDL_ARTS_SYM(arts_stream_set),
SDL_ARTS_SYM(arts_stream_get),
SDL_ARTS_SYM(arts_write),
SDL_ARTS_SYM(arts_close_stream),
SDL_ARTS_SYM(arts_suspend),
SDL_ARTS_SYM(arts_suspended),
SDL_ARTS_SYM(arts_error_text),
/* *INDENT-ON* */
};
#undef SDL_ARTS_SYM
static void
UnloadARTSLibrary()
{
if (arts_handle != NULL) {
SDL_UnloadObject(arts_handle);
arts_handle = NULL;
}
}
static int
LoadARTSLibrary(void)
{
int i, retval = -1;
if (arts_handle == NULL) {
arts_handle = SDL_LoadObject(arts_library);
if (arts_handle != NULL) {
retval = 0;
for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
*arts_functions[i].func =
SDL_LoadFunction(arts_handle, arts_functions[i].name);
if (!*arts_functions[i].func) {
retval = -1;
UnloadARTSLibrary();
break;
}
}
}
}
return retval;
}
#else
static void
UnloadARTSLibrary()
{
return;
}
static int
LoadARTSLibrary(void)
{
return 0;
}
#endif /* SDL_AUDIO_DRIVER_ARTS_DYNAMIC */
/* This function waits until it is possible to write a full sound buffer */
static void
ARTS_WaitDevice(_THIS)
{
Sint32 ticks;
/* Check to see if the thread-parent process is still alive */
{
static int cnt = 0;
/* Note that this only works with thread implementations
that use a different process id for each thread.
*/
/* Check every 10 loops */
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
SDL_OpenedAudioDeviceDisconnected(this);
}
}
}
/* Use timer for general audio synchronization */
ticks =
((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
if (ticks > 0) {
SDL_Delay(ticks);
}
}
static void
ARTS_PlayDevice(_THIS)
{
/* Write the audio data */
int written = SDL_NAME(arts_write) (this->hidden->stream,
this->hidden->mixbuf,
this->hidden->mixlen);
/* If timer synchronization is enabled, set the next write frame */
if (this->hidden->frame_ticks) {
this->hidden->next_frame += this->hidden->frame_ticks;
}
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
#endif
}
static Uint8 *
ARTS_GetDeviceBuf(_THIS)
{
return (this->hidden->mixbuf);
}
static void
ARTS_CloseDevice(_THIS)
{
if (this->hidden->stream) {
SDL_NAME(arts_close_stream) (this->hidden->stream);
}
SDL_NAME(arts_free) ();
SDL_free(this->hidden->mixbuf);
SDL_free(this->hidden);
}
static int
ARTS_Suspend(void)
{
const Uint32 abortms = SDL_GetTicks() + 3000; /* give up after 3 secs */
while ( (!SDL_NAME(arts_suspended)()) && !SDL_TICKS_PASSED(SDL_GetTicks(), abortms) ) {
if ( SDL_NAME(arts_suspend)() ) {
break;
}
}
return SDL_NAME(arts_suspended)();
}
static int
ARTS_OpenDevice(_THIS, const char *devname)
{
int rc = 0;
int bits, frag_spec = 0;
SDL_AudioFormat test_format = 0;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
switch (test_format) {
case AUDIO_U8:
case AUDIO_S16LSB:
break;
default:
continue;
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "arts");
}
this->spec.format = test_format;
bits = SDL_AUDIO_BITSIZE(test_format);
if ((rc = SDL_NAME(arts_init) ()) != 0) {
return SDL_SetError("Unable to initialize ARTS: %s",
SDL_NAME(arts_error_text) (rc));
}
if (!ARTS_Suspend()) {
return SDL_SetError("ARTS can not open audio device");
}
this->hidden->stream = SDL_NAME(arts_play_stream) (this->spec.freq,
bits,
this->spec.channels,
"SDL");
/* Play nothing so we have at least one write (server bug workaround). */
SDL_NAME(arts_write) (this->hidden->stream, "", 0);
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
/* Determine the power of two of the fragment size */
for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
if ((0x01 << frag_spec) != this->spec.size) {
return SDL_SetError("Fragment size must be a power of two");
}
frag_spec |= 0x00020000; /* two fragments, for low latency */
#ifdef ARTS_P_PACKET_SETTINGS
SDL_NAME(arts_stream_set) (this->hidden->stream,
ARTS_P_PACKET_SETTINGS, frag_spec);
#else
SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_SIZE,
frag_spec & 0xffff);
SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_COUNT,
frag_spec >> 16);
#endif
this->spec.size = SDL_NAME(arts_stream_get) (this->hidden->stream,
ARTS_P_PACKET_SIZE);
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
/* Get the parent process id (we're the parent of the audio thread) */
this->hidden->parent = getpid();
/* We're ready to rock and roll. :-) */
return 0;
}
static void
ARTS_Deinitialize(void)
{
UnloadARTSLibrary();
}
static SDL_bool
ARTS_Init(SDL_AudioDriverImpl * impl)
{
if (LoadARTSLibrary() < 0) {
return SDL_FALSE;
} else {
if (SDL_NAME(arts_init) () != 0) {
UnloadARTSLibrary();
SDL_SetError("ARTS: arts_init failed (no audio server?)");
return SDL_FALSE;
}
/* Play a stream so aRts doesn't crash */
if (ARTS_Suspend()) {
arts_stream_t stream;
stream = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
SDL_NAME(arts_write) (stream, "", 0);
SDL_NAME(arts_close_stream) (stream);
}
SDL_NAME(arts_free) ();
}
/* Set the function pointers */
impl->OpenDevice = ARTS_OpenDevice;
impl->PlayDevice = ARTS_PlayDevice;
impl->WaitDevice = ARTS_WaitDevice;
impl->GetDeviceBuf = ARTS_GetDeviceBuf;
impl->CloseDevice = ARTS_CloseDevice;
impl->Deinitialize = ARTS_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap ARTS_bootstrap = {
"arts", "Analog RealTime Synthesizer", ARTS_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_ARTS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,53 +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.
*/
#include "../../SDL_internal.h"
#ifndef SDL_artsaudio_h_
#define SDL_artsaudio_h_
#include <artsc.h>
#include "../SDL_sysaudio.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData
{
/* The stream descriptor for the audio device */
arts_stream_t stream;
/* The parent process id, to detect when application quits */
pid_t parent;
/* Raw mixing buffer */
Uint8 *mixbuf;
int mixlen;
/* Support for audio timing using a timer, in addition to SDL_IOReady() */
float frame_ticks;
float next_frame;
};
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
#endif /* SDL_artsaudio_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -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;

View File

@@ -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;
@@ -952,7 +960,7 @@ audioqueue_thread(void *arg)
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. */
@@ -973,7 +981,7 @@ 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
@@ -1123,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. */
@@ -1145,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)
{
@@ -1162,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;

View File

@@ -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"

View File

@@ -38,10 +38,10 @@ FeedAudioDevice(_THIS, const void *buf, const int buflen)
{
const int framelen = (SDL_AUDIO_BITSIZE(this->spec.format) / 8) * this->spec.channels;
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels'];
var SDL3 = Module['SDL3'];
var numChannels = SDL3.audio.currentOutputBuffer['numberOfChannels'];
for (var c = 0; c < numChannels; ++c) {
var channelData = SDL2.audio.currentOutputBuffer['getChannelData'](c);
var channelData = SDL3.audio.currentOutputBuffer['getChannelData'](c);
if (channelData.length != $1) {
throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
}
@@ -107,10 +107,10 @@ HandleCaptureProcess(_THIS)
}
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
var SDL3 = Module['SDL3'];
var numChannels = SDL3.capture.currentCaptureBuffer.numberOfChannels;
for (var c = 0; c < numChannels; ++c) {
var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(c);
var channelData = SDL3.capture.currentCaptureBuffer.getChannelData(c);
if (channelData.length != $1) {
throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
}
@@ -153,45 +153,45 @@ static void
EMSCRIPTENAUDIO_CloseDevice(_THIS)
{
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var SDL3 = Module['SDL3'];
if ($0) {
if (SDL2.capture.silenceTimer !== undefined) {
clearTimeout(SDL2.capture.silenceTimer);
if (SDL3.capture.silenceTimer !== undefined) {
clearTimeout(SDL3.capture.silenceTimer);
}
if (SDL2.capture.stream !== undefined) {
var tracks = SDL2.capture.stream.getAudioTracks();
if (SDL3.capture.stream !== undefined) {
var tracks = SDL3.capture.stream.getAudioTracks();
for (var i = 0; i < tracks.length; i++) {
SDL2.capture.stream.removeTrack(tracks[i]);
SDL3.capture.stream.removeTrack(tracks[i]);
}
SDL2.capture.stream = undefined;
SDL3.capture.stream = undefined;
}
if (SDL2.capture.scriptProcessorNode !== undefined) {
SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
SDL2.capture.scriptProcessorNode.disconnect();
SDL2.capture.scriptProcessorNode = undefined;
if (SDL3.capture.scriptProcessorNode !== undefined) {
SDL3.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
SDL3.capture.scriptProcessorNode.disconnect();
SDL3.capture.scriptProcessorNode = undefined;
}
if (SDL2.capture.mediaStreamNode !== undefined) {
SDL2.capture.mediaStreamNode.disconnect();
SDL2.capture.mediaStreamNode = undefined;
if (SDL3.capture.mediaStreamNode !== undefined) {
SDL3.capture.mediaStreamNode.disconnect();
SDL3.capture.mediaStreamNode = undefined;
}
if (SDL2.capture.silenceBuffer !== undefined) {
SDL2.capture.silenceBuffer = undefined
if (SDL3.capture.silenceBuffer !== undefined) {
SDL3.capture.silenceBuffer = undefined
}
SDL2.capture = undefined;
SDL3.capture = undefined;
} else {
if (SDL2.audio.scriptProcessorNode != undefined) {
SDL2.audio.scriptProcessorNode.disconnect();
SDL2.audio.scriptProcessorNode = undefined;
if (SDL3.audio.scriptProcessorNode != undefined) {
SDL3.audio.scriptProcessorNode.disconnect();
SDL3.audio.scriptProcessorNode = undefined;
}
SDL2.audio = undefined;
SDL3.audio = undefined;
}
if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) {
SDL2.audioContext.close();
SDL2.audioContext = undefined;
if ((SDL3.audioContext !== undefined) && (SDL3.audio === undefined) && (SDL3.capture === undefined)) {
SDL3.audioContext.close();
SDL3.audioContext = undefined;
}
}, this->iscapture);
#if 0 /* !!! FIXME: currently not used. Can we move some stuff off the SDL2 namespace? --ryan. */
#if 0 /* !!! FIXME: currently not used. Can we move some stuff off the SDL3 namespace? --ryan. */
SDL_free(this->hidden);
#endif
}
@@ -207,27 +207,27 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
/* create context */
result = MAIN_THREAD_EM_ASM_INT({
if(typeof(Module['SDL2']) === 'undefined') {
Module['SDL2'] = {};
if(typeof(Module['SDL3']) === 'undefined') {
Module['SDL3'] = {};
}
var SDL2 = Module['SDL2'];
var SDL3 = Module['SDL3'];
if (!$0) {
SDL2.audio = {};
SDL3.audio = {};
} else {
SDL2.capture = {};
SDL3.capture = {};
}
if (!SDL2.audioContext) {
if (!SDL3.audioContext) {
if (typeof(AudioContext) !== 'undefined') {
SDL2.audioContext = new AudioContext();
SDL3.audioContext = new AudioContext();
} else if (typeof(webkitAudioContext) !== 'undefined') {
SDL2.audioContext = new webkitAudioContext();
SDL3.audioContext = new webkitAudioContext();
}
if (SDL2.audioContext) {
autoResumeAudioContext(SDL2.audioContext);
if (SDL3.audioContext) {
autoResumeAudioContext(SDL3.audioContext);
}
}
return SDL2.audioContext === undefined ? -1 : 0;
return SDL3.audioContext === undefined ? -1 : 0;
}, iscapture);
if (result < 0) {
return SDL_SetError("Web Audio API is not available!");
@@ -250,7 +250,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
this->spec.format = test_format;
/* Initialize all variables that we clean on shutdown */
#if 0 /* !!! FIXME: currently not used. Can we move some stuff off the SDL2 namespace? --ryan. */
#if 0 /* !!! FIXME: currently not used. Can we move some stuff off the SDL3 namespace? --ryan. */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
@@ -262,8 +262,8 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
/* limit to native freq */
this->spec.freq = EM_ASM_INT_V({
var SDL2 = Module['SDL2'];
return SDL2.audioContext.sampleRate;
var SDL3 = Module['SDL3'];
return SDL3.audioContext.sampleRate;
});
SDL_CalculateAudioSpec(&this->spec);
@@ -286,24 +286,24 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
to be honest. */
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var SDL3 = Module['SDL3'];
var have_microphone = function(stream) {
//console.log('SDL audio capture: we have a microphone! Replacing silence callback.');
if (SDL2.capture.silenceTimer !== undefined) {
clearTimeout(SDL2.capture.silenceTimer);
SDL2.capture.silenceTimer = undefined;
if (SDL3.capture.silenceTimer !== undefined) {
clearTimeout(SDL3.capture.silenceTimer);
SDL3.capture.silenceTimer = undefined;
}
SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(stream);
SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1);
SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {
if ((SDL2 === undefined) || (SDL2.capture === undefined)) { return; }
SDL3.capture.mediaStreamNode = SDL3.audioContext.createMediaStreamSource(stream);
SDL3.capture.scriptProcessorNode = SDL3.audioContext.createScriptProcessor($1, $0, 1);
SDL3.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {
if ((SDL3 === undefined) || (SDL3.capture === undefined)) { return; }
audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
SDL3.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
dynCall('vi', $2, [$3]);
};
SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
SDL2.capture.stream = stream;
SDL3.capture.mediaStreamNode.connect(SDL3.capture.scriptProcessorNode);
SDL3.capture.scriptProcessorNode.connect(SDL3.audioContext.destination);
SDL3.capture.stream = stream;
};
var no_microphone = function(error) {
@@ -311,14 +311,14 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
};
/* we write silence to the audio callback until the microphone is available (user approves use, etc). */
SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate);
SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0);
SDL3.capture.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate);
SDL3.capture.silenceBuffer.getChannelData(0).fill(0.0);
var silence_callback = function() {
SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
SDL3.capture.currentCaptureBuffer = SDL3.capture.silenceBuffer;
dynCall('vi', $2, [$3]);
};
SDL2.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000);
SDL3.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000);
if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) {
navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone);
@@ -329,14 +329,14 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
} else {
/* setup a ScriptProcessorNode */
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
if ((SDL2 === undefined) || (SDL2.audio === undefined)) { return; }
SDL2.audio.currentOutputBuffer = e['outputBuffer'];
var SDL3 = Module['SDL3'];
SDL3.audio.scriptProcessorNode = SDL3.audioContext['createScriptProcessor']($1, 0, $0);
SDL3.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
if ((SDL3 === undefined) || (SDL3.audio === undefined)) { return; }
SDL3.audio.currentOutputBuffer = e['outputBuffer'];
dynCall('vi', $2, [$3]);
};
SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
SDL3.audio.scriptProcessorNode['connect'](SDL3.audioContext['destination']);
}, this->spec.channels, this->spec.samples, HandleAudioProcess, this);
}

View File

@@ -1,335 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_ESD
/* Allow access to an ESD network stream mixing buffer */
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <esd.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_esdaudio.h"
#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
#include "SDL_name.h"
#include "SDL_loadso.h"
#else
#define SDL_NAME(X) X
#endif
#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC;
static void *esd_handle = NULL;
static int (*SDL_NAME(esd_open_sound)) (const char *host);
static int (*SDL_NAME(esd_close)) (int esd);
static int (*SDL_NAME(esd_play_stream)) (esd_format_t format, int rate,
const char *host, const char *name);
#define SDL_ESD_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
static struct
{
const char *name;
void **func;
} const esd_functions[] = {
SDL_ESD_SYM(esd_open_sound),
SDL_ESD_SYM(esd_close), SDL_ESD_SYM(esd_play_stream),
};
#undef SDL_ESD_SYM
static void
UnloadESDLibrary()
{
if (esd_handle != NULL) {
SDL_UnloadObject(esd_handle);
esd_handle = NULL;
}
}
static int
LoadESDLibrary(void)
{
int i, retval = -1;
if (esd_handle == NULL) {
esd_handle = SDL_LoadObject(esd_library);
if (esd_handle) {
retval = 0;
for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
*esd_functions[i].func =
SDL_LoadFunction(esd_handle, esd_functions[i].name);
if (!*esd_functions[i].func) {
retval = -1;
UnloadESDLibrary();
break;
}
}
}
}
return retval;
}
#else
static void
UnloadESDLibrary()
{
return;
}
static int
LoadESDLibrary(void)
{
return 0;
}
#endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */
/* This function waits until it is possible to write a full sound buffer */
static void
ESD_WaitDevice(_THIS)
{
Sint32 ticks;
/* Check to see if the thread-parent process is still alive */
{
static int cnt = 0;
/* Note that this only works with thread implementations
that use a different process id for each thread.
*/
/* Check every 10 loops */
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
SDL_OpenedAudioDeviceDisconnected(this);
}
}
}
/* Use timer for general audio synchronization */
ticks = ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
if (ticks > 0) {
SDL_Delay(ticks);
}
}
static void
ESD_PlayDevice(_THIS)
{
int written = 0;
/* Write the audio data, checking for EAGAIN on broken audio drivers */
do {
written = write(this->hidden->audio_fd,
this->hidden->mixbuf, this->hidden->mixlen);
if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
SDL_Delay(1); /* Let a little CPU time go by */
}
} while ((written < 0) &&
((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
/* Set the next write frame */
this->hidden->next_frame += this->hidden->frame_ticks;
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
}
}
static Uint8 *
ESD_GetDeviceBuf(_THIS)
{
return (this->hidden->mixbuf);
}
static void
ESD_CloseDevice(_THIS)
{
if (this->hidden->audio_fd >= 0) {
SDL_NAME(esd_close) (this->hidden->audio_fd);
}
SDL_free(this->hidden->mixbuf);
SDL_free(this->hidden);
}
/* Try to get the name of the program */
static char *
get_progname(void)
{
char *progname = NULL;
#ifdef __LINUX__
FILE *fp;
static char temp[BUFSIZ];
SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid());
fp = fopen(temp, "r");
if (fp != NULL) {
if (fgets(temp, sizeof(temp) - 1, fp)) {
progname = SDL_strrchr(temp, '/');
if (progname == NULL) {
progname = temp;
} else {
progname = progname + 1;
}
}
fclose(fp);
}
#endif
return (progname);
}
static int
ESD_OpenDevice(_THIS, const char *devname)
{
esd_format_t format = (ESD_STREAM | ESD_PLAY);
SDL_AudioFormat test_format = 0;
int found = 0;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
SDL_zerop(this->hidden);
this->hidden->audio_fd = -1;
/* Convert audio spec to the ESD audio format */
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format);
!found && test_format; test_format = SDL_NextAudioFormat()) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
found = 1;
switch (test_format) {
case AUDIO_U8:
format |= ESD_BITS8;
break;
case AUDIO_S16SYS:
format |= ESD_BITS16;
break;
default:
found = 0;
break;
}
}
if (!found) {
return SDL_SetError("Couldn't find any hardware audio formats");
}
if (this->spec.channels == 1) {
format |= ESD_MONO;
} else {
format |= ESD_STEREO;
}
#if 0
this->spec.samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */
#endif
/* Open a connection to the ESD audio server */
this->hidden->audio_fd =
SDL_NAME(esd_play_stream) (format, this->spec.freq, NULL,
get_progname());
if (this->hidden->audio_fd < 0) {
return SDL_SetError("Couldn't open ESD connection");
}
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
this->hidden->frame_ticks =
(float) (this->spec.samples * 1000) / this->spec.freq;
this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
/* Get the parent process id (we're the parent of the audio thread) */
this->hidden->parent = getpid();
/* We're ready to rock and roll. :-) */
return 0;
}
static void
ESD_Deinitialize(void)
{
UnloadESDLibrary();
}
static SDL_bool
ESD_Init(SDL_AudioDriverImpl * impl)
{
if (LoadESDLibrary() < 0) {
return SDL_FALSE;
} else {
int connection = 0;
/* Don't start ESD if it's not running */
SDL_setenv("ESD_NO_SPAWN", "1", 0);
connection = SDL_NAME(esd_open_sound) (NULL);
if (connection < 0) {
UnloadESDLibrary();
SDL_SetError("ESD: esd_open_sound failed (no audio server?)");
return SDL_FALSE;
}
SDL_NAME(esd_close) (connection);
}
/* Set the function pointers */
impl->OpenDevice = ESD_OpenDevice;
impl->PlayDevice = ESD_PlayDevice;
impl->WaitDevice = ESD_WaitDevice;
impl->GetDeviceBuf = ESD_GetDeviceBuf;
impl->CloseDevice = ESD_CloseDevice;
impl->Deinitialize = ESD_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap ESD_bootstrap = {
"esd", "Enlightened Sound Daemon", ESD_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_ESD */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,51 +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.
*/
#include "../../SDL_internal.h"
#ifndef SDL_esdaudio_h_
#define SDL_esdaudio_h_
#include "../SDL_sysaudio.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData
{
/* The file descriptor for the audio device */
int audio_fd;
/* The parent process id, to detect when application quits */
pid_t parent;
/* Raw mixing buffer */
Uint8 *mixbuf;
int mixlen;
/* Support for audio timing using a timer */
float frame_ticks;
float next_frame;
};
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
#endif /* SDL_esdaudio_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,317 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_FUSIONSOUND
/* !!! FIXME: why is this is SDL_FS_* instead of FUSIONSOUND_*? */
/* Allow access to a raw mixing buffer */
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <unistd.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_fsaudio.h"
#include <fusionsound/fusionsound_version.h>
/* #define SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC "libfusionsound.so" */
#ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
#include "SDL_name.h"
#include "SDL_loadso.h"
#else
#define SDL_NAME(X) X
#endif
#if (FUSIONSOUND_MAJOR_VERSION == 1) && (FUSIONSOUND_MINOR_VERSION < 1)
typedef DFBResult DirectResult;
#endif
/* Buffers to use - more than 2 gives a lot of latency */
#define FUSION_BUFFERS (2)
#ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
static const char *fs_library = SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC;
static void *fs_handle = NULL;
static DirectResult (*SDL_NAME(FusionSoundInit)) (int *argc, char *(*argv[]));
static DirectResult (*SDL_NAME(FusionSoundCreate)) (IFusionSound **
ret_interface);
#define SDL_FS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
static struct
{
const char *name;
void **func;
} fs_functions[] = {
/* *INDENT-OFF* */
SDL_FS_SYM(FusionSoundInit),
SDL_FS_SYM(FusionSoundCreate),
/* *INDENT-ON* */
};
#undef SDL_FS_SYM
static void
UnloadFusionSoundLibrary()
{
if (fs_handle != NULL) {
SDL_UnloadObject(fs_handle);
fs_handle = NULL;
}
}
static int
LoadFusionSoundLibrary(void)
{
int i, retval = -1;
if (fs_handle == NULL) {
fs_handle = SDL_LoadObject(fs_library);
if (fs_handle != NULL) {
retval = 0;
for (i = 0; i < SDL_arraysize(fs_functions); ++i) {
*fs_functions[i].func =
SDL_LoadFunction(fs_handle, fs_functions[i].name);
if (!*fs_functions[i].func) {
retval = -1;
UnloadFusionSoundLibrary();
break;
}
}
}
}
return retval;
}
#else
static void
UnloadFusionSoundLibrary()
{
return;
}
static int
LoadFusionSoundLibrary(void)
{
return 0;
}
#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */
/* This function waits until it is possible to write a full sound buffer */
static void
SDL_FS_WaitDevice(_THIS)
{
this->hidden->stream->Wait(this->hidden->stream,
this->hidden->mixsamples);
}
static void
SDL_FS_PlayDevice(_THIS)
{
DirectResult ret;
ret = this->hidden->stream->Write(this->hidden->stream,
this->hidden->mixbuf,
this->hidden->mixsamples);
/* If we couldn't write, assume fatal error for now */
if (ret) {
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
#endif
}
static Uint8 *
SDL_FS_GetDeviceBuf(_THIS)
{
return (this->hidden->mixbuf);
}
static void
SDL_FS_CloseDevice(_THIS)
{
if (this->hidden->stream) {
this->hidden->stream->Release(this->hidden->stream);
}
if (this->hidden->fs) {
this->hidden->fs->Release(this->hidden->fs);
}
SDL_free(this->hidden->mixbuf);
SDL_free(this->hidden);
}
static int
SDL_FS_OpenDevice(_THIS, const char *devname)
{
int bytes;
SDL_AudioFormat test_format;
FSSampleFormat fs_format;
FSStreamDescription desc;
DirectResult ret;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
switch (test_format) {
case AUDIO_U8:
fs_format = FSSF_U8;
break;
case AUDIO_S16SYS:
fs_format = FSSF_S16;
break;
case AUDIO_S32SYS:
fs_format = FSSF_S32;
break;
case AUDIO_F32SYS:
fs_format = FSSF_FLOAT;
break;
default:
continue;
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "fusionsound");
}
this->spec.format = test_format;
bytes = SDL_AUDIO_BITSIZE(test_format) / 8;
/* Retrieve the main sound interface. */
ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
if (ret) {
return SDL_SetError("Unable to initialize FusionSound: %d", ret);
}
this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;
/* Fill stream description. */
desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT | FSSDF_PREBUFFER;
desc.samplerate = this->spec.freq;
desc.buffersize = this->spec.size * FUSION_BUFFERS;
desc.channels = this->spec.channels;
desc.prebuffer = 10;
desc.sampleformat = fs_format;
ret =
this->hidden->fs->CreateStream(this->hidden->fs, &desc,
&this->hidden->stream);
if (ret) {
return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
}
/* See what we got */
desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT;
ret = this->hidden->stream->GetDescription(this->hidden->stream, &desc);
this->spec.freq = desc.samplerate;
this->spec.size =
desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
this->spec.channels = desc.channels;
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
/* We're ready to rock and roll. :-) */
return 0;
}
static void
SDL_FS_Deinitialize(void)
{
UnloadFusionSoundLibrary();
}
static SDL_bool
SDL_FS_Init(SDL_AudioDriverImpl * impl)
{
if (LoadFusionSoundLibrary() < 0) {
return SDL_FALSE;
} else {
DirectResult ret;
ret = SDL_NAME(FusionSoundInit) (NULL, NULL);
if (ret) {
UnloadFusionSoundLibrary();
SDL_SetError
("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
ret);
return SDL_FALSE;
}
}
/* Set the function pointers */
impl->OpenDevice = SDL_FS_OpenDevice;
impl->PlayDevice = SDL_FS_PlayDevice;
impl->WaitDevice = SDL_FS_WaitDevice;
impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
impl->CloseDevice = SDL_FS_CloseDevice;
impl->Deinitialize = SDL_FS_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap FUSIONSOUND_bootstrap = {
"fusionsound", "FusionSound", SDL_FS_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,363 @@
/*
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.
*/
#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(&current_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: */

View File

@@ -18,33 +18,33 @@
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_fsaudio_h_
#define SDL_fsaudio_h_
#ifndef _SDL_n3dsaudio_h_
#define _SDL_n3dsaudio_h_
#include <fusionsound/fusionsound.h>
#include "../SDL_sysaudio.h"
#include <3ds.h>
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
#define _THIS SDL_AudioDevice *this
#define NUM_BUFFERS 2 /* -- Don't lower this! */
struct SDL_PrivateAudioData
{
/* Interface */
IFusionSound *fs;
/* The stream interface for the audio device */
IFusionSoundStream *stream;
/* Raw mixing buffer */
/* Speaker data */
Uint8 *mixbuf;
int mixlen;
int mixsamples;
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_fsaudio_h_ */
/* vi: set ts=4 sw=4 expandtab: */
#endif /* _SDL_n3dsaudio_h_ */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -1,160 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_NACL
#include "SDL_naclaudio.h"
#include "SDL_audio.h"
#include "SDL_mutex.h"
#include "../SDL_audio_c.h"
#include "../SDL_audiodev_c.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi_simple/ps.h"
#include "ppapi_simple/ps_interface.h"
#include "ppapi_simple/ps_event.h"
/* The tag name used by NACL audio */
#define NACLAUDIO_DRIVER_NAME "nacl"
#define SAMPLE_FRAME_COUNT 4096
/* Audio driver functions */
static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
/* FIXME: Make use of latency if needed */
static void nacl_audio_callback(void* stream, uint32_t buffer_size, PP_TimeDelta latency, void* data) {
const int len = (int) buffer_size;
SDL_AudioDevice* _this = (SDL_AudioDevice*) data;
SDL_AudioCallback callback = _this->callbackspec.callback;
SDL_LockMutex(_this->mixer_lock);
/* Only do something if audio is enabled */
if (!SDL_AtomicGet(&_this->enabled) || SDL_AtomicGet(&_this->paused)) {
if (_this->stream) {
SDL_AudioStreamClear(_this->stream);
}
SDL_memset(stream, _this->spec.silence, len);
} else {
SDL_assert(_this->spec.size == len);
if (_this->stream == NULL) { /* no conversion necessary. */
callback(_this->callbackspec.userdata, stream, len);
} else { /* streaming/converting */
const int stream_len = _this->callbackspec.size;
while (SDL_AudioStreamAvailable(_this->stream) < len) {
callback(_this->callbackspec.userdata, _this->work_buffer, stream_len);
if (SDL_AudioStreamPut(_this->stream, _this->work_buffer, stream_len) == -1) {
SDL_AudioStreamClear(_this->stream);
SDL_AtomicSet(&_this->enabled, 0);
break;
}
}
const int got = SDL_AudioStreamGet(_this->stream, stream, len);
SDL_assert((got < 0) || (got == len));
if (got != len) {
SDL_memset(stream, _this->spec.silence, len);
}
}
}
SDL_UnlockMutex(_this->mixer_lock);
}
static void NACLAUDIO_CloseDevice(SDL_AudioDevice *device) {
const PPB_Core *core = PSInterfaceCore();
const PPB_Audio *ppb_audio = PSInterfaceAudio();
SDL_PrivateAudioData *hidden = (SDL_PrivateAudioData *) device->hidden;
ppb_audio->StopPlayback(hidden->audio);
core->ReleaseResource(hidden->audio);
}
static int
NACLAUDIO_OpenDevice(_THIS, const char *devname) {
PP_Instance instance = PSGetInstanceId();
const PPB_Audio *ppb_audio = PSInterfaceAudio();
const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
private = (SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *private));
if (private == NULL) {
return SDL_OutOfMemory();
}
_this->spec.freq = 44100;
_this->spec.format = AUDIO_S16LSB;
_this->spec.channels = 2;
_this->spec.samples = ppb_audiocfg->RecommendSampleFrameCount(
instance,
PP_AUDIOSAMPLERATE_44100,
SAMPLE_FRAME_COUNT);
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&_this->spec);
private->audio = ppb_audio->Create(
instance,
ppb_audiocfg->CreateStereo16Bit(instance, PP_AUDIOSAMPLERATE_44100, _this->spec.samples),
nacl_audio_callback,
_this);
/* Start audio playback while we are still on the main thread. */
ppb_audio->StartPlayback(private->audio);
return 0;
}
static SDL_bool
NACLAUDIO_Init(SDL_AudioDriverImpl * impl)
{
if (PSGetInstanceId() == 0) {
return SDL_FALSE;
}
/* Set the function pointers */
impl->OpenDevice = NACLAUDIO_OpenDevice;
impl->CloseDevice = NACLAUDIO_CloseDevice;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->ProvidesOwnCallbackThread = SDL_TRUE;
/*
* impl->WaitDevice = NACLAUDIO_WaitDevice;
* impl->GetDeviceBuf = NACLAUDIO_GetDeviceBuf;
* impl->PlayDevice = NACLAUDIO_PlayDevice;
* impl->Deinitialize = NACLAUDIO_Deinitialize;
*/
return SDL_TRUE;
}
AudioBootStrap NACLAUDIO_bootstrap = {
NACLAUDIO_DRIVER_NAME, "SDL NaCl Audio Driver",
NACLAUDIO_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_NACL */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,461 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_NAS
/* Allow access to a raw mixing buffer */
#include <signal.h>
#include <unistd.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "SDL_loadso.h"
#include "../SDL_audio_c.h"
#include "SDL_nasaudio.h"
static void (*NAS_AuCloseServer) (AuServer *);
static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
static void (*NAS_AuHandleEvents) (AuServer *);
static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
static void (*NAS_AuSetElements)
(AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
static void (*NAS_AuWriteElement)
(AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
static AuUint32 (*NAS_AuReadElement)
(AuServer *, AuFlowID, int, AuUint32, AuPointer, AuStatus *);
static AuServer *(*NAS_AuOpenServer)
(_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
(AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer);
#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC;
static void *nas_handle = NULL;
static int
load_nas_sym(const char *fn, void **addr)
{
*addr = SDL_LoadFunction(nas_handle, fn);
if (*addr == NULL) {
return 0;
}
return 1;
}
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
#define SDL_NAS_SYM(x) \
if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1
#else
#define SDL_NAS_SYM(x) NAS_##x = x
#endif
static int
load_nas_syms(void)
{
SDL_NAS_SYM(AuCloseServer);
SDL_NAS_SYM(AuNextEvent);
SDL_NAS_SYM(AuDispatchEvent);
SDL_NAS_SYM(AuHandleEvents);
SDL_NAS_SYM(AuCreateFlow);
SDL_NAS_SYM(AuStartFlow);
SDL_NAS_SYM(AuSetElements);
SDL_NAS_SYM(AuWriteElement);
SDL_NAS_SYM(AuReadElement);
SDL_NAS_SYM(AuOpenServer);
SDL_NAS_SYM(AuRegisterEventHandler);
return 0;
}
#undef SDL_NAS_SYM
#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
static void
UnloadNASLibrary(void)
{
if (nas_handle != NULL) {
SDL_UnloadObject(nas_handle);
nas_handle = NULL;
}
}
static int
LoadNASLibrary(void)
{
int retval = 0;
if (nas_handle == NULL) {
nas_handle = SDL_LoadObject(nas_library);
if (nas_handle == NULL) {
/* Copy error string so we can use it in a new SDL_SetError(). */
const char *origerr = SDL_GetError();
const size_t len = SDL_strlen(origerr) + 1;
char *err = SDL_stack_alloc(char, len);
SDL_strlcpy(err, origerr, len);
SDL_SetError("NAS: SDL_LoadObject('%s') failed: %s", nas_library, err);
SDL_stack_free(err);
retval = -1;
} else {
retval = load_nas_syms();
if (retval < 0) {
UnloadNASLibrary();
}
}
}
return retval;
}
#else
static void
UnloadNASLibrary(void)
{
}
static int
LoadNASLibrary(void)
{
load_nas_syms();
return 0;
}
#endif /* SDL_AUDIO_DRIVER_NAS_DYNAMIC */
/* This function waits until it is possible to write a full sound buffer */
static void
NAS_WaitDevice(_THIS)
{
while (this->hidden->buf_free < this->hidden->mixlen) {
AuEvent ev;
NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
NAS_AuDispatchEvent(this->hidden->aud, &ev);
}
}
static void
NAS_PlayDevice(_THIS)
{
while (this->hidden->mixlen > this->hidden->buf_free) {
/*
* We think the buffer is full? Yikes! Ask the server for events,
* in the hope that some of them is LowWater events telling us more
* of the buffer is free now than what we think.
*/
AuEvent ev;
NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
NAS_AuDispatchEvent(this->hidden->aud, &ev);
}
this->hidden->buf_free -= this->hidden->mixlen;
/* Write the audio data */
NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
this->hidden->mixlen, this->hidden->mixbuf, AuFalse,
NULL);
this->hidden->written += this->hidden->mixlen;
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
#endif
}
static Uint8 *
NAS_GetDeviceBuf(_THIS)
{
return (this->hidden->mixbuf);
}
static int
NAS_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
struct SDL_PrivateAudioData *h = this->hidden;
int retval;
while (SDL_TRUE) {
/* just keep the event queue moving and the server chattering. */
NAS_AuHandleEvents(h->aud);
retval = (int) NAS_AuReadElement(h->aud, h->flow, 1, buflen, buffer, NULL);
/*printf("read %d capture bytes\n", (int) retval);*/
if (retval == 0) {
SDL_Delay(10); /* don't burn the CPU if we're waiting for data. */
} else {
break;
}
}
return retval;
}
static void
NAS_FlushCapture(_THIS)
{
struct SDL_PrivateAudioData *h = this->hidden;
AuUint32 total = 0;
AuUint32 br;
Uint8 buf[512];
do {
/* just keep the event queue moving and the server chattering. */
NAS_AuHandleEvents(h->aud);
br = NAS_AuReadElement(h->aud, h->flow, 1, sizeof (buf), buf, NULL);
/*printf("flushed %d capture bytes\n", (int) br);*/
total += br;
} while ((br == sizeof (buf)) && (total < this->spec.size));
}
static void
NAS_CloseDevice(_THIS)
{
if (this->hidden->aud) {
NAS_AuCloseServer(this->hidden->aud);
}
SDL_free(this->hidden->mixbuf);
SDL_free(this->hidden);
}
static AuBool
event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
{
SDL_AudioDevice *this = (SDL_AudioDevice *) hnd->data;
struct SDL_PrivateAudioData *h = this->hidden;
if (this->iscapture) {
return AuTrue; /* we don't (currently) care about any of this for capture devices */
}
switch (ev->type) {
case AuEventTypeElementNotify:
{
AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
switch (event->kind) {
case AuElementNotifyKindLowWater:
if (h->buf_free >= 0) {
h->really += event->num_bytes;
gettimeofday(&h->last_tv, 0);
h->buf_free += event->num_bytes;
} else {
h->buf_free = event->num_bytes;
}
break;
case AuElementNotifyKindState:
switch (event->cur_state) {
case AuStatePause:
if (event->reason != AuReasonUser) {
if (h->buf_free >= 0) {
h->really += event->num_bytes;
gettimeofday(&h->last_tv, 0);
h->buf_free += event->num_bytes;
} else {
h->buf_free = event->num_bytes;
}
}
break;
}
}
}
}
return AuTrue;
}
static AuDeviceID
find_device(_THIS)
{
/* These "Au" things are all macros, not functions... */
struct SDL_PrivateAudioData *h = this->hidden;
const unsigned int devicekind = this->iscapture ? AuComponentKindPhysicalInput : AuComponentKindPhysicalOutput;
const int numdevs = AuServerNumDevices(h->aud);
const int nch = this->spec.channels;
int i;
/* Try to find exact match on channels first... */
for (i = 0; i < numdevs; i++) {
const AuDeviceAttributes *dev = AuServerDevice(h->aud, i);
if ((AuDeviceKind(dev) == devicekind) && (AuDeviceNumTracks(dev) == nch)) {
return AuDeviceIdentifier(dev);
}
}
/* Take anything, then... */
for (i = 0; i < numdevs; i++) {
const AuDeviceAttributes *dev = AuServerDevice(h->aud, i);
if (AuDeviceKind(dev) == devicekind) {
this->spec.channels = AuDeviceNumTracks(dev);
return AuDeviceIdentifier(dev);
}
}
return AuNone;
}
static int
NAS_OpenDevice(_THIS, const char *devname)
{
AuElement elms[3];
int buffer_size;
SDL_bool iscapture = this->iscapture;
SDL_AudioFormat test_format, format = 0;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
switch (test_format) {
case AUDIO_U8:
format = AuFormatLinearUnsigned8;
break;
case AUDIO_S8:
format = AuFormatLinearSigned8;
break;
case AUDIO_U16LSB:
format = AuFormatLinearUnsigned16LSB;
break;
case AUDIO_U16MSB:
format = AuFormatLinearUnsigned16MSB;
break;
case AUDIO_S16LSB:
format = AuFormatLinearSigned16LSB;
break;
case AUDIO_S16MSB:
format = AuFormatLinearSigned16MSB;
break;
default:
continue;
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "nas");
}
this->spec.format = test_format;
this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (this->hidden->aud == 0) {
return SDL_SetError("NAS: Couldn't open connection to NAS server");
}
this->hidden->dev = find_device(this);
if ((this->hidden->dev == AuNone)
|| (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
return SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
}
buffer_size = this->spec.freq;
if (buffer_size < 4096)
buffer_size = 4096;
if (buffer_size > 32768)
buffer_size = 32768; /* So that the buffer won't get unmanageably big. */
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
if (iscapture) {
AuMakeElementImportDevice(elms, this->spec.freq, this->hidden->dev,
AuUnlimitedSamples, 0, NULL);
AuMakeElementExportClient(elms + 1, 0, this->spec.freq, format,
this->spec.channels, AuTrue, buffer_size,
buffer_size, 0, NULL);
} else {
AuMakeElementImportClient(elms, this->spec.freq, format,
this->spec.channels, AuTrue, buffer_size,
buffer_size / 4, 0, NULL);
AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
AuUnlimitedSamples, 0, NULL);
}
NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue,
2, elms, NULL);
NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
this->hidden->flow, event_handler,
(AuPointer) this);
NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
/* Allocate mixing buffer */
if (!iscapture) {
this->hidden->mixlen = this->spec.size;
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
}
/* We're ready to rock and roll. :-) */
return 0;
}
static void
NAS_Deinitialize(void)
{
UnloadNASLibrary();
}
static SDL_bool
NAS_Init(SDL_AudioDriverImpl * impl)
{
if (LoadNASLibrary() < 0) {
return SDL_FALSE;
} else {
AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (aud == NULL) {
SDL_SetError("NAS: AuOpenServer() failed (no audio server?)");
return SDL_FALSE;
}
NAS_AuCloseServer(aud);
}
/* Set the function pointers */
impl->OpenDevice = NAS_OpenDevice;
impl->PlayDevice = NAS_PlayDevice;
impl->WaitDevice = NAS_WaitDevice;
impl->GetDeviceBuf = NAS_GetDeviceBuf;
impl->CaptureFromDevice = NAS_CaptureFromDevice;
impl->FlushCapture = NAS_FlushCapture;
impl->CloseDevice = NAS_CloseDevice;
impl->Deinitialize = NAS_Deinitialize;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap NAS_bootstrap = {
"nas", "Network Audio System", NAS_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_NAS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,56 +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.
*/
#include "../../SDL_internal.h"
#ifndef SDL_nasaudio_h_
#define SDL_nasaudio_h_
#ifdef __sgi
#include <nas/audiolib.h>
#else
#include <audio/audiolib.h>
#endif
#include <sys/time.h>
#include "../SDL_sysaudio.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData
{
AuServer *aud;
AuFlowID flow;
AuDeviceID dev;
/* Raw mixing buffer */
Uint8 *mixbuf;
int mixlen;
int written;
int really;
int bps;
struct timeval last_tv;
int buf_free;
};
#endif /* SDL_nasaudio_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,450 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_OS2
/* Allow access to a raw mixing buffer */
#include "../../core/os2/SDL_os2.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_os2audio.h"
/*
void lockIncr(volatile int *piVal);
#pragma aux lockIncr = \
"lock add [eax], 1 "\
parm [eax];
void lockDecr(volatile int *piVal);
#pragma aux lockDecr = \
"lock sub [eax], 1 "\
parm [eax];
*/
static ULONG _getEnvULong(const char *name, ULONG ulMax, ULONG ulDefault)
{
ULONG ulValue;
char* end;
char* envval = SDL_getenv(name);
if (envval == NULL)
return ulDefault;
ulValue = SDL_strtoul(envval, &end, 10);
return (end == envval) || (ulValue > ulMax)? ulDefault : ulMax;
}
static int _MCIError(const char *func, ULONG ulResult)
{
CHAR acBuf[128];
mciGetErrorString(ulResult, acBuf, sizeof(acBuf));
return SDL_SetError("[%s] %s", func, acBuf);
}
static void _mixIOError(const char *function, ULONG ulRC)
{
debug_os2("%s() - failed, rc = 0x%X (%s)",
function, ulRC,
(ulRC == MCIERR_INVALID_MODE) ? "Mixer mode does not match request" :
(ulRC == MCIERR_INVALID_BUFFER) ? "Caller sent an invalid buffer" : "unknown");
}
static LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
ULONG ulFlags)
{
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)pBuffer->ulUserParm;
ULONG ulRC;
if (ulFlags != MIX_WRITE_COMPLETE) {
debug_os2("flags = 0x%X", ulFlags);
return 0;
}
/*lockDecr((int *)&pAData->ulQueuedBuf);*/
ulRC = DosPostEventSem(pAData->hevBuf);
if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
debug_os2("DosPostEventSem(), rc = %u", ulRC);
}
return 1; /* return value doesn't seem to matter. */
}
static LONG APIENTRY cbAudioReadEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
ULONG ulFlags)
{
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)pBuffer->ulUserParm;
ULONG ulRC;
if (ulFlags != MIX_READ_COMPLETE) {
debug_os2("flags = 0x%X", ulFlags);
return 0;
}
pAData->stMCIMixSetup.pmixRead(pAData->stMCIMixSetup.ulMixHandle, pBuffer, 1);
ulRC = DosPostEventSem(pAData->hevBuf);
if (ulRC != NO_ERROR && ulRC != ERROR_ALREADY_POSTED) {
debug_os2("DosPostEventSem(), rc = %u", ulRC);
}
return 1;
}
static void OS2_DetectDevices(void)
{
MCI_SYSINFO_PARMS stMCISysInfo;
CHAR acBuf[256];
ULONG ulDevicesNum;
MCI_SYSINFO_LOGDEVICE stLogDevice;
MCI_SYSINFO_PARMS stSysInfoParams;
ULONG ulRC;
ULONG ulHandle = 0;
acBuf[0] = '\0';
stMCISysInfo.pszReturn = acBuf;
stMCISysInfo.ulRetSize = sizeof(acBuf);
stMCISysInfo.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_QUANTITY,
&stMCISysInfo, 0);
if (ulRC != NO_ERROR) {
debug_os2("MCI_SYSINFO, MCI_SYSINFO_QUANTITY - failed, rc = 0x%X", ulRC);
return;
}
ulDevicesNum = SDL_strtoul(stMCISysInfo.pszReturn, NULL, 10);
for (stSysInfoParams.ulNumber = 0; stSysInfoParams.ulNumber < ulDevicesNum;
stSysInfoParams.ulNumber++) {
/* Get device install name. */
stSysInfoParams.pszReturn = acBuf;
stSysInfoParams.ulRetSize = sizeof(acBuf);
stSysInfoParams.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_INSTALLNAME,
&stSysInfoParams, 0);
if (ulRC != NO_ERROR) {
debug_os2("MCI_SYSINFO, MCI_SYSINFO_INSTALLNAME - failed, rc = 0x%X", ulRC);
continue;
}
/* Get textual product description. */
stSysInfoParams.ulItem = MCI_SYSINFO_QUERY_DRIVER;
stSysInfoParams.pSysInfoParm = &stLogDevice;
SDL_strlcpy(stLogDevice.szInstallName, stSysInfoParams.pszReturn, MAX_DEVICE_NAME);
ulRC = mciSendCommand(0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_ITEM,
&stSysInfoParams, 0);
if (ulRC != NO_ERROR) {
debug_os2("MCI_SYSINFO, MCI_SYSINFO_ITEM - failed, rc = 0x%X", ulRC);
continue;
}
ulHandle++;
SDL_AddAudioDevice(0, stLogDevice.szProductInfo, NULL, (void *)(ulHandle));
ulHandle++;
SDL_AddAudioDevice(1, stLogDevice.szProductInfo, NULL, (void *)(ulHandle));
}
}
static void OS2_WaitDevice(_THIS)
{
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
ULONG ulRC;
/* Wait for an audio chunk to finish */
ulRC = DosWaitEventSem(pAData->hevBuf, 5000);
if (ulRC != NO_ERROR) {
debug_os2("DosWaitEventSem(), rc = %u", ulRC);
}
}
static Uint8 *OS2_GetDeviceBuf(_THIS)
{
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
return (Uint8 *) pAData->aMixBuffers[pAData->ulNextBuf].pBuffer;
}
static void OS2_PlayDevice(_THIS)
{
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
ULONG ulRC;
PMCI_MIX_BUFFER pMixBuffer = &pAData->aMixBuffers[pAData->ulNextBuf];
/* Queue it up */
/*lockIncr((int *)&pAData->ulQueuedBuf);*/
ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
pMixBuffer, 1);
if (ulRC != MCIERR_SUCCESS) {
_mixIOError("pmixWrite", ulRC);
} else {
pAData->ulNextBuf = (pAData->ulNextBuf + 1) % pAData->cMixBuffers;
}
}
static void OS2_CloseDevice(_THIS)
{
SDL_PrivateAudioData *pAData = (SDL_PrivateAudioData *)_this->hidden;
MCI_GENERIC_PARMS sMCIGenericParms;
ULONG ulRC;
if (pAData == NULL)
return;
/* Close up audio */
if (pAData->usDeviceId != (USHORT)~0) { /* Device is open. */
if (pAData->stMCIMixSetup.ulBitsPerSample != 0) { /* Mixer was initialized. */
ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
MCI_WAIT | MCI_MIXSETUP_DEINIT,
&pAData->stMCIMixSetup, 0);
if (ulRC != MCIERR_SUCCESS) {
debug_os2("MCI_MIXSETUP, MCI_MIXSETUP_DEINIT - failed");
}
}
if (pAData->cMixBuffers != 0) { /* Buffers was allocated. */
MCI_BUFFER_PARMS stMCIBuffer;
stMCIBuffer.ulBufferSize = pAData->aMixBuffers[0].ulBufferLength;
stMCIBuffer.ulNumBuffers = pAData->cMixBuffers;
stMCIBuffer.pBufList = pAData->aMixBuffers;
ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
MCI_WAIT | MCI_DEALLOCATE_MEMORY, &stMCIBuffer, 0);
if (ulRC != MCIERR_SUCCESS) {
debug_os2("MCI_BUFFER, MCI_DEALLOCATE_MEMORY - failed");
}
}
ulRC = mciSendCommand(pAData->usDeviceId, MCI_CLOSE, MCI_WAIT,
&sMCIGenericParms, 0);
if (ulRC != MCIERR_SUCCESS) {
debug_os2("MCI_CLOSE - failed");
}
}
if (pAData->hevBuf != NULLHANDLE)
DosCloseEventSem(pAData->hevBuf);
SDL_free(pAData);
}
static int OS2_OpenDevice(_THIS, const char *devname)
{
SDL_PrivateAudioData *pAData;
SDL_AudioFormat test_format;
MCI_AMP_OPEN_PARMS stMCIAmpOpen;
MCI_BUFFER_PARMS stMCIBuffer;
ULONG ulRC;
ULONG ulIdx;
BOOL new_freq;
SDL_bool iscapture = _this->iscapture;
new_freq = FALSE;
SDL_zero(stMCIAmpOpen);
SDL_zero(stMCIBuffer);
for (test_format = SDL_FirstAudioFormat(_this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
if (test_format == AUDIO_U8 || test_format == AUDIO_S16)
break;
}
if (!test_format) {
debug_os2("Unsupported audio format, AUDIO_S16 used");
test_format = AUDIO_S16;
}
pAData = (SDL_PrivateAudioData *) SDL_calloc(1, sizeof(struct SDL_PrivateAudioData));
if (pAData == NULL)
return SDL_OutOfMemory();
_this->hidden = pAData;
ulRC = DosCreateEventSem(NULL, &pAData->hevBuf, DCE_AUTORESET, TRUE);
if (ulRC != NO_ERROR) {
debug_os2("DosCreateEventSem() failed, rc = %u", ulRC);
return -1;
}
/* Open audio device */
stMCIAmpOpen.usDeviceID = (_this->handle != NULL) ? ((ULONG)_this->handle - 1) : 0;
stMCIAmpOpen.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
ulRC = mciSendCommand(0, MCI_OPEN,
(_getEnvULong("SDL_AUDIO_SHARE", 1, 0) != 0)?
MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE :
MCI_WAIT | MCI_OPEN_TYPE_ID,
&stMCIAmpOpen, 0);
if (ulRC != MCIERR_SUCCESS) {
stMCIAmpOpen.usDeviceID = (USHORT)~0;
return _MCIError("MCI_OPEN", ulRC);
}
pAData->usDeviceId = stMCIAmpOpen.usDeviceID;
if (iscapture) {
MCI_CONNECTOR_PARMS stMCIConnector;
MCI_AMP_SET_PARMS stMCIAmpSet;
BOOL fLineIn = _getEnvULong("SDL_AUDIO_LINEIN", 1, 0);
/* Set particular connector. */
SDL_zero(stMCIConnector);
stMCIConnector.ulConnectorType = (fLineIn)? MCI_LINE_IN_CONNECTOR :
MCI_MICROPHONE_CONNECTOR;
mciSendCommand(stMCIAmpOpen.usDeviceID, MCI_CONNECTOR,
MCI_WAIT | MCI_ENABLE_CONNECTOR |
MCI_CONNECTOR_TYPE, &stMCIConnector, 0);
/* Disable monitor. */
SDL_zero(stMCIAmpSet);
stMCIAmpSet.ulItem = MCI_AMP_SET_MONITOR;
mciSendCommand(stMCIAmpOpen.usDeviceID, MCI_SET,
MCI_WAIT | MCI_SET_OFF | MCI_SET_ITEM,
&stMCIAmpSet, 0);
/* Set record volume. */
stMCIAmpSet.ulLevel = _getEnvULong("SDL_AUDIO_RECVOL", 100, 90);
stMCIAmpSet.ulItem = MCI_AMP_SET_AUDIO;
stMCIAmpSet.ulAudio = MCI_SET_AUDIO_ALL; /* Both cnannels. */
stMCIAmpSet.ulValue = (fLineIn) ? MCI_LINE_IN_CONNECTOR :
MCI_MICROPHONE_CONNECTOR ;
mciSendCommand(stMCIAmpOpen.usDeviceID, MCI_SET,
MCI_WAIT | MCI_SET_AUDIO | MCI_AMP_SET_GAIN,
&stMCIAmpSet, 0);
}
_this->spec.format = test_format;
_this->spec.channels = _this->spec.channels > 1 ? 2 : 1;
if (_this->spec.freq < 8000) {
_this->spec.freq = 8000;
new_freq = TRUE;
} else if (_this->spec.freq > 48000) {
_this->spec.freq = 48000;
new_freq = TRUE;
}
/* Setup mixer. */
pAData->stMCIMixSetup.ulFormatTag = MCI_WAVE_FORMAT_PCM;
pAData->stMCIMixSetup.ulBitsPerSample = SDL_AUDIO_BITSIZE(test_format);
pAData->stMCIMixSetup.ulSamplesPerSec = _this->spec.freq;
pAData->stMCIMixSetup.ulChannels = _this->spec.channels;
pAData->stMCIMixSetup.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
if (!iscapture) {
pAData->stMCIMixSetup.ulFormatMode= MCI_PLAY;
pAData->stMCIMixSetup.pmixEvent = cbAudioWriteEvent;
} else {
pAData->stMCIMixSetup.ulFormatMode= MCI_RECORD;
pAData->stMCIMixSetup.pmixEvent = cbAudioReadEvent;
}
ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
if (ulRC != MCIERR_SUCCESS && _this->spec.freq > 44100) {
new_freq = TRUE;
pAData->stMCIMixSetup.ulSamplesPerSec = 44100;
_this->spec.freq = 44100;
ulRC = mciSendCommand(pAData->usDeviceId, MCI_MIXSETUP,
MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0);
}
debug_os2("Setup mixer [BPS: %u, Freq.: %u, Channels: %u]: %s",
pAData->stMCIMixSetup.ulBitsPerSample,
pAData->stMCIMixSetup.ulSamplesPerSec,
pAData->stMCIMixSetup.ulChannels,
(ulRC == MCIERR_SUCCESS)? "SUCCESS" : "FAIL");
if (ulRC != MCIERR_SUCCESS) {
pAData->stMCIMixSetup.ulBitsPerSample = 0;
return _MCIError("MCI_MIXSETUP", ulRC);
}
if (_this->spec.samples == 0 || new_freq == TRUE) {
/* also see SDL_audio.c:prepare_audiospec() */
/* Pick a default of ~46 ms at desired frequency */
Uint32 samples = (_this->spec.freq / 1000) * 46;
Uint32 power2 = 1;
while (power2 < samples) {
power2 <<= 1;
}
_this->spec.samples = power2;
}
/* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(&_this->spec);
/* Allocate memory buffers */
stMCIBuffer.ulBufferSize = _this->spec.size;/* (_this->spec.freq / 1000) * 100 */
stMCIBuffer.ulNumBuffers = NUM_BUFFERS;
stMCIBuffer.pBufList = pAData->aMixBuffers;
ulRC = mciSendCommand(pAData->usDeviceId, MCI_BUFFER,
MCI_WAIT | MCI_ALLOCATE_MEMORY, &stMCIBuffer, 0);
if (ulRC != MCIERR_SUCCESS) {
return _MCIError("MCI_BUFFER", ulRC);
}
pAData->cMixBuffers = stMCIBuffer.ulNumBuffers;
_this->spec.size = stMCIBuffer.ulBufferSize;
/* Fill all device buffers with data */
for (ulIdx = 0; ulIdx < stMCIBuffer.ulNumBuffers; ulIdx++) {
pAData->aMixBuffers[ulIdx].ulFlags = 0;
pAData->aMixBuffers[ulIdx].ulBufferLength = stMCIBuffer.ulBufferSize;
pAData->aMixBuffers[ulIdx].ulUserParm = (ULONG)pAData;
SDL_memset(((PMCI_MIX_BUFFER)stMCIBuffer.pBufList)[ulIdx].pBuffer,
_this->spec.silence, stMCIBuffer.ulBufferSize);
}
/* Write buffers to kick off the amp mixer */
ulRC = pAData->stMCIMixSetup.pmixWrite(pAData->stMCIMixSetup.ulMixHandle,
pAData->aMixBuffers, 1);
if (ulRC != MCIERR_SUCCESS) {
_mixIOError("pmixWrite", ulRC);
return -1;
}
return 0;
}
static SDL_bool OS2_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
impl->DetectDevices = OS2_DetectDevices;
impl->OpenDevice = OS2_OpenDevice;
impl->PlayDevice = OS2_PlayDevice;
impl->WaitDevice = OS2_WaitDevice;
impl->GetDeviceBuf = OS2_GetDeviceBuf;
impl->CloseDevice = OS2_CloseDevice;
/* TODO: IMPLEMENT CAPTURE SUPPORT:
impl->CaptureFromDevice = ;
impl->FlushCapture = ;
impl->HasCaptureSupport = SDL_TRUE;
*/
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap OS2AUDIO_bootstrap = {
"DART", "OS/2 DART", OS2_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_OS2 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,54 +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.
*/
#include "../../SDL_internal.h"
#ifndef SDL_os2mm_h_
#define SDL_os2mm_h_
#include "../SDL_sysaudio.h"
#define INCL_OS2MM
#define INCL_PM
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#include <os2me.h>
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *_this
#define NUM_BUFFERS 3
typedef struct SDL_PrivateAudioData
{
USHORT usDeviceId;
BYTE _pad[2];
MCI_MIXSETUP_PARMS stMCIMixSetup;
HEV hevBuf;
ULONG ulNextBuf;
ULONG cMixBuffers;
MCI_MIX_BUFFER aMixBuffers[NUM_BUFFERS];
/* ULONG ulQueuedBuf;*/
} SDL_PrivateAudioData;
#endif /* SDL_os2mm_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,494 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_PAUDIO
/* Allow access to a raw mixing buffer */
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "SDL_stdinc.h"
#include "../SDL_audio_c.h"
#include "../../core/unix/SDL_poll.h"
#include "SDL_paudio.h"
/* #define DEBUG_AUDIO */
/* A conflict within AIX 4.3.3 <sys/> headers and probably others as well.
* I guess nobody ever uses audio... Shame over AIX header files. */
#include <sys/machine.h>
#undef BIG_ENDIAN
#include <sys/audio.h>
/* Open the audio device for playback, and don't block if busy */
/* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */
#define OPEN_FLAGS O_WRONLY
/* Get the name of the audio device we use for output */
#ifndef _PATH_DEV_DSP
#define _PATH_DEV_DSP "/dev/%caud%c/%c"
#endif
static char devsettings[][3] = {
{'p', '0', '1'}, {'p', '0', '2'}, {'p', '0', '3'}, {'p', '0', '4'},
{'p', '1', '1'}, {'p', '1', '2'}, {'p', '1', '3'}, {'p', '1', '4'},
{'p', '2', '1'}, {'p', '2', '2'}, {'p', '2', '3'}, {'p', '2', '4'},
{'p', '3', '1'}, {'p', '3', '2'}, {'p', '3', '3'}, {'p', '3', '4'},
{'b', '0', '1'}, {'b', '0', '2'}, {'b', '0', '3'}, {'b', '0', '4'},
{'b', '1', '1'}, {'b', '1', '2'}, {'b', '1', '3'}, {'b', '1', '4'},
{'b', '2', '1'}, {'b', '2', '2'}, {'b', '2', '3'}, {'b', '2', '4'},
{'b', '3', '1'}, {'b', '3', '2'}, {'b', '3', '3'}, {'b', '3', '4'},
{'\0', '\0', '\0'}
};
static int
OpenUserDefinedDevice(char *path, int maxlen, int flags)
{
const char *audiodev;
int fd;
/* Figure out what our audio device is */
if ((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) {
audiodev = SDL_getenv("AUDIODEV");
}
if (audiodev == NULL) {
return -1;
}
fd = open(audiodev, flags, 0);
if (path != NULL) {
SDL_strlcpy(path, audiodev, maxlen);
path[maxlen - 1] = '\0';
}
return fd;
}
static int
OpenAudioPath(char *path, int maxlen, int flags, int classic)
{
struct stat sb;
int cycle = 0;
int fd = OpenUserDefinedDevice(path, maxlen, flags);
if (fd != -1) {
return fd;
}
/* !!! FIXME: do we really need a table here? */
while (devsettings[cycle][0] != '\0') {
char audiopath[1024];
SDL_snprintf(audiopath, SDL_arraysize(audiopath),
_PATH_DEV_DSP,
devsettings[cycle][0],
devsettings[cycle][1], devsettings[cycle][2]);
if (stat(audiopath, &sb) == 0) {
fd = open(audiopath, flags, 0);
if (fd >= 0) {
if (path != NULL) {
SDL_strlcpy(path, audiopath, maxlen);
}
return fd;
}
}
}
return -1;
}
/* This function waits until it is possible to write a full sound buffer */
static void
PAUDIO_WaitDevice(_THIS)
{
fd_set fdset;
/* See if we need to use timed audio synchronization */
if (this->hidden->frame_ticks) {
/* Use timer for general audio synchronization */
Sint32 ticks;
ticks = ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
if (ticks > 0) {
SDL_Delay(ticks);
}
} else {
int timeoutMS;
audio_buffer paud_bufinfo;
if (ioctl(this->hidden->audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Couldn't get audio buffer information\n");
#endif
timeoutMS = 10 * 1000;
} else {
timeoutMS = paud_bufinfo.write_buf_time;
#ifdef DEBUG_AUDIO
fprintf(stderr, "Waiting for write_buf_time=%d ms\n", timeoutMS);
#endif
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Waiting for audio to get ready\n");
#endif
if (SDL_IOReady(this->hidden->audio_fd, SDL_IOR_WRITE, timeoutMS) <= 0) {
/*
* In general we should never print to the screen,
* but in this case we have no other way of letting
* the user know what happened.
*/
fprintf(stderr, "SDL: %s - Audio timeout - buggy audio driver? (disabled)\n", strerror(errno));
SDL_OpenedAudioDeviceDisconnected(this);
/* Don't try to close - may hang */
this->hidden->audio_fd = -1;
#ifdef DEBUG_AUDIO
fprintf(stderr, "Done disabling audio\n");
#endif
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Ready!\n");
#endif
}
}
static void
PAUDIO_PlayDevice(_THIS)
{
int written = 0;
const Uint8 *mixbuf = this->hidden->mixbuf;
const size_t mixlen = this->hidden->mixlen;
/* Write the audio data, checking for EAGAIN on broken audio drivers */
do {
written = write(this->hidden->audio_fd, mixbuf, mixlen);
if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
SDL_Delay(1); /* Let a little CPU time go by */
}
} while ((written < 0) &&
((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
/* If timer synchronization is enabled, set the next write frame */
if (this->hidden->frame_ticks) {
this->hidden->next_frame += this->hidden->frame_ticks;
}
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
#endif
}
static Uint8 *
PAUDIO_GetDeviceBuf(_THIS)
{
return this->hidden->mixbuf;
}
static void
PAUDIO_CloseDevice(_THIS)
{
if (this->hidden->audio_fd >= 0) {
close(this->hidden->audio_fd);
}
SDL_free(this->hidden->mixbuf);
SDL_free(this->hidden);
}
static int
PAUDIO_OpenDevice(_THIS, const char *devname)
{
const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
char audiodev[1024];
const char *err = NULL;
int flags;
int bytes_per_sample;
SDL_AudioFormat test_format;
audio_init paud_init;
audio_buffer paud_bufinfo;
audio_control paud_control;
audio_change paud_change;
int fd = -1;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
SDL_zerop(this->hidden);
/* Open the audio device */
fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
this->hidden->audio_fd = fd;
if (fd < 0) {
return SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
}
/*
* We can't set the buffer size - just ask the device for the maximum
* that we can have.
*/
if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
return SDL_SetError("Couldn't get audio buffer information");
}
if (this->spec.channels > 1)
this->spec.channels = 2;
else
this->spec.channels = 1;
/*
* Fields in the audio_init structure:
*
* Ignored by us:
*
* paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only?
* paud.slot_number; * slot number of the adapter
* paud.device_id; * adapter identification number
*
* Input:
*
* paud.srate; * the sampling rate in Hz
* paud.bits_per_sample; * 8, 16, 32, ...
* paud.bsize; * block size for this rate
* paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX
* paud.channels; * 1=mono, 2=stereo
* paud.flags; * FIXED - fixed length data
* * LEFT_ALIGNED, RIGHT_ALIGNED (var len only)
* * TWOS_COMPLEMENT - 2's complement data
* * SIGNED - signed? comment seems wrong in sys/audio.h
* * BIG_ENDIAN
* paud.operation; * PLAY, RECORD
*
* Output:
*
* paud.flags; * PITCH - pitch is supported
* * INPUT - input is supported
* * OUTPUT - output is supported
* * MONITOR - monitor is supported
* * VOLUME - volume is supported
* * VOLUME_DELAY - volume delay is supported
* * BALANCE - balance is supported
* * BALANCE_DELAY - balance delay is supported
* * TREBLE - treble control is supported
* * BASS - bass control is supported
* * BESTFIT_PROVIDED - best fit returned
* * LOAD_CODE - DSP load needed
* paud.rc; * NO_PLAY - DSP code can't do play requests
* * NO_RECORD - DSP code can't do record requests
* * INVALID_REQUEST - request was invalid
* * CONFLICT - conflict with open's flags
* * OVERLOADED - out of DSP MIPS or memory
* paud.position_resolution; * smallest increment for position
*/
paud_init.srate = this->spec.freq;
paud_init.mode = PCM;
paud_init.operation = PLAY;
paud_init.channels = this->spec.channels;
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
switch (test_format) {
case AUDIO_U8:
flags = TWOS_COMPLEMENT | FIXED;
break;
case AUDIO_S8:
flags = SIGNED | TWOS_COMPLEMENT | FIXED;
break;
case AUDIO_S16LSB:
flags = SIGNED | TWOS_COMPLEMENT | FIXED;
break;
case AUDIO_S16MSB:
flags = BIG_ENDIAN | SIGNED | TWOS_COMPLEMENT | FIXED;
break;
case AUDIO_U16LSB:
flags = TWOS_COMPLEMENT | FIXED;
break;
case AUDIO_U16MSB:
flags = BIG_ENDIAN | TWOS_COMPLEMENT | FIXED;
break;
default:
continue;
}
break;
}
if (!test_format) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Couldn't find any hardware audio formats\n");
#endif
return SDL_SetError("%s: Unsupported audio format", "paud");
}
this->spec.format = test_format;
paud_init.bits_per_sample = SDL_AUDIO_BITSIZE(test_format);
bytes_per_sample = SDL_AUDIO_BITSIZE(test_format) / 8;
paud_init.flags = flags;
/*
* We know the buffer size and the max number of subsequent writes
* that can be pending. If more than one can pend, allow the application
* to do something like double buffering between our write buffer and
* the device's own buffer that we are filling with write() anyway.
*
* We calculate this->spec.samples like this because
* SDL_CalculateAudioSpec() will give put paud_bufinfo.write_buf_cap
* (or paud_bufinfo.write_buf_cap/2) into this->spec.size in return.
*/
if (paud_bufinfo.request_buf_cap == 1) {
this->spec.samples = paud_bufinfo.write_buf_cap
/ bytes_per_sample / this->spec.channels;
} else {
this->spec.samples = paud_bufinfo.write_buf_cap
/ bytes_per_sample / this->spec.channels / 2;
}
paud_init.bsize = bytes_per_sample * this->spec.channels;
SDL_CalculateAudioSpec(&this->spec);
/*
* The AIX paud device init can't modify the values of the audio_init
* structure that we pass to it. So we don't need any recalculation
* of this stuff and no reinit call as in linux dsp code.
*
* /dev/paud supports all of the encoding formats, so we don't need
* to do anything like reopening the device, either.
*/
if (ioctl(fd, AUDIO_INIT, &paud_init) < 0) {
switch (paud_init.rc) {
case 1:
err = "DSP can't do play requests";
break;
case 2:
err = "DSP can't do record requests";
break;
case 4:
err = "request was invalid";
break;
case 5:
err = "conflict with open's flags";
break;
case 6:
err = "out of DSP MIPS or memory";
break;
default:
err = "not documented in sys/audio.h";
break;
}
return SDL_SetError("paud: Couldn't set audio format (%s)", err);
}
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
/*
* Set some paramters: full volume, first speaker that we can find.
* Ignore the other settings for now.
*/
paud_change.input = AUDIO_IGNORE; /* the new input source */
paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,OUTPUT_1 */
paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */
paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */
paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */
paud_change.balance = 0x3fffffff; /* the new balance */
paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */
paud_change.treble = AUDIO_IGNORE; /* the new treble state */
paud_change.bass = AUDIO_IGNORE; /* the new bass state */
paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */
paud_control.ioctl_request = AUDIO_CHANGE;
paud_control.request_info = (char *) &paud_change;
if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Can't change audio display settings\n");
#endif
}
/*
* Tell the device to expect data. Actual start will wait for
* the first write() call.
*/
paud_control.ioctl_request = AUDIO_START;
paud_control.position = 0;
if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
#ifdef DEBUG_AUDIO
fprintf(stderr, "Can't start audio play\n");
#endif
return SDL_SetError("Can't start audio play");
}
/* Check to see if we need to use SDL_IOReady() workaround */
if (workaround != NULL) {
this->hidden->frame_ticks = (float) (this->spec.samples * 1000) /
this->spec.freq;
this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
}
/* We're ready to rock and roll. :-) */
return 0;
}
static SDL_bool
PAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* !!! FIXME: not right for device enum? */
int fd = OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
if (fd < 0) {
SDL_SetError("PAUDIO: Couldn't open audio device");
return SDL_FALSE;
}
close(fd);
/* Set the function pointers */
impl->OpenDevice = PAUDIO_OpenDevice;
impl->PlayDevice = PAUDIO_PlayDevice;
impl->PlayDevice = PAUDIO_WaitDevice;
impl->GetDeviceBuf = PAUDIO_GetDeviceBuf;
impl->CloseDevice = PAUDIO_CloseDevice;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; /* !!! FIXME: add device enum! */
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap PAUDIO_bootstrap = {
"paud", "AIX Paudio", PAUDIO_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_PAUDIO */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -48,15 +48,30 @@ PS2AUDIO_OpenDevice(_THIS, const char *devname)
}
SDL_zerop(this->hidden);
/* This is the native supported audio PS2 config */
this->spec.freq = 48000;
/* 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 = 2;
this->spec.format = AUDIO_S16LSB;
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 = 16;
format.bits = this->spec.format == AUDIO_S8 ? 8 : 16;
format.freq = this->spec.freq;
format.channels = this->spec.channels;

View File

@@ -1,627 +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.
*/
/*
* !!! FIXME: streamline this a little by removing all the
* !!! FIXME: if (capture) {} else {} sections that are identical
* !!! FIXME: except for one flag.
*/
/* !!! FIXME: can this target support hotplugging? */
/* !!! FIXME: ...does SDL2 even support QNX? */
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_QSA
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sched.h>
#include <sys/select.h>
#include <sys/neutrino.h>
#include <sys/asoundlib.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../../core/unix/SDL_poll.h"
#include "../SDL_audio_c.h"
#include "SDL_qsa_audio.h"
/* default channel communication parameters */
#define DEFAULT_CPARAMS_RATE 44100
#define DEFAULT_CPARAMS_VOICES 1
#define DEFAULT_CPARAMS_FRAG_SIZE 4096
#define DEFAULT_CPARAMS_FRAGS_MIN 1
#define DEFAULT_CPARAMS_FRAGS_MAX 1
/* List of found devices */
#define QSA_MAX_DEVICES 32
#define QSA_MAX_NAME_LENGTH 81+16 /* Hardcoded in QSA, can't be changed */
typedef struct _QSA_Device
{
char name[QSA_MAX_NAME_LENGTH]; /* Long audio device name for SDL */
int cardno;
int deviceno;
} QSA_Device;
QSA_Device qsa_playback_device[QSA_MAX_DEVICES];
uint32_t qsa_playback_devices;
QSA_Device qsa_capture_device[QSA_MAX_DEVICES];
uint32_t qsa_capture_devices;
static SDL_INLINE int
QSA_SetError(const char *fn, int status)
{
return SDL_SetError("QSA: %s() failed: %s", fn, snd_strerror(status));
}
/* !!! FIXME: does this need to be here? Does the SDL version not work? */
static void
QSA_ThreadInit(_THIS)
{
/* Increase default 10 priority to 25 to avoid jerky sound */
struct sched_param param;
if (SchedGet(0, 0, &param) != -1) {
param.sched_priority = param.sched_curpriority + 15;
SchedSet(0, 0, SCHED_NOCHANGE, &param);
}
}
/* PCM channel parameters initialize function */
static void
QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
{
SDL_zerop(cpars);
cpars->channel = SND_PCM_CHANNEL_PLAYBACK;
cpars->mode = SND_PCM_MODE_BLOCK;
cpars->start_mode = SND_PCM_START_DATA;
cpars->stop_mode = SND_PCM_STOP_STOP;
cpars->format.format = SND_PCM_SFMT_S16_LE;
cpars->format.interleave = 1;
cpars->format.rate = DEFAULT_CPARAMS_RATE;
cpars->format.voices = DEFAULT_CPARAMS_VOICES;
cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE;
cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN;
cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX;
}
/* This function waits until it is possible to write a full sound buffer */
static void
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 */
/* For example, Vortex 8820 audio driver stucks on second DAC because */
/* it doesn't exist ! */
result = SDL_IOReady(this->hidden->audio_fd,
this->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE,
2 * 1000);
switch (result) {
case -1:
SDL_SetError("QSA: SDL_IOReady() failed: %s", strerror(errno));
break;
case 0:
SDL_SetError("QSA: timeout on buffer waiting occured");
this->hidden->timeout_on_wait = 1;
break;
default:
this->hidden->timeout_on_wait = 0;
break;
}
}
static void
QSA_PlayDevice(_THIS)
{
snd_pcm_channel_status_t cstatus;
int written;
int status;
int towrite;
void *pcmbuffer;
if (!SDL_AtomicGet(&this->enabled) || !this->hidden) {
return;
}
towrite = this->spec.size;
pcmbuffer = this->hidden->pcm_buf;
/* Write the audio data, checking for EAGAIN (buffer full) and underrun */
do {
written =
snd_pcm_plugin_write(this->hidden->audio_handle, pcmbuffer,
towrite);
if (written != towrite) {
/* Check if samples playback got stuck somewhere in hardware or in */
/* the audio device driver */
if ((errno == EAGAIN) && (written == 0)) {
if (this->hidden->timeout_on_wait != 0) {
SDL_SetError("QSA: buffer playback timeout");
return;
}
}
/* Check for errors or conditions */
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
/* Let a little CPU time go by and try to write again */
SDL_Delay(1);
/* if we wrote some data */
towrite -= written;
pcmbuffer += written * this->spec.channels;
continue;
} else {
if ((errno == EINVAL) || (errno == EIO)) {
SDL_zero(cstatus);
if (!this->iscapture) {
cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
} else {
cstatus.channel = SND_PCM_CHANNEL_CAPTURE;
}
status =
snd_pcm_plugin_status(this->hidden->audio_handle,
&cstatus);
if (status < 0) {
QSA_SetError("snd_pcm_plugin_status", status);
return;
}
if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
(cstatus.status == SND_PCM_STATUS_READY)) {
if (!this->iscapture) {
status =
snd_pcm_plugin_prepare(this->hidden->
audio_handle,
SND_PCM_CHANNEL_PLAYBACK);
} else {
status =
snd_pcm_plugin_prepare(this->hidden->
audio_handle,
SND_PCM_CHANNEL_CAPTURE);
}
if (status < 0) {
QSA_SetError("snd_pcm_plugin_prepare", status);
return;
}
}
continue;
} else {
return;
}
}
} else {
/* we wrote all remaining data */
towrite -= written;
pcmbuffer += written * this->spec.channels;
}
} while ((towrite > 0) && SDL_AtomicGet(&this->enabled));
/* If we couldn't write, assume fatal error for now */
if (towrite != 0) {
SDL_OpenedAudioDeviceDisconnected(this);
}
}
static Uint8 *
QSA_GetDeviceBuf(_THIS)
{
return this->hidden->pcm_buf;
}
static void
QSA_CloseDevice(_THIS)
{
if (this->hidden->audio_handle != NULL) {
if (!this->iscapture) {
/* Finish playing available samples */
snd_pcm_plugin_flush(this->hidden->audio_handle,
SND_PCM_CHANNEL_PLAYBACK);
} else {
/* Cancel unread samples during capture */
snd_pcm_plugin_flush(this->hidden->audio_handle,
SND_PCM_CHANNEL_CAPTURE);
}
snd_pcm_close(this->hidden->audio_handle);
}
SDL_free(this->hidden->pcm_buf);
SDL_free(this->hidden);
}
static int
QSA_OpenDevice(_THIS, const char *devname)
{
const QSA_Device *device = (const QSA_Device *) this->handle;
SDL_bool iscapture = this->iscapture;
int status = 0;
int format = 0;
SDL_AudioFormat test_format;
snd_pcm_channel_setup_t csetup;
snd_pcm_channel_params_t cparams;
/* Initialize all variables that we clean on shutdown */
this->hidden =
(struct SDL_PrivateAudioData *) SDL_calloc(1,
(sizeof
(struct
SDL_PrivateAudioData)));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
/* Initialize channel transfer parameters to default */
QSA_InitAudioParams(&cparams);
if (device != NULL) {
/* Open requested audio device */
this->hidden->deviceno = device->deviceno;
this->hidden->cardno = device->cardno;
status = snd_pcm_open(&this->hidden->audio_handle,
device->cardno, device->deviceno,
iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
} else {
/* Open system default audio device */
status = snd_pcm_open_preferred(&this->hidden->audio_handle,
&this->hidden->cardno,
&this->hidden->deviceno,
iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
}
/* Check if requested device is opened */
if (status < 0) {
this->hidden->audio_handle = NULL;
return QSA_SetError("snd_pcm_open", status);
}
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
/* if match found set format to equivalent QSA format */
switch (test_format) {
case AUDIO_U8:
format = SND_PCM_SFMT_U8;
break;
case AUDIO_S8:
format = SND_PCM_SFMT_S8;
break;
case AUDIO_S16LSB:
format = SND_PCM_SFMT_S16_LE;
break;
case AUDIO_S16MSB:
format = SND_PCM_SFMT_S16_BE;
break;
case AUDIO_U16LSB:
format = SND_PCM_SFMT_U16_LE;
break;
case AUDIO_U16MSB:
format = SND_PCM_SFMT_U16_BE;
break;
case AUDIO_S32LSB:
format = SND_PCM_SFMT_S32_LE;
break;
case AUDIO_S32MSB:
format = SND_PCM_SFMT_S32_BE;
break;
case AUDIO_F32LSB:
format = SND_PCM_SFMT_FLOAT_LE;
break;
case AUDIO_F32MSB:
format = SND_PCM_SFMT_FLOAT_BE;
break;
default:
continue;
}
break;
}
/* assumes test_format not 0 on success */
/* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "qsa");
}
this->spec.format = test_format;
/* Set the audio format */
cparams.format.format = format;
/* Set mono/stereo/4ch/6ch/8ch audio */
cparams.format.voices = this->spec.channels;
/* Set rate */
cparams.format.rate = this->spec.freq;
/* Setup the transfer parameters according to cparams */
status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
if (status < 0) {
return QSA_SetError("snd_pcm_plugin_params", status);
}
/* Make sure channel is setup right one last time */
SDL_zero(csetup);
if (!this->iscapture) {
csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
} else {
csetup.channel = SND_PCM_CHANNEL_CAPTURE;
}
/* Setup an audio channel */
if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
return SDL_SetError("QSA: Unable to setup channel");
}
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
this->hidden->pcm_len = this->spec.size;
if (this->hidden->pcm_len == 0) {
this->hidden->pcm_len =
csetup.buf.block.frag_size * this->spec.channels *
(snd_pcm_format_width(format) / 8);
}
/*
* Allocate memory to the audio buffer and initialize with silence
* (Note that buffer size must be a multiple of fragment size, so find
* closest multiple)
*/
this->hidden->pcm_buf =
(Uint8 *) SDL_malloc(this->hidden->pcm_len);
if (this->hidden->pcm_buf == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->pcm_buf, this->spec.silence,
this->hidden->pcm_len);
/* get the file descriptor */
if (!this->iscapture) {
this->hidden->audio_fd =
snd_pcm_file_descriptor(this->hidden->audio_handle,
SND_PCM_CHANNEL_PLAYBACK);
} else {
this->hidden->audio_fd =
snd_pcm_file_descriptor(this->hidden->audio_handle,
SND_PCM_CHANNEL_CAPTURE);
}
if (this->hidden->audio_fd < 0) {
return QSA_SetError("snd_pcm_file_descriptor", status);
}
/* Prepare an audio channel */
if (!this->iscapture) {
/* Prepare audio playback */
status =
snd_pcm_plugin_prepare(this->hidden->audio_handle,
SND_PCM_CHANNEL_PLAYBACK);
} else {
/* Prepare audio capture */
status =
snd_pcm_plugin_prepare(this->hidden->audio_handle,
SND_PCM_CHANNEL_CAPTURE);
}
if (status < 0) {
return QSA_SetError("snd_pcm_plugin_prepare", status);
}
/* We're really ready to rock and roll. :-) */
return 0;
}
static void
QSA_DetectDevices(void)
{
uint32_t it;
uint32_t cards;
uint32_t devices;
int32_t status;
/* Detect amount of available devices */
/* this value can be changed in the runtime */
cards = snd_cards();
/* If io-audio manager is not running we will get 0 as number */
/* of available audio devices */
if (cards == 0) {
/* We have no any available audio devices */
return;
}
/* !!! FIXME: code duplication */
/* Find requested devices by type */
{ /* output devices */
/* Playback devices enumeration requested */
for (it = 0; it < cards; it++) {
devices = 0;
do {
status =
snd_card_get_longname(it,
qsa_playback_device
[qsa_playback_devices].name,
QSA_MAX_NAME_LENGTH);
if (status == EOK) {
snd_pcm_t *handle;
/* Add device number to device name */
sprintf(qsa_playback_device[qsa_playback_devices].name +
SDL_strlen(qsa_playback_device
[qsa_playback_devices].name), " d%d",
devices);
/* Store associated card number id */
qsa_playback_device[qsa_playback_devices].cardno = it;
/* Check if this device id could play anything */
status =
snd_pcm_open(&handle, it, devices,
SND_PCM_OPEN_PLAYBACK);
if (status == EOK) {
qsa_playback_device[qsa_playback_devices].deviceno =
devices;
status = snd_pcm_close(handle);
if (status == EOK) {
/* Note that spec is NULL, because we are required to open the device before
* acquiring the mix format, making this information inaccessible at
* enumeration time
*/
SDL_AddAudioDevice(SDL_FALSE, qsa_playback_device[qsa_playback_devices].name, NULL, &qsa_playback_device[qsa_playback_devices]);
qsa_playback_devices++;
}
} else {
/* Check if we got end of devices list */
if (status == -ENOENT) {
break;
}
}
} else {
break;
}
/* Check if we reached maximum devices count */
if (qsa_playback_devices >= QSA_MAX_DEVICES) {
break;
}
devices++;
} while (1);
/* Check if we reached maximum devices count */
if (qsa_playback_devices >= QSA_MAX_DEVICES) {
break;
}
}
}
{ /* capture devices */
/* Capture devices enumeration requested */
for (it = 0; it < cards; it++) {
devices = 0;
do {
status =
snd_card_get_longname(it,
qsa_capture_device
[qsa_capture_devices].name,
QSA_MAX_NAME_LENGTH);
if (status == EOK) {
snd_pcm_t *handle;
/* Add device number to device name */
sprintf(qsa_capture_device[qsa_capture_devices].name +
SDL_strlen(qsa_capture_device
[qsa_capture_devices].name), " d%d",
devices);
/* Store associated card number id */
qsa_capture_device[qsa_capture_devices].cardno = it;
/* Check if this device id could play anything */
status =
snd_pcm_open(&handle, it, devices,
SND_PCM_OPEN_CAPTURE);
if (status == EOK) {
qsa_capture_device[qsa_capture_devices].deviceno =
devices;
status = snd_pcm_close(handle);
if (status == EOK) {
/* Note that spec is NULL, because we are required to open the device before
* acquiring the mix format, making this information inaccessible at
* enumeration time
*/
SDL_AddAudioDevice(SDL_TRUE, qsa_capture_device[qsa_capture_devices].name, NULL, &qsa_capture_device[qsa_capture_devices]);
qsa_capture_devices++;
}
} else {
/* Check if we got end of devices list */
if (status == -ENOENT) {
break;
}
}
/* Check if we reached maximum devices count */
if (qsa_capture_devices >= QSA_MAX_DEVICES) {
break;
}
} else {
break;
}
devices++;
} while (1);
/* Check if we reached maximum devices count */
if (qsa_capture_devices >= QSA_MAX_DEVICES) {
break;
}
}
}
}
static void
QSA_Deinitialize(void)
{
/* Clear devices array on shutdown */
/* !!! FIXME: we zero these on init...any reason to do it here? */
SDL_zeroa(qsa_playback_device);
SDL_zeroa(qsa_capture_device);
qsa_playback_devices = 0;
qsa_capture_devices = 0;
}
static SDL_bool
QSA_Init(SDL_AudioDriverImpl * impl)
{
/* Clear devices array */
SDL_zeroa(qsa_playback_device);
SDL_zeroa(qsa_capture_device);
qsa_playback_devices = 0;
qsa_capture_devices = 0;
/* Set function pointers */
/* DeviceLock and DeviceUnlock functions are used default, */
/* provided by SDL, which uses pthread_mutex for lock/unlock */
impl->DetectDevices = QSA_DetectDevices;
impl->OpenDevice = QSA_OpenDevice;
impl->ThreadInit = QSA_ThreadInit;
impl->WaitDevice = QSA_WaitDevice;
impl->PlayDevice = QSA_PlayDevice;
impl->GetDeviceBuf = QSA_GetDeviceBuf;
impl->CloseDevice = QSA_CloseDevice;
impl->Deinitialize = QSA_Deinitialize;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap QSAAUDIO_bootstrap = {
"qsa", "QNX QSA Audio", QSA_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_QSA */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,420 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_SUNAUDIO
/* Allow access to a raw mixing buffer */
#include <fcntl.h>
#include <errno.h>
#ifdef __NETBSD__
#include <sys/ioctl.h>
#include <sys/audioio.h>
#endif
#ifdef __SVR4
#include <sys/audioio.h>
#else
#include <sys/time.h>
#include <sys/types.h>
#endif
#include <unistd.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../../core/unix/SDL_poll.h"
#include "../SDL_audio_c.h"
#include "../SDL_audiodev_c.h"
#include "SDL_sunaudio.h"
/* Open the audio device for playback, and don't block if busy */
#if defined(AUDIO_GETINFO) && !defined(AUDIO_GETBUFINFO)
#define AUDIO_GETBUFINFO AUDIO_GETINFO
#endif
/* Audio driver functions */
static Uint8 snd2au(int sample);
/* Audio driver bootstrap functions */
static void
SUNAUDIO_DetectDevices(void)
{
SDL_EnumUnixAudioDevices(1, (int (*)(int)) NULL);
}
#ifdef DEBUG_AUDIO
void
CheckUnderflow(_THIS)
{
#ifdef AUDIO_GETBUFINFO
audio_info_t info;
int left;
ioctl(this->hidden->audio_fd, AUDIO_GETBUFINFO, &info);
left = (this->hidden->written - info.play.samples);
if (this->hidden->written && (left == 0)) {
fprintf(stderr, "audio underflow!\n");
}
#endif
}
#endif
static void
SUNAUDIO_WaitDevice(_THIS)
{
#ifdef AUDIO_GETBUFINFO
#define SLEEP_FUDGE 10 /* 10 ms scheduling fudge factor */
audio_info_t info;
Sint32 left;
ioctl(this->hidden->audio_fd, AUDIO_GETBUFINFO, &info);
left = (this->hidden->written - info.play.samples);
if (left > this->hidden->fragsize) {
Sint32 sleepy;
sleepy = ((left - this->hidden->fragsize) / this->hidden->frequency);
sleepy -= SLEEP_FUDGE;
if (sleepy > 0) {
SDL_Delay(sleepy);
}
}
#else
SDL_IOReady(this->hidden->audio_fd, SDL_IOR_WRITE, -1);
#endif
}
static void
SUNAUDIO_PlayDevice(_THIS)
{
/* Write the audio data */
if (this->hidden->ulaw_only) {
/* Assuming that this->spec.freq >= 8000 Hz */
int accum, incr, pos;
Uint8 *aubuf;
accum = 0;
incr = this->spec.freq / 8;
aubuf = this->hidden->ulaw_buf;
switch (this->hidden->audio_fmt & 0xFF) {
case 8:
{
Uint8 *sndbuf;
sndbuf = this->hidden->mixbuf;
for (pos = 0; pos < this->hidden->fragsize; ++pos) {
*aubuf = snd2au((0x80 - *sndbuf) * 64);
accum += incr;
while (accum > 0) {
accum -= 1000;
sndbuf += 1;
}
aubuf += 1;
}
}
break;
case 16:
{
Sint16 *sndbuf;
sndbuf = (Sint16 *) this->hidden->mixbuf;
for (pos = 0; pos < this->hidden->fragsize; ++pos) {
*aubuf = snd2au(*sndbuf / 4);
accum += incr;
while (accum > 0) {
accum -= 1000;
sndbuf += 1;
}
aubuf += 1;
}
}
break;
}
#ifdef DEBUG_AUDIO
CheckUnderflow(this);
#endif
if (write(this->hidden->audio_fd, this->hidden->ulaw_buf,
this->hidden->fragsize) < 0) {
/* Assume fatal error, for now */
SDL_OpenedAudioDeviceDisconnected(this);
}
this->hidden->written += this->hidden->fragsize;
} else {
#ifdef DEBUG_AUDIO
CheckUnderflow(this);
#endif
if (write(this->hidden->audio_fd, this->hidden->mixbuf,
this->spec.size) < 0) {
/* Assume fatal error, for now */
SDL_OpenedAudioDeviceDisconnected(this);
}
this->hidden->written += this->hidden->fragsize;
}
}
static Uint8 *
SUNAUDIO_GetDeviceBuf(_THIS)
{
return (this->hidden->mixbuf);
}
static void
SUNAUDIO_CloseDevice(_THIS)
{
SDL_free(this->hidden->ulaw_buf);
if (this->hidden->audio_fd >= 0) {
close(this->hidden->audio_fd);
}
SDL_free(this->hidden->mixbuf);
SDL_free(this->hidden);
}
static int
SUNAUDIO_OpenDevice(_THIS, const char *devname)
{
#ifdef AUDIO_SETINFO
int enc;
#endif
SDL_bool iscapture = this->iscapture;
int desired_freq = 0;
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
SDL_AudioFormat format = 0;
audio_info_t info;
/* We don't care what the devname is...we'll try to open anything. */
/* ...but default to first name in the list... */
if (devname == NULL) {
devname = SDL_GetAudioDeviceName(0, iscapture);
if (devname == NULL) {
return SDL_SetError("No such audio device");
}
}
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
SDL_zerop(this->hidden);
/* Open the audio device */
this->hidden->audio_fd = open(devname, flags, 0);
if (this->hidden->audio_fd < 0) {
return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
}
desired_freq = this->spec.freq;
/* Determine the audio parameters from the AudioSpec */
switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
case 8:
{ /* Unsigned 8 bit audio data */
this->spec.format = AUDIO_U8;
#ifdef AUDIO_SETINFO
enc = AUDIO_ENCODING_LINEAR8;
#endif
}
break;
case 16:
{ /* Signed 16 bit audio data */
this->spec.format = AUDIO_S16SYS;
#ifdef AUDIO_SETINFO
enc = AUDIO_ENCODING_LINEAR;
#endif
}
break;
default:
{
/* !!! FIXME: fallback to conversion on unsupported types! */
return SDL_SetError("Unsupported audio format");
}
}
this->hidden->audio_fmt = this->spec.format;
this->hidden->ulaw_only = 0; /* modern Suns do support linear audio */
#ifdef AUDIO_SETINFO
for (;;) {
audio_info_t info;
AUDIO_INITINFO(&info); /* init all fields to "no change" */
/* Try to set the requested settings */
info.play.sample_rate = this->spec.freq;
info.play.channels = this->spec.channels;
info.play.precision = (enc == AUDIO_ENCODING_ULAW)
? 8 : this->spec.format & 0xff;
info.play.encoding = enc;
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
/* Check to be sure we got what we wanted */
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
return SDL_SetError("Error getting audio parameters: %s",
strerror(errno));
}
if (info.play.encoding == enc
&& info.play.precision == (this->spec.format & 0xff)
&& info.play.channels == this->spec.channels) {
/* Yow! All seems to be well! */
this->spec.freq = info.play.sample_rate;
break;
}
}
switch (enc) {
case AUDIO_ENCODING_LINEAR8:
/* unsigned 8bit apparently not supported here */
enc = AUDIO_ENCODING_LINEAR;
this->spec.format = AUDIO_S16SYS;
break; /* try again */
case AUDIO_ENCODING_LINEAR:
/* linear 16bit didn't work either, resort to µ-law */
enc = AUDIO_ENCODING_ULAW;
this->spec.channels = 1;
this->spec.freq = 8000;
this->spec.format = AUDIO_U8;
this->hidden->ulaw_only = 1;
break;
default:
/* oh well... */
return SDL_SetError("Error setting audio parameters: %s",
strerror(errno));
}
}
#endif /* AUDIO_SETINFO */
this->hidden->written = 0;
/* We can actually convert on-the-fly to U-Law */
if (this->hidden->ulaw_only) {
this->spec.freq = desired_freq;
this->hidden->fragsize = (this->spec.samples * 1000) /
(this->spec.freq / 8);
this->hidden->frequency = 8;
this->hidden->ulaw_buf = (Uint8 *) SDL_malloc(this->hidden->fragsize);
if (this->hidden->ulaw_buf == NULL) {
return SDL_OutOfMemory();
}
this->spec.channels = 1;
} else {
this->hidden->fragsize = this->spec.samples;
this->hidden->frequency = this->spec.freq / 1000;
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Audio device %s U-Law only\n",
this->hidden->ulaw_only ? "is" : "is not");
fprintf(stderr, "format=0x%x chan=%d freq=%d\n",
this->spec.format, this->spec.channels, this->spec.freq);
#endif
/* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(&this->spec);
/* Allocate mixing buffer */
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);
/* We're ready to rock and roll. :-) */
return 0;
}
/************************************************************************/
/* This function (snd2au()) copyrighted: */
/************************************************************************/
/* Copyright 1989 by Rich Gopstein and Harris Corporation */
/* */
/* Permission to use, copy, modify, and distribute this software */
/* and its documentation for any purpose and without fee is */
/* hereby granted, provided that the above copyright notice */
/* appears in all copies and that both that copyright notice and */
/* this permission notice appear in supporting documentation, and */
/* that the name of Rich Gopstein and Harris Corporation not be */
/* used in advertising or publicity pertaining to distribution */
/* of the software without specific, written prior permission. */
/* Rich Gopstein and Harris Corporation make no representations */
/* about the suitability of this software for any purpose. It */
/* provided "as is" without express or implied warranty. */
/************************************************************************/
static Uint8
snd2au(int sample)
{
int mask;
if (sample < 0) {
sample = -sample;
mask = 0x7f;
} else {
mask = 0xff;
}
if (sample < 32) {
sample = 0xF0 | (15 - sample / 2);
} else if (sample < 96) {
sample = 0xE0 | (15 - (sample - 32) / 4);
} else if (sample < 224) {
sample = 0xD0 | (15 - (sample - 96) / 8);
} else if (sample < 480) {
sample = 0xC0 | (15 - (sample - 224) / 16);
} else if (sample < 992) {
sample = 0xB0 | (15 - (sample - 480) / 32);
} else if (sample < 2016) {
sample = 0xA0 | (15 - (sample - 992) / 64);
} else if (sample < 4064) {
sample = 0x90 | (15 - (sample - 2016) / 128);
} else if (sample < 8160) {
sample = 0x80 | (15 - (sample - 4064) / 256);
} else {
sample = 0x80;
}
return (mask & sample);
}
static SDL_bool
SUNAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
impl->DetectDevices = SUNAUDIO_DetectDevices;
impl->OpenDevice = SUNAUDIO_OpenDevice;
impl->PlayDevice = SUNAUDIO_PlayDevice;
impl->WaitDevice = SUNAUDIO_WaitDevice;
impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf;
impl->CloseDevice = SUNAUDIO_CloseDevice;
impl->AllowsArbitraryDeviceNames = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap SUNAUDIO_bootstrap = {
"audio", "UNIX /dev/audio interface", SUNAUDIO_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_SUNAUDIO */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,47 +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.
*/
#include "../../SDL_internal.h"
#ifndef SDL_sunaudio_h_
#define SDL_sunaudio_h_
#include "../SDL_sysaudio.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData
{
/* The file descriptor for the audio device */
int audio_fd;
SDL_AudioFormat audio_fmt; /* The app audio format */
Uint8 *mixbuf; /* The app mixing buffer */
int ulaw_only; /* Flag -- does hardware only output U-law? */
Uint8 *ulaw_buf; /* The U-law mixing buffer */
Sint32 written; /* The number of samples written */
int fragsize; /* The audio fragment size in samples */
int frequency; /* The audio frequency in KHz */
};
#endif /* SDL_sunaudio_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -46,13 +46,27 @@
#endif
/* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */
static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32,{ 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
static 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 } };
/* handle to Avrt.dll--Vista and later!--for flagging the callback thread as "Pro Audio" (low latency). */
static HMODULE libavrt = NULL;
typedef HANDLE(WINAPI *pfnAvSetMmThreadCharacteristicsW)(LPCWSTR, LPDWORD);
typedef BOOL(WINAPI *pfnAvRevertMmThreadCharacteristics)(HANDLE);
static pfnAvSetMmThreadCharacteristicsW pAvSetMmThreadCharacteristicsW = NULL;
static pfnAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL;
static void
WASAPI_DetectDevices(void)
{
WASAPI_EnumerateEndpoints();
SDL_IMMDevice_EnumerateEndpoints(SDL_FALSE);
}
int
WASAPI_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
{
return SDL_IMMDevice_GetDefaultAudioInfo(name, spec, iscapture);
}
static SDL_INLINE SDL_bool
@@ -126,7 +140,7 @@ UpdateAudioStream(_THIS, const SDL_AudioSpec *oldspec)
return 0;
}
static int ActivateWasapiDevice(_THIS, SDL_bool isrecovery);
static void ReleaseWasapiDevice(_THIS);
static SDL_bool
@@ -143,7 +157,7 @@ RecoverWasapiDevice(_THIS)
devices try to reinitialize whatever the new default is, so it's more
likely to carry on here, but this handles a non-default device that
simply had its format changed in the Windows Control Panel. */
if (WASAPI_ActivateDevice(this, SDL_TRUE) == -1) {
if (ActivateWasapiDevice(this, SDL_TRUE) == -1) {
SDL_OpenedAudioDeviceDisconnected(this);
return SDL_FALSE;
}
@@ -349,11 +363,6 @@ ReleaseWasapiDevice(_THIS)
this->hidden->capturestream = NULL;
}
if (this->hidden->activation_handler) {
WASAPI_PlatformDeleteActivationHandler(this->hidden->activation_handler);
this->hidden->activation_handler = NULL;
}
if (this->hidden->event) {
CloseHandle(this->hidden->event);
this->hidden->event = NULL;
@@ -362,18 +371,6 @@ ReleaseWasapiDevice(_THIS)
static void
WASAPI_CloseDevice(_THIS)
{
WASAPI_UnrefDevice(this);
}
void
WASAPI_RefDevice(_THIS)
{
SDL_AtomicIncRef(&this->hidden->refcount);
}
void
WASAPI_UnrefDevice(_THIS)
{
if (!SDL_AtomicDecRef(&this->hidden->refcount)) {
return;
@@ -390,7 +387,7 @@ WASAPI_UnrefDevice(_THIS)
}
/* This is called once a device is activated, possibly asynchronously. */
int
static int
WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
{
/* !!! FIXME: we could request an exclusive mode stream, which is lower latency;
@@ -419,7 +416,7 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
SDL_assert(client != NULL);
#if defined(__WINRT__) || defined(__GDK__) /* CreateEventEx() arrived in Vista, so we need an #ifdef for XP. */
#if 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);
@@ -458,7 +455,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 */
@@ -538,6 +538,34 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
return 0; /* good to go. */
}
static int
ActivateWasapiDevice(_THIS, const SDL_bool isrecovery)
{
IMMDevice *device = NULL;
HRESULT ret;
if (SDL_IMMDevice_Get(this->hidden->devid, &device, this->iscapture) < 0) {
this->hidden->client = NULL;
return -1; /* This is already set by SDL_IMMDevice_Get */
}
/* this is not async in standard win32, yay! */
ret = IMMDevice_Activate(device, &SDL_IID_IAudioClient, CLSCTX_ALL, NULL, (void **) &this->hidden->client);
IMMDevice_Release(device);
if (FAILED(ret)) {
SDL_assert(this->hidden->client == NULL);
return WIN_SetErrorFromHRESULT("WASAPI can't activate audio endpoint", ret);
}
SDL_assert(this->hidden->client != NULL);
if (WASAPI_PrepDevice(this, isrecovery) == -1) { /* not async, fire it right away. */
return -1;
}
return 0; /* good to go. */
}
static int
WASAPI_OpenDevice(_THIS, const char *devname)
@@ -552,7 +580,7 @@ WASAPI_OpenDevice(_THIS, const char *devname)
}
SDL_zerop(this->hidden);
WASAPI_RefDevice(this); /* so CloseDevice() will unref to zero. */
SDL_AtomicIncRef(&this->hidden->refcount); /* so CloseDevice() will unref to zero. */
if (!devid) { /* is default device? */
this->hidden->default_device_generation = SDL_AtomicGet(this->iscapture ? &SDL_IMMDevice_DefaultCaptureGeneration : &SDL_IMMDevice_DefaultPlaybackGeneration);
@@ -563,7 +591,7 @@ WASAPI_OpenDevice(_THIS, const char *devname)
}
}
if (WASAPI_ActivateDevice(this, SDL_FALSE) == -1) {
if (ActivateWasapiDevice(this, SDL_FALSE) == -1) {
return -1; /* already set error. */
}
@@ -581,26 +609,58 @@ WASAPI_OpenDevice(_THIS, const char *devname)
static void
WASAPI_ThreadInit(_THIS)
{
WASAPI_PlatformThreadInit(this);
/* this thread uses COM. */
if (SUCCEEDED(WIN_CoInitialize())) { /* can't report errors, hope it worked! */
this->hidden->coinitialized = SDL_TRUE;
}
/* Set this thread to very high "Pro Audio" priority. */
if (pAvSetMmThreadCharacteristicsW) {
DWORD idx = 0;
this->hidden->task = pAvSetMmThreadCharacteristicsW(L"Pro Audio", &idx);
}
}
static void
WASAPI_ThreadDeinit(_THIS)
{
WASAPI_PlatformThreadDeinit(this);
/* Set this thread back to normal priority. */
if (this->hidden->task && pAvRevertMmThreadCharacteristics) {
pAvRevertMmThreadCharacteristics(this->hidden->task);
this->hidden->task = NULL;
}
if (this->hidden->coinitialized) {
WIN_CoUninitialize();
this->hidden->coinitialized = SDL_FALSE;
}
}
static void
WASAPI_Deinitialize(void)
{
WASAPI_PlatformDeinit();
if (libavrt) {
FreeLibrary(libavrt);
libavrt = NULL;
}
pAvSetMmThreadCharacteristicsW = NULL;
pAvRevertMmThreadCharacteristics = NULL;
SDL_IMMDevice_Quit();
}
static SDL_bool
WASAPI_Init(SDL_AudioDriverImpl * impl)
{
if (WASAPI_PlatformInit() == -1) {
return SDL_FALSE;
if (SDL_IMMDevice_Init() < 0) {
return SDL_FALSE; /* Error 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! */
if (libavrt) {
pAvSetMmThreadCharacteristicsW = (pfnAvSetMmThreadCharacteristicsW) GetProcAddress(libavrt, "AvSetMmThreadCharacteristicsW");
pAvRevertMmThreadCharacteristics = (pfnAvRevertMmThreadCharacteristics) GetProcAddress(libavrt, "AvRevertMmThreadCharacteristics");
}
/* Set the function pointers */

View File

@@ -51,25 +51,8 @@ struct SDL_PrivateAudioData
int framesize;
int default_device_generation;
SDL_bool device_lost;
void *activation_handler;
SDL_atomic_t just_activated;
};
/* win32 and winrt implementations call into these. */
int WASAPI_PrepDevice(_THIS, const SDL_bool updatestream);
void WASAPI_RefDevice(_THIS);
void WASAPI_UnrefDevice(_THIS);
/* 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);
void WASAPI_PlatformDeleteActivationHandler(void *handler);
#ifdef __cplusplus
}
#endif

View File

@@ -1,162 +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.
*/
#include "../../SDL_internal.h"
/* This is code that Windows uses to talk to WASAPI-related system APIs.
This is for non-WinRT desktop apps. The C++/CX implementation of these
functions, exclusive to WinRT, are in SDL_wasapi_winrt.cpp.
The code in SDL_wasapi.c is used by both standard Windows and WinRT builds
to deal with audio and calls into these functions. */
#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"
#include <audioclient.h>
#include "SDL_wasapi.h"
/* handle to Avrt.dll--Vista and later!--for flagging the callback thread as "Pro Audio" (low latency). */
static HMODULE libavrt = NULL;
typedef HANDLE(WINAPI *pfnAvSetMmThreadCharacteristicsW)(LPCWSTR, LPDWORD);
typedef BOOL(WINAPI *pfnAvRevertMmThreadCharacteristics)(HANDLE);
static pfnAvSetMmThreadCharacteristicsW pAvSetMmThreadCharacteristicsW = NULL;
static pfnAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL;
/* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */
static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32,{ 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
int
WASAPI_PlatformInit(void)
{
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! */
if (libavrt) {
pAvSetMmThreadCharacteristicsW = (pfnAvSetMmThreadCharacteristicsW) GetProcAddress(libavrt, "AvSetMmThreadCharacteristicsW");
pAvRevertMmThreadCharacteristics = (pfnAvRevertMmThreadCharacteristics) GetProcAddress(libavrt, "AvRevertMmThreadCharacteristics");
}
return 0;
}
void
WASAPI_PlatformDeinit(void)
{
if (libavrt) {
FreeLibrary(libavrt);
libavrt = NULL;
}
pAvSetMmThreadCharacteristicsW = NULL;
pAvRevertMmThreadCharacteristics = NULL;
SDL_IMMDevice_Quit();
}
void
WASAPI_PlatformThreadInit(_THIS)
{
/* this thread uses COM. */
if (SUCCEEDED(WIN_CoInitialize())) { /* can't report errors, hope it worked! */
this->hidden->coinitialized = SDL_TRUE;
}
/* Set this thread to very high "Pro Audio" priority. */
if (pAvSetMmThreadCharacteristicsW) {
DWORD idx = 0;
this->hidden->task = pAvSetMmThreadCharacteristicsW(L"Pro Audio", &idx);
}
}
void
WASAPI_PlatformThreadDeinit(_THIS)
{
/* Set this thread back to normal priority. */
if (this->hidden->task && pAvRevertMmThreadCharacteristics) {
pAvRevertMmThreadCharacteristics(this->hidden->task);
this->hidden->task = NULL;
}
if (this->hidden->coinitialized) {
WIN_CoUninitialize();
this->hidden->coinitialized = SDL_FALSE;
}
}
int
WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
{
IMMDevice *device = NULL;
HRESULT ret;
if (SDL_IMMDevice_Get(this->hidden->devid, &device, this->iscapture) < 0) {
this->hidden->client = NULL;
return -1; /* This is already set by SDL_IMMDevice_Get */
}
/* this is not async in standard win32, yay! */
ret = IMMDevice_Activate(device, &SDL_IID_IAudioClient, CLSCTX_ALL, NULL, (void **) &this->hidden->client);
IMMDevice_Release(device);
if (FAILED(ret)) {
SDL_assert(this->hidden->client == NULL);
return WIN_SetErrorFromHRESULT("WASAPI can't activate audio endpoint", ret);
}
SDL_assert(this->hidden->client != NULL);
if (WASAPI_PrepDevice(this, isrecovery) == -1) { /* not async, fire it right away. */
return -1;
}
return 0; /* good to go. */
}
void
WASAPI_EnumerateEndpoints(void)
{
SDL_IMMDevice_EnumerateEndpoints(SDL_FALSE);
}
int
WASAPI_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
{
return SDL_IMMDevice_GetDefaultAudioInfo(name, spec, iscapture);
}
void
WASAPI_PlatformDeleteActivationHandler(void *handler)
{
/* not asynchronous. */
SDL_assert(!"This function should have only been called on WinRT.");
}
#endif /* SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__) */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,447 +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.
*/
#include "../../SDL_internal.h"
// This is C++/CX code that the WinRT port uses to talk to WASAPI-related
// system APIs. The C implementation of these functions, for non-WinRT apps,
// is in SDL_wasapi_win32.c. The code in SDL_wasapi.c is used by both standard
// Windows and WinRT builds to deal with audio and calls into these functions.
#if SDL_AUDIO_DRIVER_WASAPI && defined(__WINRT__)
#include <Windows.h>
#include <windows.ui.core.h>
#include <windows.devices.enumeration.h>
#include <windows.media.devices.h>
#include <wrl/implements.h>
#include <collection.h>
extern "C" {
#include "../../core/windows/SDL_windows.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"
using namespace Windows::Devices::Enumeration;
using namespace Windows::Media::Devices;
using namespace Windows::Foundation;
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:
SDL_WasapiDeviceEventHandler(const SDL_bool _iscapture);
~SDL_WasapiDeviceEventHandler();
void OnDeviceAdded(DeviceWatcher^ sender, DeviceInformation^ args);
void OnDeviceRemoved(DeviceWatcher^ sender, DeviceInformationUpdate^ args);
void OnDeviceUpdated(DeviceWatcher^ sender, DeviceInformationUpdate^ args);
void OnEnumerationCompleted(DeviceWatcher^ sender, Platform::Object^ args);
void OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args);
void OnDefaultCaptureDeviceChanged(Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args);
SDL_semaphore* completed;
private:
const SDL_bool iscapture;
DeviceWatcher^ watcher;
Windows::Foundation::EventRegistrationToken added_handler;
Windows::Foundation::EventRegistrationToken removed_handler;
Windows::Foundation::EventRegistrationToken updated_handler;
Windows::Foundation::EventRegistrationToken completed_handler;
Windows::Foundation::EventRegistrationToken default_changed_handler;
};
SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(const SDL_bool _iscapture)
: iscapture(_iscapture)
, completed(SDL_CreateSemaphore(0))
{
if (!completed)
return; // uhoh.
Platform::String^ selector = _iscapture ? MediaDevice::GetAudioCaptureSelector() :
MediaDevice::GetAudioRenderSelector();
Platform::Collections::Vector<Platform::String^> properties;
properties.Append(SDL_PKEY_AudioEngine_DeviceFormat);
watcher = DeviceInformation::CreateWatcher(selector, properties.GetView());
if (!watcher)
return; // uhoh.
// !!! FIXME: this doesn't need a lambda here, I think, if I make SDL_WasapiDeviceEventHandler a proper C++/CX class. --ryan.
added_handler = watcher->Added += ref new TypedEventHandler<DeviceWatcher^, DeviceInformation^>([this](DeviceWatcher^ sender, DeviceInformation^ args) { OnDeviceAdded(sender, args); } );
removed_handler = watcher->Removed += ref new TypedEventHandler<DeviceWatcher^, DeviceInformationUpdate^>([this](DeviceWatcher^ sender, DeviceInformationUpdate^ args) { OnDeviceRemoved(sender, args); } );
updated_handler = watcher->Updated += ref new TypedEventHandler<DeviceWatcher^, DeviceInformationUpdate^>([this](DeviceWatcher^ sender, DeviceInformationUpdate^ args) { OnDeviceUpdated(sender, args); } );
completed_handler = watcher->EnumerationCompleted += ref new TypedEventHandler<DeviceWatcher^, Platform::Object^>([this](DeviceWatcher^ sender, Platform::Object^ args) { OnEnumerationCompleted(sender, args); } );
if (iscapture) {
default_changed_handler = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler<Platform::Object^, DefaultAudioCaptureDeviceChangedEventArgs^>([this](Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args) { OnDefaultCaptureDeviceChanged(sender, args); } );
} else {
default_changed_handler = MediaDevice::DefaultAudioRenderDeviceChanged += ref new TypedEventHandler<Platform::Object^, DefaultAudioRenderDeviceChangedEventArgs^>([this](Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args) { OnDefaultRenderDeviceChanged(sender, args); } );
}
watcher->Start();
}
SDL_WasapiDeviceEventHandler::~SDL_WasapiDeviceEventHandler()
{
if (watcher) {
watcher->Added -= added_handler;
watcher->Removed -= removed_handler;
watcher->Updated -= updated_handler;
watcher->EnumerationCompleted -= completed_handler;
watcher->Stop();
watcher = nullptr;
}
if (completed) {
SDL_DestroySemaphore(completed);
completed = nullptr;
}
if (iscapture) {
MediaDevice::DefaultAudioCaptureDeviceChanged -= default_changed_handler;
} else {
MediaDevice::DefaultAudioRenderDeviceChanged -= default_changed_handler;
}
}
void
SDL_WasapiDeviceEventHandler::OnDeviceAdded(DeviceWatcher^ sender, DeviceInformation^ info)
{
SDL_assert(sender == this->watcher);
char *utf8dev = WIN_StringToUTF8(info->Name->Data());
if (utf8dev) {
WAVEFORMATEXTENSIBLE fmt;
Platform::Object^ obj = info->Properties->Lookup(SDL_PKEY_AudioEngine_DeviceFormat);
if (obj) {
IPropertyValue^ property = (IPropertyValue^) obj;
Platform::Array<unsigned char>^ data;
property->GetUInt8Array(&data);
SDL_memcpy(&fmt, data->Data, SDL_min(data->Length, sizeof(WAVEFORMATEXTENSIBLE)));
} else {
SDL_zero(fmt);
}
WASAPI_AddDevice(this->iscapture, utf8dev, &fmt, info->Id->Data());
SDL_free(utf8dev);
}
}
void
SDL_WasapiDeviceEventHandler::OnDeviceRemoved(DeviceWatcher^ sender, DeviceInformationUpdate^ info)
{
SDL_assert(sender == this->watcher);
WASAPI_RemoveDevice(this->iscapture, info->Id->Data());
}
void
SDL_WasapiDeviceEventHandler::OnDeviceUpdated(DeviceWatcher^ sender, DeviceInformationUpdate^ args)
{
SDL_assert(sender == this->watcher);
}
void
SDL_WasapiDeviceEventHandler::OnEnumerationCompleted(DeviceWatcher^ sender, Platform::Object^ args)
{
SDL_assert(sender == this->watcher);
SDL_SemPost(this->completed);
}
void
SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args)
{
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(&SDL_IMMDevice_DefaultCaptureGeneration, 1);
}
static SDL_WasapiDeviceEventHandler *playback_device_event_handler;
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)
{
// DeviceWatchers will fire an Added event for each existing device at
// startup, so we don't need to enumerate them separately before
// listening for updates.
playback_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_FALSE);
capture_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_TRUE);
SDL_SemWait(playback_device_event_handler->completed);
SDL_SemWait(capture_device_event_handler->completed);
}
struct SDL_WasapiActivationHandler : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >
{
SDL_WasapiActivationHandler() : device(nullptr) {}
STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation *operation);
SDL_AudioDevice *device;
};
HRESULT
SDL_WasapiActivationHandler::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *async)
{
// Just set a flag, since we're probably in a different thread. We'll pick it up and init everything on our own thread to prevent races.
SDL_AtomicSet(&device->hidden->just_activated, 1);
WASAPI_UnrefDevice(device);
return S_OK;
}
void
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)
{
LPCWSTR devid = _this->hidden->devid;
Platform::String^ defdevid;
if (devid == nullptr) {
defdevid = _this->iscapture ? MediaDevice::GetDefaultAudioCaptureId(AudioDeviceRole::Default) : MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
if (defdevid) {
devid = defdevid->Data();
}
}
SDL_AtomicSet(&_this->hidden->just_activated, 0);
ComPtr<SDL_WasapiActivationHandler> handler = Make<SDL_WasapiActivationHandler>();
if (handler == nullptr) {
return SDL_SetError("Failed to allocate WASAPI activation handler");
}
handler.Get()->AddRef(); // we hold a reference after ComPtr destructs on return, causing a Release, and Release ourselves in WASAPI_PlatformDeleteActivationHandler(), etc.
handler.Get()->device = _this;
_this->hidden->activation_handler = handler.Get();
WASAPI_RefDevice(_this); /* completion handler will unref it. */
IActivateAudioInterfaceAsyncOperation *async = nullptr;
const HRESULT ret = ActivateAudioInterfaceAsync(devid, __uuidof(IAudioClient), nullptr, handler.Get(), &async);
if (FAILED(ret) || async == nullptr) {
if (async != nullptr) {
async->Release();
}
handler.Get()->Release();
WASAPI_UnrefDevice(_this);
return WIN_SetErrorFromHRESULT("WASAPI can't activate requested audio endpoint", ret);
}
/* Spin until the async operation is complete.
* If we don't PrepDevice before leaving this function, the bug list gets LONG:
* - device.spec is not filled with the correct information
* - The 'obtained' spec will be wrong for ALLOW_CHANGE properties
* - SDL_AudioStreams will/will not be allocated at the right time
* - SDL_assert(device->callbackspec.size == device->spec.size) will fail
* - When the assert is ignored, skipping or a buffer overflow will occur
*/
while (!SDL_AtomicCAS(&_this->hidden->just_activated, 1, 0)) {
SDL_Delay(1);
}
HRESULT activateRes = S_OK;
IUnknown *iunknown = nullptr;
const HRESULT getActivateRes = async->GetActivateResult(&activateRes, &iunknown);
async->Release();
if (FAILED(getActivateRes)) {
return WIN_SetErrorFromHRESULT("Failed to get WASAPI activate result", getActivateRes);
} else if (FAILED(activateRes)) {
return WIN_SetErrorFromHRESULT("Failed to activate WASAPI device", activateRes);
}
iunknown->QueryInterface(IID_PPV_ARGS(&_this->hidden->client));
if (!_this->hidden->client) {
return SDL_SetError("Failed to query WASAPI client interface");
}
if (WASAPI_PrepDevice(_this, isrecovery) == -1) {
return -1;
}
return 0;
}
void
WASAPI_PlatformThreadInit(_THIS)
{
// !!! FIXME: set this thread to "Pro Audio" priority.
}
void
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: */

View File

@@ -1,459 +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.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_WINMM
/* Allow access to a raw mixing buffer */
#include "../../core/windows/SDL_windows.h"
#include <mmsystem.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_winmm.h"
/* MinGW32 mmsystem.h doesn't include these structures */
#if defined(__MINGW32__) && defined(_MMSYSTEM_H)
typedef struct tagWAVEINCAPS2W
{
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
WCHAR szPname[MAXPNAMELEN];
DWORD dwFormats;
WORD wChannels;
WORD wReserved1;
GUID ManufacturerGuid;
GUID ProductGuid;
GUID NameGuid;
} WAVEINCAPS2W,*PWAVEINCAPS2W,*NPWAVEINCAPS2W,*LPWAVEINCAPS2W;
typedef struct tagWAVEOUTCAPS2W
{
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
WCHAR szPname[MAXPNAMELEN];
DWORD dwFormats;
WORD wChannels;
WORD wReserved1;
DWORD dwSupport;
GUID ManufacturerGuid;
GUID ProductGuid;
GUID NameGuid;
} WAVEOUTCAPS2W,*PWAVEOUTCAPS2W,*NPWAVEOUTCAPS2W,*LPWAVEOUTCAPS2W;
#endif /* defined(__MINGW32__) && defined(_MMSYSTEM_H) */
#ifndef WAVE_FORMAT_IEEE_FLOAT
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif
#define DETECT_DEV_IMPL(iscap, typ, capstyp) \
static void DetectWave##typ##Devs(void) { \
const UINT iscapture = iscap ? 1 : 0; \
const UINT devcount = wave##typ##GetNumDevs(); \
capstyp##2W caps; \
SDL_AudioSpec spec; \
UINT i; \
SDL_zero(spec); \
for (i = 0; i < devcount; i++) { \
if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \
if (name != NULL) { \
/* Note that freq/format are not filled in, as this information \
* is not provided by the caps struct! At best, we get possible \
* sample formats, but not an _active_ format. \
*/ \
spec.channels = (Uint8)caps.wChannels; \
SDL_AddAudioDevice((int) iscapture, name, &spec, (void *) ((size_t) i+1)); \
SDL_free(name); \
} \
} \
} \
}
DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS)
DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS)
static void
WINMM_DetectDevices(void)
{
DetectWaveInDevs();
DetectWaveOutDevs();
}
static void CALLBACK
CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
/* Only service "buffer is filled" messages */
if (uMsg != WIM_DATA)
return;
/* Signal that we have a new buffer of data */
ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
}
/* The Win32 callback for filling the WAVE device */
static void CALLBACK
FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
/* Only service "buffer done playing" messages */
if (uMsg != WOM_DONE)
return;
/* Signal that we are done playing a buffer */
ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
}
static int
SetMMerror(const char *function, MMRESULT code)
{
int len;
char errbuf[MAXERRORLENGTH];
wchar_t werrbuf[MAXERRORLENGTH];
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
len = SDL_static_cast(int, SDL_strlen(errbuf));
waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
MAXERRORLENGTH - len, NULL, NULL);
return SDL_SetError("%s", errbuf);
}
static void
WINMM_WaitDevice(_THIS)
{
/* Wait for an audio chunk to finish */
WaitForSingleObject(this->hidden->audio_sem, INFINITE);
}
static Uint8 *
WINMM_GetDeviceBuf(_THIS)
{
return (Uint8 *) (this->hidden->
wavebuf[this->hidden->next_buffer].lpData);
}
static void
WINMM_PlayDevice(_THIS)
{
/* Queue it up */
waveOutWrite(this->hidden->hout,
&this->hidden->wavebuf[this->hidden->next_buffer],
sizeof(this->hidden->wavebuf[0]));
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
}
static int
WINMM_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
const int nextbuf = this->hidden->next_buffer;
MMRESULT result;
SDL_assert(buflen == this->spec.size);
/* Wait for an audio chunk to finish */
WaitForSingleObject(this->hidden->audio_sem, INFINITE);
/* Copy it to caller's buffer... */
SDL_memcpy(buffer, this->hidden->wavebuf[nextbuf].lpData, this->spec.size);
/* requeue the buffer that just finished. */
result = waveInAddBuffer(this->hidden->hin,
&this->hidden->wavebuf[nextbuf],
sizeof (this->hidden->wavebuf[nextbuf]));
if (result != MMSYSERR_NOERROR) {
return -1; /* uhoh! Disable the device. */
}
/* queue the next buffer in sequence, next time. */
this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
return this->spec.size;
}
static void
WINMM_FlushCapture(_THIS)
{
/* Wait for an audio chunk to finish */
if (WaitForSingleObject(this->hidden->audio_sem, 0) == WAIT_OBJECT_0) {
const int nextbuf = this->hidden->next_buffer;
/* requeue the buffer that just finished without reading from it. */
waveInAddBuffer(this->hidden->hin,
&this->hidden->wavebuf[nextbuf],
sizeof (this->hidden->wavebuf[nextbuf]));
this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
}
}
static void
WINMM_CloseDevice(_THIS)
{
int i;
if (this->hidden->hout) {
waveOutReset(this->hidden->hout);
/* Clean up mixing buffers */
for (i = 0; i < NUM_BUFFERS; ++i) {
if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
waveOutUnprepareHeader(this->hidden->hout,
&this->hidden->wavebuf[i],
sizeof (this->hidden->wavebuf[i]));
}
}
waveOutClose(this->hidden->hout);
}
if (this->hidden->hin) {
waveInReset(this->hidden->hin);
/* Clean up mixing buffers */
for (i = 0; i < NUM_BUFFERS; ++i) {
if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
waveInUnprepareHeader(this->hidden->hin,
&this->hidden->wavebuf[i],
sizeof (this->hidden->wavebuf[i]));
}
}
waveInClose(this->hidden->hin);
}
if (this->hidden->audio_sem) {
CloseHandle(this->hidden->audio_sem);
}
SDL_free(this->hidden->mixbuf);
SDL_free(this->hidden);
}
static SDL_bool
PrepWaveFormat(_THIS, UINT devId, WAVEFORMATEX *pfmt, const int iscapture)
{
SDL_zerop(pfmt);
if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
pfmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
} else {
pfmt->wFormatTag = WAVE_FORMAT_PCM;
}
pfmt->wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
pfmt->nChannels = this->spec.channels;
pfmt->nSamplesPerSec = this->spec.freq;
pfmt->nBlockAlign = pfmt->nChannels * (pfmt->wBitsPerSample / 8);
pfmt->nAvgBytesPerSec = pfmt->nSamplesPerSec * pfmt->nBlockAlign;
if (iscapture) {
return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
} else {
return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
}
}
static int
WINMM_OpenDevice(_THIS, const char *devname)
{
SDL_AudioFormat test_format;
SDL_bool iscapture = this->iscapture;
void *handle = this->handle;
MMRESULT result;
WAVEFORMATEX waveformat;
UINT devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */
UINT i;
if (handle != NULL) { /* specific device requested? */
/* -1 because we increment the original value to avoid NULL. */
const size_t val = ((size_t) handle) - 1;
devId = (UINT) val;
}
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
SDL_zerop(this->hidden);
/* Initialize the wavebuf structures for closing */
for (i = 0; i < NUM_BUFFERS; ++i)
this->hidden->wavebuf[i].dwUser = 0xFFFF;
if (this->spec.channels > 2)
this->spec.channels = 2; /* !!! FIXME: is this right? */
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
switch (test_format) {
case AUDIO_U8:
case AUDIO_S16:
case AUDIO_S32:
case AUDIO_F32:
this->spec.format = test_format;
if (PrepWaveFormat(this, devId, &waveformat, iscapture)) {
break;
}
continue;
default:
continue;
}
break;
}
if (!test_format) {
return SDL_SetError("%s: Unsupported audio format", "winmm");
}
/* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(&this->spec);
/* Open the audio device */
if (iscapture) {
result = waveInOpen(&this->hidden->hin, devId, &waveformat,
(DWORD_PTR) CaptureSound, (DWORD_PTR) this,
CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR) {
return SetMMerror("waveInOpen()", result);
}
} else {
result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
(DWORD_PTR) FillSound, (DWORD_PTR) this,
CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR) {
return SetMMerror("waveOutOpen()", result);
}
}
#ifdef SOUND_DEBUG
/* Check the sound device we retrieved */
{
if (iscapture) {
WAVEINCAPS caps;
result = waveInGetDevCaps((UINT) this->hidden->hout,
&caps, sizeof (caps));
if (result != MMSYSERR_NOERROR) {
return SetMMerror("waveInGetDevCaps()", result);
}
printf("Audio device: %s\n", caps.szPname);
} else {
WAVEOUTCAPS caps;
result = waveOutGetDevCaps((UINT) this->hidden->hout,
&caps, sizeof(caps));
if (result != MMSYSERR_NOERROR) {
return SetMMerror("waveOutGetDevCaps()", result);
}
printf("Audio device: %s\n", caps.szPname);
}
}
#endif
/* Create the audio buffer semaphore */
this->hidden->audio_sem = CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
if (this->hidden->audio_sem == NULL) {
return SDL_SetError("Couldn't create semaphore");
}
/* Create the sound buffers */
this->hidden->mixbuf =
(Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
SDL_zeroa(this->hidden->wavebuf);
for (i = 0; i < NUM_BUFFERS; ++i) {
this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
this->hidden->wavebuf[i].lpData =
(LPSTR) & this->hidden->mixbuf[i * this->spec.size];
if (iscapture) {
result = waveInPrepareHeader(this->hidden->hin,
&this->hidden->wavebuf[i],
sizeof(this->hidden->wavebuf[i]));
if (result != MMSYSERR_NOERROR) {
return SetMMerror("waveInPrepareHeader()", result);
}
result = waveInAddBuffer(this->hidden->hin,
&this->hidden->wavebuf[i],
sizeof(this->hidden->wavebuf[i]));
if (result != MMSYSERR_NOERROR) {
return SetMMerror("waveInAddBuffer()", result);
}
} else {
result = waveOutPrepareHeader(this->hidden->hout,
&this->hidden->wavebuf[i],
sizeof(this->hidden->wavebuf[i]));
if (result != MMSYSERR_NOERROR) {
return SetMMerror("waveOutPrepareHeader()", result);
}
}
}
if (iscapture) {
result = waveInStart(this->hidden->hin);
if (result != MMSYSERR_NOERROR) {
return SetMMerror("waveInStart()", result);
}
}
return 0; /* Ready to go! */
}
static SDL_bool
WINMM_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
impl->DetectDevices = WINMM_DetectDevices;
impl->OpenDevice = WINMM_OpenDevice;
impl->PlayDevice = WINMM_PlayDevice;
impl->WaitDevice = WINMM_WaitDevice;
impl->GetDeviceBuf = WINMM_GetDeviceBuf;
impl->CaptureFromDevice = WINMM_CaptureFromDevice;
impl->FlushCapture = WINMM_FlushCapture;
impl->CloseDevice = WINMM_CloseDevice;
impl->HasCaptureSupport = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
}
AudioBootStrap WINMM_bootstrap = {
"winmm", "Windows Waveform Audio", WINMM_Init, SDL_FALSE
};
#endif /* SDL_AUDIO_DRIVER_WINMM */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,45 +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.
*/
#include "../../SDL_internal.h"
#ifndef SDL_winmm_h_
#define SDL_winmm_h_
#include "../SDL_sysaudio.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
#define NUM_BUFFERS 2 /* -- Don't lower this! */
struct SDL_PrivateAudioData
{
HWAVEOUT hout;
HWAVEIN hin;
HANDLE audio_sem;
Uint8 *mixbuf; /* The raw allocated mixing buffer */
WAVEHDR wavebuf[NUM_BUFFERS]; /* Wave audio fragments */
int next_buffer;
};
#endif /* SDL_winmm_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -25,6 +25,7 @@
#include "SDL_hints.h"
#include "SDL_main.h"
#include "SDL_timer.h"
#include "SDL_version.h"
#ifdef __ANDROID__
@@ -63,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);
@@ -167,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) },
@@ -207,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 */
@@ -536,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)
{
@@ -1271,17 +1281,6 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeGenerateScancod
SDL_SendKeyboardUnicodeKey(chUnicode);
}
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);
}
JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetHint)(
JNIEnv *env, jclass cls,
jstring name)

View File

@@ -42,8 +42,7 @@ SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue)
&GDK_GlobalTaskQueue
);
if (FAILED(hr)) {
SDL_SetError("[GDK] Could not create global task queue");
return -1;
return SDL_SetError("[GDK] Could not create global task queue");
}
/* The initial call gets the non-duplicated handle so they can clean it up */
@@ -51,8 +50,7 @@ SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue)
} else {
/* Duplicate the global task queue handle into outTaskQueue */
if (FAILED(XTaskQueueDuplicateHandle(GDK_GlobalTaskQueue, outTaskQueue))) {
SDL_SetError("[GDK] Unable to acquire global task queue");
return -1;
return SDL_SetError("[GDK] Unable to acquire global task queue");
}
}

View File

@@ -22,6 +22,7 @@
#include "SDL_hints.h"
#include "SDL_dbus.h"
#include "SDL_atomic.h"
#include "SDL_sandbox.h"
#include "../../stdlib/SDL_vacopy.h"
#if SDL_USE_LIBDBUS
@@ -29,6 +30,7 @@
#include "SDL_loadso.h"
static const char *dbus_library = "libdbus-1.so.3";
static void *dbus_handle = NULL;
static char *inhibit_handle = NULL;
static unsigned int screensaver_cookie = 0;
static SDL_DBusContext dbus;
@@ -192,6 +194,8 @@ SDL_DBus_Quit(void)
#endif
SDL_zero(dbus);
UnloadDBUSLibrary();
SDL_free(inhibit_handle);
inhibit_handle = NULL;
}
SDL_DBusContext *
@@ -287,6 +291,32 @@ SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const ch
return retval;
}
static SDL_bool
SDL_DBus_CallWithBasicReply(DBusConnection *conn, DBusMessage *msg, const int expectedtype, void *result)
{
SDL_bool retval = SDL_FALSE;
DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
if (reply) {
DBusMessageIter iter, actual_iter;
dbus.message_iter_init(reply, &iter);
if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
dbus.message_iter_recurse(&iter, &actual_iter);
} else {
actual_iter = iter;
}
if (dbus.message_iter_get_arg_type(&actual_iter) == expectedtype) {
dbus.message_iter_get_basic(&actual_iter, result);
retval = SDL_TRUE;
}
dbus.message_unref(reply);
}
return retval;
}
SDL_bool
SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
{
@@ -318,19 +348,7 @@ SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const
DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get");
if (msg) {
if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
if (reply) {
DBusMessageIter iter, sub;
dbus.message_iter_init(reply, &iter);
if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
dbus.message_iter_recurse(&iter, &sub);
if (dbus.message_iter_get_arg_type(&sub) == expectedtype) {
dbus.message_iter_get_basic(&sub, result);
retval = SDL_TRUE;
}
}
dbus.message_unref(reply);
}
retval = SDL_DBus_CallWithBasicReply(conn, msg, expectedtype, result);
}
dbus.message_unref(msg);
}
@@ -349,20 +367,114 @@ SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface
void
SDL_DBus_ScreensaverTickle(void)
{
if (screensaver_cookie == 0) { /* no need to tickle if we're inhibiting. */
if (screensaver_cookie == 0 && inhibit_handle == NULL) { /* no need to tickle if we're inhibiting. */
/* org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. */
SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
}
}
static SDL_bool
SDL_DBus_AppendDictWithKeyValue(DBusMessageIter *iterInit, const char *key, const char *value)
{
DBusMessageIter iterDict, iterEntry, iterValue;
if (!dbus.message_iter_open_container(iterInit, DBUS_TYPE_ARRAY, "{sv}", &iterDict))
goto failed;
if (!dbus.message_iter_open_container(&iterDict, DBUS_TYPE_DICT_ENTRY, NULL, &iterEntry))
goto failed;
if (!dbus.message_iter_append_basic(&iterEntry, DBUS_TYPE_STRING, &key))
goto failed;
if (!dbus.message_iter_open_container(&iterEntry, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &iterValue))
goto failed;
if (!dbus.message_iter_append_basic(&iterValue, DBUS_TYPE_STRING, &value))
goto failed;
if (!dbus.message_iter_close_container(&iterEntry, &iterValue)
|| !dbus.message_iter_close_container(&iterDict, &iterEntry)
|| !dbus.message_iter_close_container(iterInit, &iterDict)) {
goto failed;
}
return SDL_TRUE;
failed:
/* message_iter_abandon_container_if_open() and message_iter_abandon_container() might be
* missing if libdbus is too old. Instead, we just return without cleaning up any eventual
* open container */
return SDL_FALSE;
}
SDL_bool
SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
{
if ( (inhibit && (screensaver_cookie != 0)) || (!inhibit && (screensaver_cookie == 0)) ) {
const char *default_inhibit_reason = "Playing a game";
if ( (inhibit && (screensaver_cookie != 0 || inhibit_handle != NULL))
|| (!inhibit && (screensaver_cookie == 0 && inhibit_handle == NULL)) ) {
return SDL_TRUE;
}
if (!dbus.session_conn) {
/* We either lost connection to the session bus or were not able to
* load the D-Bus library at all. */
return SDL_FALSE;
}
if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
const char *bus_name = "org.freedesktop.portal.Desktop";
const char *path = "/org/freedesktop/portal/desktop";
const char *interface = "org.freedesktop.portal.Inhibit";
const char *window = ""; /* As a future improvement we could gather the X11 XID or Wayland surface identifier */
static const unsigned int INHIBIT_IDLE = 8; /* Taken from the portal API reference */
DBusMessageIter iterInit;
if (inhibit) {
DBusMessage *msg;
SDL_bool retval = SDL_FALSE;
const char *key = "reason";
const char *reply = NULL;
const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME);
if (!reason || !reason[0]) {
reason = default_inhibit_reason;
}
msg = dbus.message_new_method_call(bus_name, path, interface, "Inhibit");
if (!msg) {
return SDL_FALSE;
}
if (!dbus.message_append_args(msg, DBUS_TYPE_STRING, &window, DBUS_TYPE_UINT32, &INHIBIT_IDLE, DBUS_TYPE_INVALID)) {
dbus.message_unref(msg);
return SDL_FALSE;
}
dbus.message_iter_init_append(msg, &iterInit);
if (!SDL_DBus_AppendDictWithKeyValue(&iterInit, key, reason)) {
dbus.message_unref(msg);
return SDL_FALSE;
}
if (SDL_DBus_CallWithBasicReply(dbus.session_conn, msg, DBUS_TYPE_OBJECT_PATH, &reply)) {
inhibit_handle = SDL_strdup(reply);
retval = SDL_TRUE;
}
dbus.message_unref(msg);
return retval;
} else {
if (!SDL_DBus_CallVoidMethod(bus_name, inhibit_handle, "org.freedesktop.portal.Request", "Close", DBUS_TYPE_INVALID)) {
return SDL_FALSE;
}
SDL_free(inhibit_handle);
inhibit_handle = NULL;
}
} else {
const char *node = "org.freedesktop.ScreenSaver";
const char *bus_name = "org.freedesktop.ScreenSaver";
const char *path = "/org/freedesktop/ScreenSaver";
const char *interface = "org.freedesktop.ScreenSaver";
@@ -373,17 +485,17 @@ SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
app = "My SDL application";
}
if (!reason || !reason[0]) {
reason = "Playing a game";
reason = default_inhibit_reason;
}
if (!SDL_DBus_CallMethod(node, path, interface, "Inhibit",
if (!SDL_DBus_CallMethod(bus_name, path, interface, "Inhibit",
DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID,
DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
return SDL_FALSE;
}
return (screensaver_cookie != 0) ? SDL_TRUE : SDL_FALSE;
} else {
if (!SDL_DBus_CallVoidMethod(node, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
if (!SDL_DBus_CallVoidMethod(bus_name, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {
return SDL_FALSE;
}
screensaver_cookie = 0;

View File

@@ -42,7 +42,7 @@
#include "SDL_endian.h"
#include "SDL_scancode.h"
#include "../../events/SDL_events_c.h"
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
#include "../../events/SDL_scancode_tables_c.h"
#include "../../core/linux/SDL_evdev_capabilities.h"
#include "../../core/linux/SDL_udev.h"
@@ -509,23 +509,21 @@ SDL_EVDEV_Poll(void)
static SDL_Scancode
SDL_EVDEV_translate_keycode(int keycode)
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
SDL_Scancode scancode = SDL_GetScancodeFromTable(SDL_SCANCODE_TABLE_LINUX, keycode);
if (keycode < SDL_arraysize(linux_scancode_table)) {
scancode = linux_scancode_table[keycode];
if (scancode == SDL_SCANCODE_UNKNOWN) {
/* BTN_TOUCH is handled elsewhere, but we might still end up here if
you get an unexpected BTN_TOUCH from something SDL believes is not
a touch device. In this case, we'd rather not get a misleading
SDL_Log message about an unknown key. */
if (keycode != BTN_TOUCH) {
SDL_Log("The key you just pressed is not recognized by SDL. To help "
"get this fixed, please report this to the SDL forums/mailing list "
"<https://discourse.libsdl.org/> EVDEV KeyCode %d", keycode);
}
#ifdef DEBUG_SCANCODES
if (scancode == SDL_SCANCODE_UNKNOWN) {
/* BTN_TOUCH is handled elsewhere, but we might still end up here if
you get an unexpected BTN_TOUCH from something SDL believes is not
a touch device. In this case, we'd rather not get a misleading
SDL_Log message about an unknown key. */
if (keycode != BTN_TOUCH) {
SDL_Log("The key you just pressed is not recognized by SDL. To help "
"get this fixed, please report this to the SDL forums/mailing list "
"<https://discourse.libsdl.org/> EVDEV KeyCode %d", keycode);
}
}
#endif /* DEBUG_SCANCODES */
return scancode;
}

View File

@@ -19,10 +19,12 @@
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_evdev_capabilities.h"
#if HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX)
#if HAVE_LINUX_INPUT_H
/* missing defines in older Linux kernel headers */
#ifndef BTN_TRIGGER_HAPPY
@@ -142,4 +144,6 @@ SDL_EVDEV_GuessDeviceClass(unsigned long bitmask_ev[NBITS(EV_MAX)],
return devclass;
}
#endif
#endif /* HAVE_LINUX_INPUT_H */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -19,13 +19,12 @@
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_evdev_capabilities_h_
#define SDL_evdev_capabilities_h_
#if HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX)
#if HAVE_LINUX_INPUT_H
#include <linux/input.h>
@@ -53,7 +52,7 @@ extern int SDL_EVDEV_GuessDeviceClass(unsigned long bitmask_ev[NBITS(EV_MAX)],
unsigned long bitmask_key[NBITS(KEY_MAX)],
unsigned long bitmask_rel[NBITS(REL_MAX)]);
#endif /* HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX) */
#endif /* HAVE_LINUX_INPUT_H */
#endif /* SDL_evdev_capabilities_h_ */

View File

@@ -37,17 +37,27 @@
#include <unistd.h>
#include <fcntl.h>
static const char IBUS_SERVICE[] = "org.freedesktop.IBus";
static const char IBUS_PATH[] = "/org/freedesktop/IBus";
static const char IBUS_SERVICE[] = "org.freedesktop.IBus";
static const char IBUS_INTERFACE[] = "org.freedesktop.IBus";
static const char IBUS_INPUT_INTERFACE[] = "org.freedesktop.IBus.InputContext";
static const char IBUS_PORTAL_SERVICE[] = "org.freedesktop.portal.IBus";
static const char IBUS_PORTAL_INTERFACE[] = "org.freedesktop.IBus.Portal";
static const char IBUS_PORTAL_INPUT_INTERFACE[] = "org.freedesktop.IBus.InputContext";
static const char *ibus_service = NULL;
static const char *ibus_interface = NULL;
static const char *ibus_input_interface = NULL;
static char *input_ctx_path = NULL;
static SDL_Rect ibus_cursor_rect = { 0, 0, 0, 0 };
static DBusConnection *ibus_conn = NULL;
static SDL_bool ibus_is_portal_interface = SDL_FALSE;
static char *ibus_addr_file = NULL;
static int inotify_fd = -1, inotify_wd = -1;
static Uint32
IBus_ModState(void)
{
@@ -202,7 +212,7 @@ IBus_MessageHandler(DBusConnection *conn, DBusMessage *msg, void *user_data)
{
SDL_DBusContext *dbus = (SDL_DBusContext *)user_data;
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "CommitText")) {
if (dbus->message_is_signal(msg, ibus_input_interface, "CommitText")) {
DBusMessageIter iter;
const char *text;
@@ -224,7 +234,7 @@ IBus_MessageHandler(DBusConnection *conn, DBusMessage *msg, void *user_data)
return DBUS_HANDLER_RESULT_HANDLED;
}
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "UpdatePreeditText")) {
if (dbus->message_is_signal(msg, ibus_input_interface, "UpdatePreeditText")) {
DBusMessageIter iter;
const char *text;
@@ -273,7 +283,7 @@ IBus_MessageHandler(DBusConnection *conn, DBusMessage *msg, void *user_data)
return DBUS_HANDLER_RESULT_HANDLED;
}
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "HidePreeditText")) {
if (dbus->message_is_signal(msg, ibus_input_interface, "HidePreeditText")) {
SDL_SendEditingText("", 0, 0);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -415,7 +425,7 @@ IBus_SetCapabilities(void *data, const char *name, const char *old_val,
caps |= IBUS_CAP_PREEDIT_TEXT;
}
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities",
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, "SetCapabilities",
DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID);
}
}
@@ -424,40 +434,60 @@ IBus_SetCapabilities(void *data, const char *name, const char *old_val,
static SDL_bool
IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
{
const char *client_name = "SDL2_Application";
const char *client_name = "SDL3_Application";
const char *path = NULL;
SDL_bool result = SDL_FALSE;
DBusObjectPathVTable ibus_vtable;
SDL_zero(ibus_vtable);
ibus_vtable.message_function = &IBus_MessageHandler;
ibus_conn = dbus->connection_open_private(addr, NULL);
/* try the portal interface first. Modern systems have this in general,
and sandbox things like FlakPak and Snaps, etc, require it. */
if (!ibus_conn) {
return SDL_FALSE;
ibus_is_portal_interface = SDL_TRUE;
ibus_service = IBUS_PORTAL_SERVICE;
ibus_interface = IBUS_PORTAL_INTERFACE;
ibus_input_interface = IBUS_PORTAL_INPUT_INTERFACE;
ibus_conn = dbus->session_conn;
result = SDL_DBus_CallMethodOnConnection(ibus_conn, ibus_service, IBUS_PATH, ibus_interface, "CreateInputContext",
DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID,
DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
if (!result) {
ibus_is_portal_interface = SDL_FALSE;
ibus_service = IBUS_SERVICE;
ibus_interface = IBUS_INTERFACE;
ibus_input_interface = IBUS_INPUT_INTERFACE;
ibus_conn = dbus->connection_open_private(addr, NULL);
if (!ibus_conn) {
return SDL_FALSE; /* oh well. */
}
dbus->connection_flush(ibus_conn);
if (!dbus->bus_register(ibus_conn, NULL)) {
ibus_conn = NULL;
return SDL_FALSE;
}
dbus->connection_flush(ibus_conn);
result = SDL_DBus_CallMethodOnConnection(ibus_conn, ibus_service, IBUS_PATH, ibus_interface, "CreateInputContext",
DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID,
DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
}
dbus->connection_flush(ibus_conn);
if (!dbus->bus_register(ibus_conn, NULL)) {
ibus_conn = NULL;
return SDL_FALSE;
}
dbus->connection_flush(ibus_conn);
if (SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext",
DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID,
DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
if (result) {
char matchstr[128];
SDL_snprintf(matchstr, sizeof (matchstr), "type='signal',interface='%s'", ibus_input_interface);
SDL_free(input_ctx_path);
input_ctx_path = SDL_strdup(path);
SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, IBus_SetCapabilities, NULL);
dbus->bus_add_match(ibus_conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
dbus->bus_add_match(ibus_conn, matchstr, NULL);
dbus->connection_try_register_object_path(ibus_conn, input_ctx_path, &ibus_vtable, dbus, NULL);
dbus->connection_flush(ibus_conn);
result = SDL_TRUE;
}
SDL_IBus_SetFocus(SDL_GetKeyboardFocus() != NULL);
@@ -549,9 +579,19 @@ SDL_IBus_Init(void)
inotify_wd = inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY);
SDL_free(addr_file);
if (addr) {
result = IBus_SetupConnection(dbus, addr);
SDL_free(addr);
result = IBus_SetupConnection(dbus, addr);
SDL_free(addr);
/* don't use the addr_file if using the portal interface. */
if (result && ibus_is_portal_interface) {
if (inotify_fd > 0) {
if (inotify_wd > 0) {
inotify_rm_watch(inotify_fd, inotify_wd);
inotify_wd = -1;
}
close(inotify_fd);
inotify_fd = -1;
}
}
}
@@ -575,16 +615,25 @@ SDL_IBus_Quit(void)
dbus = SDL_DBus_GetContext();
if (dbus && ibus_conn) {
/* if using portal, ibus_conn == session_conn; don't release it here. */
if (dbus && ibus_conn && !ibus_is_portal_interface) {
dbus->connection_close(ibus_conn);
dbus->connection_unref(ibus_conn);
}
ibus_conn = NULL;
ibus_service = NULL;
ibus_interface = NULL;
ibus_input_interface = NULL;
ibus_is_portal_interface = SDL_FALSE;
if (inotify_fd > 0 && inotify_wd > 0) {
inotify_rm_watch(inotify_fd, inotify_wd);
inotify_wd = -1;
}
/* !!! FIXME: should we close(inotify_fd) here? */
SDL_DelHintCallback(SDL_HINT_IME_INTERNAL_EDITING, IBus_SetCapabilities, NULL);
SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect));
@@ -596,7 +645,7 @@ IBus_SimpleMessage(const char *method)
SDL_DBusContext *dbus = SDL_DBus_GetContext();
if ((input_ctx_path != NULL) && (IBus_CheckConnection(dbus))) {
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, method, DBUS_TYPE_INVALID);
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, method, DBUS_TYPE_INVALID);
}
}
@@ -626,7 +675,7 @@ SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
if (state == SDL_RELEASED) {
mods |= (1 << 30); // IBUS_RELEASE_MASK
}
if (!SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
if (!SDL_DBus_CallMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, "ProcessKeyEvent",
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &ibus_keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
result = 0;
@@ -681,7 +730,7 @@ SDL_IBus_UpdateTextRect(const SDL_Rect *rect)
dbus = SDL_DBus_GetContext();
if (IBus_CheckConnection(dbus)) {
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "SetCursorLocation",
SDL_DBus_CallVoidMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, "SetCursorLocation",
DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &ibus_cursor_rect.w, DBUS_TYPE_INT32, &ibus_cursor_rect.h, DBUS_TYPE_INVALID);
}
}

View File

@@ -40,7 +40,7 @@ extern void SDL_IBus_Reset(void);
/* Sends a keypress event to IBus, returns SDL_TRUE if IBus used this event to
update its candidate list or change input methods. PumpEvents should be
called some time after this, to recieve the TextInput / TextEditing event back. */
called some time after this, to receive the TextInput / TextEditing event back. */
extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
/* Update the position of IBus' candidate list. If rect is NULL then this will

View File

@@ -18,6 +18,7 @@
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_ime.h"
#include "SDL_ibus.h"

View File

@@ -1,6 +1,7 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 2022 Collabora Ltd.
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,29 +21,29 @@
*/
#include "../../SDL_internal.h"
#ifndef SDL_paudio_h_
#define SDL_paudio_h_
#include "SDL_sandbox.h"
#include "../SDL_sysaudio.h"
#include <unistd.h>
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData
SDL_Sandbox SDL_DetectSandbox(void)
{
/* The file descriptor for the audio device */
int audio_fd;
if (access("/.flatpak-info", F_OK) == 0) {
return SDL_SANDBOX_FLATPAK;
}
/* Raw mixing buffer */
Uint8 *mixbuf;
int mixlen;
/* For Snap, we check multiple variables because they might be set for
* unrelated reasons. This is the same thing WebKitGTK does. */
if (SDL_getenv("SNAP") != NULL
&& SDL_getenv("SNAP_NAME") != NULL
&& SDL_getenv("SNAP_REVISION") != NULL) {
return SDL_SANDBOX_SNAP;
}
/* Support for audio timing using a timer, in addition to SDL_IOReady() */
float frame_ticks;
float next_frame;
};
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
if (access("/run/host/container-runtime", F_OK) == 0) {
return SDL_SANDBOX_UNKNOWN_CONTAINER;
}
#endif /* SDL_paudio_h_ */
return SDL_SANDBOX_NONE;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,6 +1,7 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 2022 Collabora Ltd.
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,26 +19,21 @@
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_error.h"
#include "SDL_filesystem.h"
#ifdef SDL_FILESYSTEM_NACL
#ifndef SDL_SANDBOX_H
#define SDL_SANDBOX_H
char *
SDL_GetBasePath(void)
typedef enum
{
SDL_Unsupported();
return NULL;
}
SDL_SANDBOX_NONE = 0,
SDL_SANDBOX_UNKNOWN_CONTAINER,
SDL_SANDBOX_FLATPAK,
SDL_SANDBOX_SNAP,
} SDL_Sandbox;
char *
SDL_GetPrefPath(const char *org, const char *app)
{
SDL_Unsupported();
return NULL;
}
/* Return the sandbox type currently in use, if any */
SDL_Sandbox SDL_DetectSandbox(void);
#endif /* SDL_FILESYSTEM_NACL */
#endif /* SDL_SANDBOX_H */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -18,6 +18,7 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
/*
* To list the properties of a device, try something like:
@@ -544,6 +545,10 @@ SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
SDL_UDEV_CallbackList *item;
SDL_UDEV_CallbackList *prev = NULL;
if (_this == NULL) {
return;
}
for (item = _this->first; item != NULL; item = item->next) {
/* found it, remove it. */
if (item->callback == cb) {

View File

@@ -24,7 +24,7 @@
#ifndef SDL_udev_h_
#define SDL_udev_h_
#if HAVE_LIBUDEV_H
#if HAVE_LIBUDEV_H && HAVE_LINUX_INPUT_H
#ifndef SDL_USE_LIBUDEV
#define SDL_USE_LIBUDEV 1
@@ -108,7 +108,7 @@ extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void);
extern void SDL_UDEV_ReleaseUdevSyms(void);
#endif /* HAVE_LIBUDEV_H */
#endif /* HAVE_LIBUDEV_H && HAVE_LINUX_INPUT_H */
#endif /* SDL_udev_h_ */

View File

@@ -1,57 +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 SDL_os2_h_
#define SDL_os2_h_
#include "SDL_log.h"
#include "SDL_stdinc.h"
#ifdef OS2DEBUG
#if (OS2DEBUG-0 >= 2)
# define debug_os2(s,...) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, \
__func__ "(): " ##s, ##__VA_ARGS__)
#else
# define debug_os2(s,...) printf(__func__ "(): " ##s "\n", ##__VA_ARGS__)
#endif
#else /* no debug */
# define debug_os2(s,...) do {} while (0)
#endif /* OS2DEBUG */
#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H)
#define OS2_SysToUTF8(S) SDL_iconv_string("UTF-8", "", (char *)(S), SDL_strlen(S)+1)
#define OS2_UTF8ToSys(S) SDL_iconv_string("", "UTF-8", (char *)(S), SDL_strlen(S)+1)
#define libiconv_clean() do {} while(0)
#else
/* StrUTF8New() - geniconv/sys2utf8.c */
#include "geniconv/geniconv.h"
#define OS2_SysToUTF8(S) StrUTF8New(1, (S), SDL_strlen((S)) + 1)
#define OS2_UTF8ToSys(S) StrUTF8New(0, (char *)(S), SDL_strlen((S)) + 1)
#endif
/* SDL_OS2Quit() will be called from SDL_QuitSubSystem() */
void SDL_OS2Quit(void);
#endif /* SDL_os2_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,161 +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.
*/
/*
Universal iconv implementation for OS/2.
Andrey Vasilkin, 2016.
*/
#define INCL_DOSMODULEMGR /* Module Manager */
#define INCL_DOSERRORS /* Error values */
#include <os2.h>
#include "geniconv.h"
/*#define DEBUG*/
#ifdef DEBUG
# include <stdio.h>
# define iconv_debug(s,...) printf(__func__"(): "##s"\n" ,##__VA_ARGS__)
#else
# define iconv_debug(s,...) do {} while (0)
#endif
/* Exports from os2iconv.c */
extern iconv_t _System os2_iconv_open (const char* tocode, const char* fromcode);
extern size_t _System os2_iconv (iconv_t cd,
char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
extern int _System os2_iconv_close (iconv_t cd);
/* Functions pointers */
typedef iconv_t (_System *FNICONV_OPEN)(const char*, const char*);
typedef size_t (_System *FNICONV) (iconv_t, char **, size_t *, char **, size_t *);
typedef int (_System *FNICONV_CLOSE)(iconv_t);
static HMODULE hmIconv = NULLHANDLE;
static FNICONV_OPEN fn_iconv_open = os2_iconv_open;
static FNICONV fn_iconv = os2_iconv;
static FNICONV_CLOSE fn_iconv_close = os2_iconv_close;
static int geniconv_init = 0;
static BOOL _loadDLL(const char *dllname,
const char *sym_iconvopen,
const char *sym_iconv,
const char *sym_iconvclose)
{
ULONG rc;
char error[256];
rc = DosLoadModule(error, sizeof(error), dllname, &hmIconv);
if (rc != NO_ERROR) {
iconv_debug("DLL %s not loaded: %s", dllname, error);
return FALSE;
}
rc = DosQueryProcAddr(hmIconv, 0, sym_iconvopen, (PFN *)&fn_iconv_open);
if (rc != NO_ERROR) {
iconv_debug("Error: cannot find entry %s in %s", sym_iconvopen, dllname);
goto fail;
}
rc = DosQueryProcAddr(hmIconv, 0, sym_iconv, (PFN *)&fn_iconv);
if (rc != NO_ERROR) {
iconv_debug("Error: cannot find entry %s in %s", sym_iconv, dllname);
goto fail;
}
rc = DosQueryProcAddr(hmIconv, 0, sym_iconvclose, (PFN *)&fn_iconv_close);
if (rc != NO_ERROR) {
iconv_debug("Error: cannot find entry %s in %s", sym_iconvclose, dllname);
goto fail;
}
iconv_debug("DLL %s used", dllname);
return TRUE;
fail:
DosFreeModule(hmIconv);
hmIconv = NULLHANDLE;
return FALSE;
}
static void _init(void)
{
if (geniconv_init) {
return; /* Already initialized */
}
geniconv_init = 1;
/* Try to load kiconv.dll, iconv2.dll or iconv.dll */
if (!_loadDLL("KICONV", "_libiconv_open", "_libiconv", "_libiconv_close") &&
!_loadDLL("ICONV2", "_libiconv_open", "_libiconv", "_libiconv_close") &&
!_loadDLL("ICONV", "_iconv_open", "_iconv", "_iconv_close") ) {
/* No DLL was loaded - use OS/2 conversion objects API */
iconv_debug("Uni*() API used");
fn_iconv_open = os2_iconv_open;
fn_iconv = os2_iconv;
fn_iconv_close = os2_iconv_close;
}
}
/* Public routines.
* ----------------
*/
/* function to unload the used iconv dynamic library */
void libiconv_clean(void)
{
geniconv_init = 0;
/* reset the function pointers. */
fn_iconv_open = os2_iconv_open;
fn_iconv = os2_iconv;
fn_iconv_close = os2_iconv_close;
if (hmIconv != NULLHANDLE) {
DosFreeModule(hmIconv);
hmIconv = NULLHANDLE;
}
}
iconv_t libiconv_open(const char* tocode, const char* fromcode)
{
_init();
return fn_iconv_open(tocode, fromcode);
}
size_t libiconv(iconv_t cd, char* * inbuf, size_t *inbytesleft,
char* * outbuf, size_t *outbytesleft)
{
return fn_iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft);
}
int libiconv_close(iconv_t cd)
{
return fn_iconv_close(cd);
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,85 +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.
*/
/*
Universal iconv implementation for OS/2.
Andrey Vasilkin, 2016.
*/
#ifndef GENICONV_H
#define GENICONV_H
#include "iconv.h"
#ifdef iconv_open
#undef iconv_open
#endif
#define iconv_open libiconv_open
#ifdef iconv
#undef iconv
#endif
#define iconv libiconv
#ifdef iconv_close
#undef iconv_close
#endif
#define iconv_close libiconv_close
#define iconv_clean libiconv_clean
/* Non-standard function for iconv to unload the used dynamic library */
void libiconv_clean(void);
iconv_t libiconv_open (const char *tocode, const char *fromcode);
int libiconv_close(iconv_t cd);
size_t libiconv (iconv_t cd, char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
/* System codepage <-> UTF-8
*
* StrUTF8()
* Converts string from system cp to UTF-8 (to_utf8 is not 0) or from UTF-8 to
* the system cp (to_utf8 is 0). Converted ASCIIZ string will be placed at the
* buffer dst, up to c_dst - 1 (for sys->utf8) or 2 (for utf8->sys) bytes.
* Returns the number of bytes written into dst, not counting the terminating
* 0 byte(s) or -1 on error.
*/
int StrUTF8(int to_utf8, char *dst, int c_dst, char *src, int c_src);
/* StrUTF8New()
* Converts string from system cp to UTF-8 (to_utf8 is not 0) or from UTF-8
* to the system cp (to_utf8 is 0). Memory for the new string is obtained by
* using libc malloc().
* Returns converted string, terminating two bytes 0 is appended to the result.
* Returns null on error.
*/
char *StrUTF8New(int to_utf8, char *str, int c_str);
/* StrUTF8Free()
* Deallocates the memory block allocated by StrUTF8New() (just libc free()).
*/
void StrUTF8Free(char *str);
#endif /* GENICONV_H */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,21 +0,0 @@
#ifndef ICONV_H_ /* minimal iconv.h header based on public knowledge */
#define ICONV_H_
#include <stddef.h> /* size_t */
#include <errno.h>
typedef void *iconv_t;
#ifdef __cplusplus
extern "C" {
#endif
extern iconv_t iconv_open(const char *, const char *);
extern size_t iconv(iconv_t, char **, size_t *, char **, size_t *);
extern int iconv_close(iconv_t);
#ifdef __cplusplus
}
#endif
#endif /* ICONV_H_ */

View File

@@ -1,37 +0,0 @@
#
# Universal iconv implementation for OS/2.
#
# OpenWatcom makefile to build a library that uses kiconv.dll / iconv2.dll /
# iconv.dll or OS/2 Uni*() API.
#
# Andrey Vasilkin, 2016.
#
LIBFILE = geniconv.lib
all: $(LIBFILE) test.exe .symbolic
CFLAGS = -I$(%WATCOM)/h/os2 -I$(%WATCOM)/h -I. -bt=os2 -q -d0 -w2 -DGENICONV_STANDALONE=1
SRCS = geniconv.c os2cp.c os2iconv.c
SRCS+= sys2utf8.c
OBJS = $(SRCS:.c=.obj)
LIBS = libuls.lib libconv.lib $(LIBFILE)
test.exe: $(LIBFILE) test.obj
wlink op quiet system os2v2 file test.obj lib {$(LIBS)} name $*
$(LIBFILE): $(OBJS)
@if exist $@ rm $@
@for %f in ($(OBJS)) do wlib -q -b $* +%f
.c.obj:
wcc386 $(CFLAGS) -fo=$^@ $<
clean: .SYMBOLIC
@if exist *.obj rm *.obj
@if exist *.err rm *.err
@if exist $(LIBFILE) rm $(LIBFILE)
@if exist test.exe rm test.exe

View File

@@ -1,416 +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.
*/
#define INCL_DOSNLS
#define INCL_DOSERRORS
#include <os2.h>
#include "os2cp.h"
#ifndef GENICONV_STANDALONE
#include "../../../SDL_internal.h"
#else
#include <string.h>
#include <ctype.h>
#define SDL_isspace isspace
#define SDL_strchr strchr
#define SDL_memcpy memcpy
#define SDL_strupr strupr
#define SDL_strcmp strcmp
#endif
typedef struct _CP2NAME {
ULONG ulCode;
PSZ pszName;
} CP2NAME;
typedef struct _NAME2CP {
PSZ pszName;
ULONG ulCode;
} NAME2CP;
static CP2NAME aCP2Name[] = {
{367, "ANSI_X3.4-1968"},
{813, "ECMA-118"},
{819, "CP819"},
{850, "850"},
{862, "862"},
{866, "866"},
{874, "ISO-IR-166"},
{878, "KOI8-R"},
{896, "JISX0201-1976"},
{901, "ISO-8859-13"},
{912, "ISO-8859-2"},
{913, "ISO-8859-3"},
{914, "ISO-8859-4"},
{915, "CYRILLIC"},
{920, "ISO-8859-9"},
{923, "ISO-8859-15"},
{943, "MS_KANJI"},
{954, "EUC-JP"},
{964, "EUC-TW"},
{970, "EUC-KR"},
{1051, "HP-ROMAN8"},
{1089, "ARABIC"},
{1129, "VISCII"},
{1168, "KOI8-U"},
{1200, "ISO-10646-UCS-2"},
{1202, "UTF-16LE"},
{1204, "UCS-2BE"},
{1208, "UTF-8"},
{1232, "UTF-32BE"},
{1234, "UTF-32LE"},
{1236, "ISO-10646-UCS-4"},
{1250, "CP1250"},
{1251, "CP1251"},
{1252, "CP1252"},
{1253, "CP1253"},
{1254, "CP1254"},
{1255, "CP1255"},
{1256, "CP1256"},
{1257, "CP1257"},
{1275, "MAC"},
{1383, "CN-GB"},
{1386, "GBK"},
{1392, "GB18030"},
{62210, "HEBREW"}
};
static NAME2CP aName2CP[] = {
{"850", 850},
{"862", 862},
{"866", 866},
{"ANSI_X3.4-1968", 367},
{"ANSI_X3.4-1986", 367},
{"ARABIC", 1089},
{"ASCII", 367},
{"ASMO-708", 1089},
{"CN-GB", 1383},
{"CP1250", 1250},
{"CP1251", 1251},
{"CP1252", 1252},
{"CP1253", 1253},
{"CP1254", 1254},
{"CP1255", 1255},
{"CP1256", 1256},
{"CP1257", 1257},
{"CP367", 367},
{"CP819", 819},
{"CP850", 850},
{"CP862", 862},
{"CP866", 866},
{"CP936", 1386},
{"CSASCII", 367},
{"CSEUCKR", 970},
{"CSEUCPKDFMTJAPANESE", 954},
{"CSEUCTW", 964},
{"CSGB2312", 1383},
{"CSHALFWIDTHKATAKANA", 896},
{"CSHPROMAN8", 1051},
{"CSIBM866", 866},
{"CSISOLATIN1", 819},
{"CSISOLATIN2", 912},
{"CSISOLATIN3", 913},
{"CSISOLATIN4", 914},
{"CSISOLATIN5", 920},
{"CSISOLATINARABIC", 1089},
{"CSISOLATINCYRILLIC", 915},
{"CSISOLATINGREEK", 813},
{"CSISOLATINHEBREW", 62210},
{"CSKOI8R", 878},
{"CSKSC56011987", 970},
{"CSMACINTOSH", 1275},
{"CSPC850MULTILINGUAL", 850},
{"CSPC862LATINHEBREW", 862},
{"CSSHIFTJIS", 943},
{"CSUCS4", 1236},
{"CSUNICODE", 1200},
{"CSUNICODE11", 1204},
{"CSVISCII", 1129},
{"CYRILLIC", 915},
{"ECMA-114", 1089},
{"ECMA-118", 813},
{"ELOT_928", 813},
{"EUC-CN", 1383},
{"EUC-JP", 954},
{"EUC-KR", 970},
{"EUC-TW", 964},
{"EUCCN", 1383},
{"EUCJP", 954},
{"EUCKR", 970},
{"EUCTW", 964},
{"EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE", 954},
{"GB18030", 1392},
{"GB2312", 1383},
{"GBK", 1386},
{"GREEK", 813},
{"GREEK8", 813},
{"HEBREW", 62210},
{"HP-ROMAN8", 1051},
{"IBM367", 367},
{"IBM819", 819},
{"IBM850", 850},
{"IBM862", 862},
{"IBM866", 866},
{"ISO-10646-UCS-2", 1200},
{"ISO-10646-UCS-4", 1236},
{"ISO-8859-1", 819},
{"ISO-8859-13", 901},
{"ISO-8859-15", 923},
{"ISO-8859-2", 912},
{"ISO-8859-3", 913},
{"ISO-8859-4", 914},
{"ISO-8859-5", 915},
{"ISO-8859-6", 1089},
{"ISO-8859-7", 813},
{"ISO-8859-8", 62210},
{"ISO-8859-9", 920},
{"ISO-IR-100", 819},
{"ISO-IR-101", 912},
{"ISO-IR-109", 913},
{"ISO-IR-110", 914},
{"ISO-IR-126", 813},
{"ISO-IR-127", 1089},
{"ISO-IR-138", 62210},
{"ISO-IR-144", 915},
{"ISO-IR-148", 920},
{"ISO-IR-149", 970},
{"ISO-IR-166", 874},
{"ISO-IR-179", 901},
{"ISO-IR-203", 923},
{"ISO-IR-6", 367},
{"ISO646-US", 367},
{"ISO8859-1", 819},
{"ISO8859-13", 901},
{"ISO8859-15", 923},
{"ISO8859-2", 912},
{"ISO8859-3", 913},
{"ISO8859-4", 914},
{"ISO8859-5", 915},
{"ISO8859-6", 1089},
{"ISO8859-7", 813},
{"ISO8859-8", 62210},
{"ISO8859-9", 920},
{"ISO_646.IRV:1991", 367},
{"ISO_8859-1", 819},
{"ISO_8859-13", 901},
{"ISO_8859-15", 923},
{"ISO_8859-15:1998", 923},
{"ISO_8859-1:1987", 819},
{"ISO_8859-2", 912},
{"ISO_8859-2:1987", 912},
{"ISO_8859-3", 913},
{"ISO_8859-3:1988", 913},
{"ISO_8859-4", 914},
{"ISO_8859-4:1988", 914},
{"ISO_8859-5", 915},
{"ISO_8859-5:1988", 915},
{"ISO_8859-6", 1089},
{"ISO_8859-6:1987", 1089},
{"ISO_8859-7", 813},
{"ISO_8859-7:1987", 813},
{"ISO_8859-7:2003", 813},
{"ISO_8859-8", 62210},
{"ISO_8859-8:1988", 62210},
{"ISO_8859-9", 920},
{"ISO_8859-9:1989", 920},
{"JISX0201-1976", 896},
{"JIS_X0201", 896},
{"KOI8-R", 878},
{"KOI8-U", 1168},
{"KOREAN", 970},
{"KSC_5601", 970},
{"KS_C_5601-1987", 970},
{"KS_C_5601-1989", 970},
{"L1", 819},
{"L2", 912},
{"L3", 913},
{"L4", 914},
{"L5", 920},
{"L7", 901},
{"LATIN-9", 923},
{"LATIN1", 819},
{"LATIN2", 912},
{"LATIN3", 913},
{"LATIN4", 914},
{"LATIN5", 920},
{"LATIN7", 901},
{"MAC", 1275},
{"MACINTOSH", 1275},
{"MACROMAN", 1275},
{"MS-ANSI", 1252},
{"MS-ARAB", 1256},
{"MS-CYRL", 1251},
{"MS-EE", 1250},
{"MS-GREEK", 1253},
{"MS-HEBR", 1255},
{"MS-TURK", 1254},
{"MS936", 1386},
{"MS_KANJI", 943},
{"R8", 1051},
{"ROMAN8", 1051},
{"SHIFT-JIS", 943},
{"SHIFT_JIS", 943},
{"SJIS", 943},
{"TIS-620", 874},
{"TIS620", 874},
{"TIS620-0", 874},
{"TIS620.2529-1", 874},
{"TIS620.2533-0", 874},
{"TIS620.2533-1", 874},
{"UCS-2", 1200},
{"UCS-2BE", 1204},
{"UCS-4", 1236},
{"UNICODE-1-1", 1204},
{"UNICODEBIG", 1204},
{"US", 367},
{"US-ASCII", 367},
{"UTF-16", 1204},
{"UTF-16BE", 1200},
{"UTF-16LE", 1202},
{"UTF-32", 1236},
{"UTF-32BE", 1232},
{"UTF-32LE", 1234},
{"UTF-8", 1208},
{"VISCII", 1129},
{"VISCII1.1-1", 1129},
{"WINBALTRIM", 1257},
{"WINDOWS-1250", 1250},
{"WINDOWS-1251", 1251},
{"WINDOWS-1252", 1252},
{"WINDOWS-1253", 1253},
{"WINDOWS-1254", 1254},
{"WINDOWS-1255", 1255},
{"WINDOWS-1256", 1256},
{"WINDOWS-1257", 1257},
{"WINDOWS-936", 1386},
{"X0201", 896}
};
char *os2cpToName(unsigned long cp)
{
ULONG ulLo = 0;
ULONG ulHi = (sizeof(aCP2Name) / sizeof(struct _CP2NAME)) - 1;
ULONG ulNext;
LONG lFound = -1;
if (cp == SYSTEM_CP) {
ULONG aulCP[3];
ULONG cCP;
if (DosQueryCp(sizeof(aulCP), aulCP, &cCP) != NO_ERROR) {
return NULL;
}
cp = aulCP[0];
}
if (aCP2Name[0].ulCode > cp || aCP2Name[ulHi].ulCode < cp) {
return NULL;
}
if (aCP2Name[0].ulCode == cp) {
return aCP2Name[0].pszName;
}
if (aCP2Name[ulHi].ulCode == cp) {
return aCP2Name[ulHi].pszName;
}
while ((ulHi - ulLo) > 1) {
ulNext = (ulLo + ulHi) / 2;
if (aCP2Name[ulNext].ulCode < cp) {
ulLo = ulNext;
} else if (aCP2Name[ulNext].ulCode > cp) {
ulHi = ulNext;
} else {
lFound = ulNext;
break;
}
}
return (lFound == -1)? NULL : aCP2Name[lFound].pszName;
}
unsigned long os2cpFromName(char *cp)
{
ULONG ulLo = 0;
ULONG ulHi = (sizeof(aName2CP) / sizeof(struct _NAME2CP)) - 1;
ULONG ulNext;
LONG lFound = -1;
LONG lCmp;
PCHAR pcEnd;
CHAR acBuf[64];
if (cp == NULL) {
ULONG aulCP[3];
ULONG cCP;
return (DosQueryCp(sizeof(aulCP), aulCP, &cCP) != NO_ERROR)? 0 : aulCP[0];
}
while (SDL_isspace((unsigned char) *cp)) {
cp++;
}
pcEnd = SDL_strchr(cp, ' ');
if (pcEnd == NULL) {
pcEnd = SDL_strchr(cp, '\0');
}
ulNext = pcEnd - cp;
if (ulNext >= sizeof(acBuf)) {
return 0;
}
SDL_memcpy(acBuf, cp, ulNext);
acBuf[ulNext] = '\0';
SDL_strupr(acBuf);
lCmp = SDL_strcmp(aName2CP[0].pszName, acBuf);
if (lCmp > 0) {
return 0;
}
if (lCmp == 0) {
return aName2CP[0].ulCode;
}
lCmp = SDL_strcmp(aName2CP[ulHi].pszName, acBuf);
if (lCmp < 0) {
return 0;
}
if (lCmp == 0) {
return aName2CP[ulHi].ulCode;
}
while ((ulHi - ulLo) > 1) {
ulNext = (ulLo + ulHi) / 2;
lCmp = SDL_strcmp(aName2CP[ulNext].pszName, acBuf);
if (lCmp < 0) {
ulLo = ulNext;
} else if (lCmp > 0) {
ulHi = ulNext;
} else {
lFound = ulNext;
break;
}
}
return (lFound == -1)? 0 : aName2CP[lFound].ulCode;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,286 +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.
*/
/*
Implementation iconv via OS/2 conversion objects API.
Andrey Vasilkin.
*/
#define ICONV_THREAD_SAFE 1
#include "geniconv.h"
#define _ULS_CALLCONV_
#define CALLCONV _System
#include <uconv.h>
#ifdef ICONV_THREAD_SAFE
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#include <os2.h>
#endif
#include "os2cp.h"
#ifndef GENICONV_STANDALONE
#include "../../../SDL_internal.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !defined(min)
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
#define SDL_min min
#define SDL_strcasecmp stricmp
#define SDL_snprintf _snprintf
#define SDL_malloc malloc
#define SDL_free free
#define SDL_memcpy memcpy
#endif
#define MAX_CP_NAME_LEN 64
typedef struct iuconv_obj {
UconvObject uo_tocode;
UconvObject uo_fromcode;
int buf_len;
UniChar *buf;
#ifdef ICONV_THREAD_SAFE
HMTX hMtx;
#endif
} iuconv_obj;
static int _createUconvObj(const char *code, UconvObject *uobj)
{
UniChar uc_code[MAX_CP_NAME_LEN];
int i;
const unsigned char *ch =
(const unsigned char *)code;
if (code == NULL)
uc_code[0] = 0;
else {
for (i = 0; i < MAX_CP_NAME_LEN; i++) {
uc_code[i] = (unsigned short)*ch;
if (! (*ch))
break;
ch++;
}
}
return UniCreateUconvObject(uc_code, uobj);
}
static int uconv_open(const char *code, UconvObject *uobj)
{
int rc;
if (!SDL_strcasecmp(code, "UTF-16")) {
*uobj = NULL;
return ULS_SUCCESS;
}
rc = _createUconvObj(code, uobj);
if (rc != ULS_SUCCESS) {
unsigned long cp = os2cpFromName((char *)code);
char cp_name[16];
if (cp != 0 && SDL_snprintf(cp_name, sizeof(cp_name), "IBM-%u", cp) > 0) {
rc = _createUconvObj(cp_name, uobj);
}
}
return rc;
}
iconv_t _System os2_iconv_open(const char* tocode, const char* fromcode)
{
UconvObject uo_tocode;
UconvObject uo_fromcode;
int rc;
iuconv_obj *iuobj;
if (tocode == NULL) {
tocode = "";
}
if (fromcode == NULL) {
fromcode = "";
}
if (SDL_strcasecmp(tocode, fromcode) != 0) {
rc = uconv_open(fromcode, &uo_fromcode);
if (rc != ULS_SUCCESS) {
errno = EINVAL;
return (iconv_t)(-1);
}
rc = uconv_open(tocode, &uo_tocode);
if (rc != ULS_SUCCESS) {
UniFreeUconvObject(uo_fromcode);
errno = EINVAL;
return (iconv_t)(-1);
}
} else {
uo_tocode = NULL;
uo_fromcode = NULL;
}
iuobj = (iuconv_obj *) SDL_malloc(sizeof(iuconv_obj));
iuobj->uo_tocode = uo_tocode;
iuobj->uo_fromcode = uo_fromcode;
iuobj->buf_len = 0;
iuobj->buf = NULL;
#ifdef ICONV_THREAD_SAFE
DosCreateMutexSem(NULL, &iuobj->hMtx, 0, FALSE);
#endif
return iuobj;
}
size_t _System os2_iconv(iconv_t cd,
char **inbuf, size_t *inbytesleft ,
char **outbuf, size_t *outbytesleft)
{
UconvObject uo_tocode = ((iuconv_obj *)(cd))->uo_tocode;
UconvObject uo_fromcode = ((iuconv_obj *)(cd))->uo_fromcode;
size_t nonIdenticalConv = 0;
UniChar *uc_buf;
size_t uc_buf_len;
UniChar **uc_str;
size_t *uc_str_len;
int rc;
size_t ret = (size_t)(-1);
if (uo_tocode == NULL && uo_fromcode == NULL) {
uc_buf_len = SDL_min(*inbytesleft, *outbytesleft);
SDL_memcpy(*outbuf, *inbuf, uc_buf_len);
*inbytesleft -= uc_buf_len;
*outbytesleft -= uc_buf_len;
outbuf += uc_buf_len;
inbuf += uc_buf_len;
return uc_buf_len;
}
#ifdef ICONV_THREAD_SAFE
DosRequestMutexSem(((iuconv_obj *)(cd))->hMtx, SEM_INDEFINITE_WAIT);
#endif
if (uo_tocode && uo_fromcode && (((iuconv_obj *)cd)->buf_len >> 1) < *inbytesleft) {
if (((iuconv_obj *)cd)->buf != NULL) {
SDL_free(((iuconv_obj *)cd)->buf);
}
((iuconv_obj *)cd)->buf_len = *inbytesleft << 1;
((iuconv_obj *)cd)->buf = (UniChar *) SDL_malloc(((iuconv_obj *)cd)->buf_len);
}
if (uo_fromcode) {
if (uo_tocode) {
uc_buf = ((iuconv_obj *)cd)->buf;
uc_buf_len = ((iuconv_obj *)cd)->buf_len;
uc_str = &uc_buf;
} else {
uc_str = (UniChar **)outbuf;
uc_buf_len = *outbytesleft;
}
uc_buf_len = uc_buf_len >> 1;
uc_str_len = &uc_buf_len;
rc = UniUconvToUcs(uo_fromcode, (void **)inbuf, inbytesleft,
uc_str, uc_str_len, &nonIdenticalConv);
uc_buf_len = uc_buf_len << 1;
if (!uo_tocode) {
*outbytesleft = uc_buf_len;
}
if (rc != ULS_SUCCESS) {
errno = EILSEQ;
goto done;
} else if (*inbytesleft && !*uc_str_len) {
errno = E2BIG;
goto done;
}
if (!uo_tocode) {
return nonIdenticalConv;
}
uc_buf = ((iuconv_obj *)cd)->buf;
uc_buf_len = ((iuconv_obj *)cd)->buf_len - uc_buf_len;
uc_str = &uc_buf;
uc_str_len = &uc_buf_len;
} else {
uc_str = (UniChar **)inbuf;
uc_str_len = inbytesleft;
}
*uc_str_len = *uc_str_len>>1;
rc = UniUconvFromUcs(uo_tocode, uc_str, uc_str_len, (void **)outbuf,
outbytesleft, &nonIdenticalConv);
if (rc != ULS_SUCCESS) {
switch (rc) {
case ULS_BUFFERFULL:
errno = E2BIG;
break;
case ULS_ILLEGALSEQUENCE:
errno = EILSEQ;
break;
case ULS_INVALID:
errno = EINVAL;
break;
}
goto done;
} else if (*uc_str_len && !*outbytesleft) {
errno = E2BIG;
goto done;
}
ret = nonIdenticalConv;
done:
#ifdef ICONV_THREAD_SAFE
DosReleaseMutexSem(((iuconv_obj *)cd)->hMtx);
#endif
return ret;
}
int _System os2_iconv_close(iconv_t cd)
{
if (!cd) return 0;
#ifdef ICONV_THREAD_SAFE
DosCloseMutexSem(((iuconv_obj *)cd)->hMtx);
#endif
if (((iuconv_obj *)cd)->uo_tocode != NULL) {
UniFreeUconvObject(((iuconv_obj *)cd)->uo_tocode);
}
if (((iuconv_obj *)cd)->uo_fromcode != NULL) {
UniFreeUconvObject(((iuconv_obj *)cd)->uo_fromcode);
}
if (((iuconv_obj *)cd)->buf != NULL) {
SDL_free(((iuconv_obj *)cd)->buf);
}
SDL_free(cd);
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,119 +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.
*/
#include "geniconv.h"
#ifndef GENICONV_STANDALONE
#include "../../../SDL_internal.h"
#else
#include <stdlib.h>
#define SDL_malloc malloc
#define SDL_realloc realloc
#define SDL_free free
#endif
int StrUTF8(int to_utf8, char *dst, int c_dst, char *src, int c_src)
{
size_t rc;
char *dststart = dst;
iconv_t cd;
char *tocp, *fromcp;
int err = 0;
if (c_dst < 4) {
return -1;
}
if (to_utf8) {
tocp = "UTF-8";
fromcp = "";
} else {
tocp = "";
fromcp = "UTF-8";
}
cd = iconv_open(tocp, fromcp);
if (cd == (iconv_t)-1) {
return -1;
}
while (c_src > 0) {
rc = iconv(cd, &src, (size_t *)&c_src, &dst, (size_t *)&c_dst);
if (rc == (size_t)-1) {
if (errno == EILSEQ) {
/* Try to skip invalid character */
src++;
c_src--;
continue;
}
err = 1;
break;
}
}
iconv_close(cd);
/* Write trailing ZERO (1 byte for UTF-8, 2 bytes for the system cp) */
if (to_utf8) {
if (c_dst < 1) {
dst--;
err = 1; /* The destination buffer overflow */
}
*dst = '\0';
} else {
if (c_dst < 2) {
dst -= (c_dst == 0) ? 2 : 1;
err = 1; /* The destination buffer overflow */
}
*((short *)dst) = '\0';
}
return (err) ? -1 : (dst - dststart);
}
char *StrUTF8New(int to_utf8, char *str, int c_str)
{
int c_newstr = (((c_str > 4) ? c_str : 4) + 1) * 2;
char * newstr = (char *) SDL_malloc(c_newstr);
if (newstr == NULL) {
return NULL;
}
c_newstr = StrUTF8(to_utf8, newstr, c_newstr, str, c_str);
if (c_newstr != -1) {
str = (char *) SDL_realloc(newstr, c_newstr + ((to_utf8) ? 1 : sizeof(short)));
if (str) {
return str;
}
}
SDL_free(newstr);
return NULL;
}
void StrUTF8Free(char *str)
{
SDL_free(str);
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,69 +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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "geniconv.h"
int main(void)
{
char acBuf[128];
char *inbuf = "ôÅÓÔ - ÐÒÏ×ÅÒËÁ"; /* KOI8-R string */
size_t inbytesleft = strlen(inbuf);
char *outbuf = acBuf;
size_t outbytesleft = sizeof(acBuf);
iconv_t ic;
/* KOI8 -> system cp */
ic = iconv_open("", "KOI8-R");
if (ic == (iconv_t)(-1)) {
puts("iconv_open() fail");
return 1;
}
iconv(ic, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
printf("KOI8-R to system cp: %s\n", acBuf);
iconv_close(ic);
/* System cp -> UTF-8 -> system cp: */
/* System cp -> UTF-8 by StrUTF8New() */
inbuf = StrUTF8New(1, acBuf, strlen(acBuf));
/* UTF-8 -> system cp. by StrUTF8() */
if (StrUTF8(0, acBuf, sizeof(acBuf), inbuf, strlen(inbuf)) == -1) {
puts("StrUTF8() failed");
} else {
printf("system cp. -> UTF-8 -> system cp.: %s\n", acBuf);
}
free(inbuf);
/* Unload used DLL */
iconv_clean();
puts("Done.");
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,4 +0,0 @@
# OpenWatcom exports file for libiconv
++'libiconv'.'ICONV2'..'_libiconv'
++'libiconv_close'.'ICONV2'..'_libiconv_close'
++'libiconv_open'.'ICONV2'..'_libiconv_open'

View File

@@ -20,8 +20,6 @@
*/
#include "../../SDL_internal.h"
#ifndef __WINRT__
#include "SDL_hid.h"
@@ -85,6 +83,4 @@ WIN_UnloadHIDDLL(void)
}
}
#endif /* !__WINRT__ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -25,8 +25,6 @@
#include "SDL_windows.h"
#ifndef __WINRT__
typedef LONG NTSTATUS;
typedef USHORT USAGE;
typedef struct _HIDP_PREPARSED_DATA *PHIDP_PREPARSED_DATA;
@@ -197,8 +195,6 @@ extern HidP_GetValueCaps_t SDL_HidP_GetValueCaps;
extern HidP_MaxDataListLength_t SDL_HidP_MaxDataListLength;
extern HidP_GetData_t SDL_HidP_GetData;
#endif /* !__WINRT__ */
#endif /* SDL_hid_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -399,7 +399,9 @@ 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) {
if (!a && !b) {
return 0;
} else if (!a && b) {
return -1;
} else if (a && !b) {
return 1;

View File

@@ -20,7 +20,7 @@
*/
#include "../../SDL_internal.h"
#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
#if defined(__WIN32__) || defined(__GDK__)
#include "SDL_windows.h"
#include "SDL_error.h"
@@ -89,14 +89,7 @@ WIN_CoInitialize(void)
If you need multi-threaded mode, call CoInitializeEx() before SDL_Init()
*/
#ifdef __WINRT__
/* DLudwig: On WinRT, it is assumed that COM was initialized in main().
CoInitializeEx is available (not CoInitialize though), however
on WinRT, main() is typically declared with the [MTAThread]
attribute, which, AFAIK, should initialize COM.
*/
return S_OK;
#elif defined(__XBOXONE__) || defined(__XBOXSERIES__)
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
/* On Xbox, there's no need to call CoInitializeEx (and it's not implemented) */
return S_OK;
#else
@@ -118,12 +111,9 @@ WIN_CoInitialize(void)
void
WIN_CoUninitialize(void)
{
#ifndef __WINRT__
CoUninitialize();
#endif
}
#ifndef __WINRT__
void *
WIN_LoadComBaseFunction(const char *name)
{
@@ -140,14 +130,10 @@ WIN_LoadComBaseFunction(const char *name)
return NULL;
}
}
#endif
HRESULT
WIN_RoInitialize(void)
{
#ifdef __WINRT__
return S_OK;
#else
typedef HRESULT (WINAPI *RoInitialize_t)(RO_INIT_TYPE initType);
RoInitialize_t RoInitializeFunc = (RoInitialize_t)WIN_LoadComBaseFunction("RoInitialize");
if (RoInitializeFunc) {
@@ -167,22 +153,19 @@ WIN_RoInitialize(void)
} else {
return E_NOINTERFACE;
}
#endif
}
void
WIN_RoUninitialize(void)
{
#ifndef __WINRT__
typedef void (WINAPI *RoUninitialize_t)(void);
RoUninitialize_t RoUninitializeFunc = (RoUninitialize_t)WIN_LoadComBaseFunction("RoUninitialize");
if (RoUninitializeFunc) {
RoUninitializeFunc();
}
#endif
}
#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__)
static BOOL
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
@@ -206,7 +189,7 @@ IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServiceP
BOOL WIN_IsWindowsVistaOrGreater(void)
{
#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__)
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
return TRUE;
#else
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
@@ -215,7 +198,7 @@ BOOL WIN_IsWindowsVistaOrGreater(void)
BOOL WIN_IsWindows7OrGreater(void)
{
#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__)
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
return TRUE;
#else
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
@@ -224,7 +207,7 @@ BOOL WIN_IsWindows7OrGreater(void)
BOOL WIN_IsWindows8OrGreater(void)
{
#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__)
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
return TRUE;
#else
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
@@ -255,8 +238,8 @@ WASAPI doesn't need this. This is just for DirectSound/WinMM.
char *
WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid)
{
#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__)
return WIN_StringToUTF8(name); /* No registry access on WinRT/UWP and Xbox, go with what we've got. */
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
return WIN_StringToUTF8(name); /* No registry access on Xbox, go with what we've got. */
#else
static const GUID nullguid = { 0 };
const unsigned char *ptr;
@@ -308,7 +291,7 @@ WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid)
retval = WIN_StringToUTF8(strw);
SDL_free(strw);
return retval ? retval : WIN_StringToUTF8(name);
#endif /* if __WINRT__ / else */
#endif /**/
}
BOOL
@@ -341,6 +324,6 @@ WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect)
winrect->bottom = sdlrect->y + sdlrect->h - 1;
}
#endif /* defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__) */
#endif /* defined(__WIN32__) || defined(__GDK__) */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -25,8 +25,12 @@
#define _INCLUDED_WINDOWS_H
#if defined(__WIN32__)
#define WIN32_LEAN_AND_MEAN
#define STRICT
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#ifndef STRICT
#define STRICT 1
#endif
#ifndef UNICODE
#define UNICODE 1
#endif
@@ -40,9 +44,14 @@
#define _WIN32_WINNT 0x501 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices(), 0x501 for raw input */
#endif
#define WINVER _WIN32_WINNT
#elif defined(__WINGDK__)
#define WIN32_LEAN_AND_MEAN
#define STRICT
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#ifndef STRICT
#define STRICT 1
#endif
#ifndef UNICODE
#define UNICODE 1
#endif
@@ -50,12 +59,13 @@
#undef _WIN32_WINNT
#define _WIN32_WINNT 0xA00
#define WINVER _WIN32_WINNT
#elif defined(__XBOXONE__) || defined(__XBOXSERIES__)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#ifndef STRICT
#define STRICT
#define STRICT 1
#endif
#ifndef UNICODE
#define UNICODE 1
@@ -69,6 +79,16 @@
#include <windows.h>
#include <basetyps.h> /* for REFIID with broken mingw.org headers */
/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
#ifndef DWORD_PTR
#define DWORD_PTR DWORD
#endif
#ifndef LONG_PTR
#define LONG_PTR LONG
#endif
#endif
#include "SDL_rect.h"
/* Routines to convert from UTF8 to native Windows text */
@@ -100,10 +120,8 @@ extern int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr);
/* Sets an error message based on GetLastError(). Always return -1. */
extern int WIN_SetError(const char *prefix);
#if !defined(__WINRT__)
/* Load a function from combase.dll */
void *WIN_LoadComBaseFunction(const char *name);
#endif
/* Wrap up the oddities of CoInitialize() into a common function. */
extern HRESULT WIN_CoInitialize(void);

View File

@@ -37,7 +37,7 @@ static HANDLE s_pXInputDLL = 0;
static int s_XInputDLLRefCount = 0;
#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__)
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
int
WIN_LoadXInputDLL(void)
@@ -70,7 +70,7 @@ WIN_UnloadXInputDLL(void)
{
}
#else /* !(defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__)) */
#else /* !(defined(__XBOXONE__) || defined(__XBOXSERIES__)) */
int
WIN_LoadXInputDLL(void)
@@ -138,7 +138,7 @@ WIN_UnloadXInputDLL(void)
}
}
#endif /* __WINRT__ */
#endif /**/
/* Ends C function definitions when using C++ */
#ifdef __cplusplus

View File

@@ -133,10 +133,13 @@ using namespace XInputOnGameInput;
#ifndef BATTERY_DEVTYPE_GAMEPAD
#define BATTERY_DEVTYPE_GAMEPAD 0x00
#endif
#ifndef BATTERY_TYPE_DISCONNECTED
#define BATTERY_TYPE_DISCONNECTED 0x00
#endif
#ifndef BATTERY_TYPE_WIRED
#define BATTERY_TYPE_WIRED 0x01
#endif
#ifndef BATTERY_TYPE_UNKNOWN
#define BATTERY_TYPE_UNKNOWN 0xFF
#endif

View File

@@ -1,67 +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.
*/
#include "../../SDL_internal.h"
#include "SDL_main.h"
#include "SDL_system.h"
#include "SDL_winrtapp_direct3d.h"
#include "SDL_winrtapp_xaml.h"
#include <wrl.h>
int (*WINRT_SDLAppEntryPoint)(int, char **) = NULL;
extern "C" DECLSPEC int
SDL_WinRTRunApp(SDL_main_func mainFunction, void * xamlBackgroundPanel)
{
if (xamlBackgroundPanel) {
return SDL_WinRTInitXAMLApp(mainFunction, xamlBackgroundPanel);
} else {
if (FAILED(Windows::Foundation::Initialize(RO_INIT_MULTITHREADED))) {
return 1;
}
return SDL_WinRTInitNonXAMLApp(mainFunction);
}
}
extern "C" DECLSPEC SDL_WinRT_DeviceFamily
SDL_WinRTGetDeviceFamily()
{
#if NTDDI_VERSION >= NTDDI_WIN10 /* !!! FIXME: I have no idea if this is the right test. This is a UWP API, I think. Older windows should...just return "mobile"? I don't know. --ryan. */
Platform::String^ deviceFamily = Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily;
if (deviceFamily->Equals("Windows.Desktop"))
{
return SDL_WINRT_DEVICEFAMILY_DESKTOP;
}
else if (deviceFamily->Equals("Windows.Mobile"))
{
return SDL_WINRT_DEVICEFAMILY_MOBILE;
}
else if (deviceFamily->Equals("Windows.Xbox"))
{
return SDL_WINRT_DEVICEFAMILY_XBOX;
}
#endif
return SDL_WINRT_DEVICEFAMILY_UNKNOWN;
}

View File

@@ -1,31 +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.
*/
#include "SDL_config.h"
#ifndef SDL_winrtapp_common_h_
#define SDL_winrtapp_common_h_
/* A pointer to the app's C-style main() function (which is a different
function than the WinRT app's actual entry point).
*/
extern int (*WINRT_SDLAppEntryPoint)(int, char **);
#endif // SDL_winrtapp_common_h_

View File

@@ -1,797 +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.
*/
#include "../../SDL_internal.h"
/* Standard C++11 includes */
#include <functional>
#include <string>
#include <sstream>
using namespace std;
/* Windows includes */
#include "ppltasks.h"
using namespace concurrency;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::Devices::Input;
using namespace Windows::Graphics::Display;
using namespace Windows::Foundation;
using namespace Windows::System;
using namespace Windows::UI::Core;
using namespace Windows::UI::Input;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
using namespace Windows::Phone::UI::Input;
#endif
/* SDL includes */
extern "C" {
#include "SDL_events.h"
#include "SDL_hints.h"
#include "SDL_main.h"
#include "SDL_stdinc.h"
#include "SDL_render.h"
#include "../../video/SDL_sysvideo.h"
//#include "../../SDL_hints_c.h"
#include "../../events/SDL_events_c.h"
#include "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_windowevents_c.h"
#include "../../render/SDL_sysrender.h"
#include "../windows/SDL_windows.h"
}
#include "../../video/winrt/SDL_winrtevents_c.h"
#include "../../video/winrt/SDL_winrtvideo_cpp.h"
#include "SDL_winrtapp_common.h"
#include "SDL_winrtapp_direct3d.h"
#if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
/* Calling IDXGIDevice3::Trim on the active Direct3D 11.x device is necessary
* when Windows 8.1 apps are about to get suspended.
*/
extern "C" void D3D11_Trim(SDL_Renderer *);
#endif
// Compile-time debugging options:
// To enable, uncomment; to disable, comment them out.
//#define LOG_POINTER_EVENTS 1
//#define LOG_WINDOW_EVENTS 1
//#define LOG_ORIENTATION_EVENTS 1
// HACK, DLudwig: record a reference to the global, WinRT 'app'/view.
// SDL/WinRT will use this throughout its code.
//
// TODO, WinRT: consider replacing SDL_WinRTGlobalApp with something
// non-global, such as something created inside
// SDL_InitSubSystem(SDL_INIT_VIDEO), or something inside
// SDL_CreateWindow().
SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;
ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
{
public:
virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
};
IFrameworkView^ SDLApplicationSource::CreateView()
{
// TODO, WinRT: see if this function (CreateView) can ever get called
// more than once. For now, just prevent it from ever assigning
// SDL_WinRTGlobalApp more than once.
SDL_assert(!SDL_WinRTGlobalApp);
SDL_WinRTApp ^ app = ref new SDL_WinRTApp();
if (!SDL_WinRTGlobalApp)
{
SDL_WinRTGlobalApp = app;
}
return app;
}
int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **))
{
WINRT_SDLAppEntryPoint = mainFunction;
auto direct3DApplicationSource = ref new SDLApplicationSource();
CoreApplication::Run(direct3DApplicationSource);
return 0;
}
static void
WINRT_ProcessWindowSizeChange() // TODO: Pass an SDL_Window-identifying thing into WINRT_ProcessWindowSizeChange()
{
CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
if (coreWindow) {
if (WINRT_GlobalSDLWindow) {
SDL_Window * window = WINRT_GlobalSDLWindow;
SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
int x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
int y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
/* WinPhone 8.0 always keeps its native window size in portrait,
regardless of orientation. This changes in WinPhone 8.1,
in which the native window's size changes along with
orientation.
Attempt to emulate WinPhone 8.1's behavior on WinPhone 8.0, with
regards to window size. This fixes a rendering bug that occurs
when a WinPhone 8.0 app is rotated to either 90 or 270 degrees.
*/
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
switch (currentOrientation) {
case DisplayOrientations::Landscape:
case DisplayOrientations::LandscapeFlipped: {
int tmp = w;
w = h;
h = tmp;
} break;
}
#endif
const Uint32 latestFlags = WINRT_DetectWindowFlags(window);
if (latestFlags & SDL_WINDOW_MAXIMIZED) {
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
} else {
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
WINRT_UpdateWindowFlags(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
/* The window can move during a resize event, such as when maximizing
or resizing from a corner */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
}
}
}
SDL_WinRTApp::SDL_WinRTApp() :
m_windowClosed(false),
m_windowVisible(true)
{
}
void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
{
applicationView->Activated +=
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &SDL_WinRTApp::OnAppActivated);
CoreApplication::Suspending +=
ref new EventHandler<SuspendingEventArgs^>(this, &SDL_WinRTApp::OnSuspending);
CoreApplication::Resuming +=
ref new EventHandler<Platform::Object^>(this, &SDL_WinRTApp::OnResuming);
CoreApplication::Exiting +=
ref new EventHandler<Platform::Object^>(this, &SDL_WinRTApp::OnExiting);
#if NTDDI_VERSION >= NTDDI_WIN10
/* HACK ALERT! Xbox One doesn't seem to detect gamepads unless something
gets registered to receive Win10's Windows.Gaming.Input.Gamepad.GamepadAdded
events. We'll register an event handler for these events here, to make
sure that gamepad detection works later on, if requested.
*/
Windows::Gaming::Input::Gamepad::GamepadAdded +=
ref new Windows::Foundation::EventHandler<Windows::Gaming::Input::Gamepad^>(
this, &SDL_WinRTApp::OnGamepadAdded
);
#endif
}
#if NTDDI_VERSION > NTDDI_WIN8
void SDL_WinRTApp::OnOrientationChanged(DisplayInformation^ sender, Object^ args)
#else
void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
#endif
{
#if LOG_ORIENTATION_EVENTS==1
{
CoreWindow^ window = CoreWindow::GetForCurrentThread();
if (window) {
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Bounds={%f,%f,%f,%f}\n",
__FUNCTION__,
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
WINRT_DISPLAY_PROPERTY(NativeOrientation),
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
window->Bounds.X,
window->Bounds.Y,
window->Bounds.Width,
window->Bounds.Height);
} else {
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
__FUNCTION__,
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
WINRT_DISPLAY_PROPERTY(NativeOrientation),
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
}
}
#endif
WINRT_ProcessWindowSizeChange();
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
// HACK: Make sure that orientation changes
// lead to the Direct3D renderer's viewport getting updated:
//
// For some reason, this doesn't seem to need to be done on Windows 8.x,
// even when going from Landscape to LandscapeFlipped. It only seems to
// be needed on Windows Phone, at least when I tested on my devices.
// I'm not currently sure why this is, but it seems to work fine. -- David L.
//
// TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases
SDL_Window * window = WINRT_GlobalSDLWindow;
if (window) {
SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SIZE_CHANGED, w, h);
}
#endif
}
void SDL_WinRTApp::SetWindow(CoreWindow^ window)
{
#if LOG_WINDOW_EVENTS==1
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window bounds={%f, %f, %f,%f}\n",
__FUNCTION__,
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
WINRT_DISPLAY_PROPERTY(NativeOrientation),
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
window->Bounds.X,
window->Bounds.Y,
window->Bounds.Width,
window->Bounds.Height);
#endif
window->SizeChanged +=
ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &SDL_WinRTApp::OnWindowSizeChanged);
window->VisibilityChanged +=
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &SDL_WinRTApp::OnVisibilityChanged);
window->Activated +=
ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>(this, &SDL_WinRTApp::OnWindowActivated);
window->Closed +=
ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &SDL_WinRTApp::OnWindowClosed);
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0);
#endif
window->PointerPressed +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerPressed);
window->PointerMoved +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerMoved);
window->PointerReleased +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerReleased);
window->PointerEntered +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerEntered);
window->PointerExited +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerExited);
window->PointerWheelChanged +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerWheelChanged);
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
// Retrieves relative-only mouse movements:
Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved +=
ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &SDL_WinRTApp::OnMouseMoved);
#endif
window->KeyDown +=
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyDown);
window->KeyUp +=
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyUp);
window->CharacterReceived +=
ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &SDL_WinRTApp::OnCharacterReceived);
#if NTDDI_VERSION >= NTDDI_WIN10
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->BackRequested +=
ref new EventHandler<BackRequestedEventArgs^>(this, &SDL_WinRTApp::OnBackButtonPressed);
#elif WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
HardwareButtons::BackPressed +=
ref new EventHandler<BackPressedEventArgs^>(this, &SDL_WinRTApp::OnBackButtonPressed);
#endif
#if NTDDI_VERSION > NTDDI_WIN8
DisplayInformation::GetForCurrentView()->OrientationChanged +=
ref new TypedEventHandler<Windows::Graphics::Display::DisplayInformation^, Object^>(this, &SDL_WinRTApp::OnOrientationChanged);
#else
DisplayProperties::OrientationChanged +=
ref new DisplayPropertiesEventHandler(this, &SDL_WinRTApp::OnOrientationChanged);
#endif
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps)
// Make sure we know when a user has opened the app's settings pane.
// This is needed in order to display a privacy policy, which needs
// to be done for network-enabled apps, as per Windows Store requirements.
using namespace Windows::UI::ApplicationSettings;
SettingsPane::GetForCurrentView()->CommandsRequested +=
ref new TypedEventHandler<SettingsPane^, SettingsPaneCommandsRequestedEventArgs^>
(this, &SDL_WinRTApp::OnSettingsPaneCommandsRequested);
#endif
}
void SDL_WinRTApp::Load(Platform::String^ entryPoint)
{
}
void SDL_WinRTApp::Run()
{
SDL_SetMainReady();
if (WINRT_SDLAppEntryPoint)
{
// TODO, WinRT: pass the C-style main() a reasonably realistic
// representation of command line arguments.
int argc = 1;
char **argv = (char **)SDL_malloc(2 * sizeof(*argv));
if (!argv) {
return;
}
argv[0] = SDL_strdup("WinRTApp");
argv[1] = NULL;
WINRT_SDLAppEntryPoint(argc, argv);
SDL_free(argv[0]);
SDL_free(argv);
}
}
static bool IsSDLWindowEventPending(SDL_WindowEventID windowEventID)
{
SDL_Event events[128];
const int count = SDL_PeepEvents(events, sizeof(events)/sizeof(SDL_Event), SDL_PEEKEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT);
for (int i = 0; i < count; ++i) {
if (events[i].window.event == windowEventID) {
return true;
}
}
return false;
}
bool SDL_WinRTApp::ShouldWaitForAppResumeEvents()
{
/* Don't wait if the app is visible: */
if (m_windowVisible) {
return false;
}
/* Don't wait until the window-hide events finish processing.
* Do note that if an app-suspend event is sent (as indicated
* by SDL_APP_WILLENTERBACKGROUND and SDL_APP_DIDENTERBACKGROUND
* events), then this code may be a moot point, as WinRT's
* own event pump (aka ProcessEvents()) will pause regardless
* of what we do here. This happens on Windows Phone 8, to note.
* Windows 8.x apps, on the other hand, may get a chance to run
* these.
*/
if (IsSDLWindowEventPending(SDL_WINDOWEVENT_HIDDEN)) {
return false;
} else if (IsSDLWindowEventPending(SDL_WINDOWEVENT_FOCUS_LOST)) {
return false;
} else if (IsSDLWindowEventPending(SDL_WINDOWEVENT_MINIMIZED)) {
return false;
}
return true;
}
void SDL_WinRTApp::PumpEvents()
{
if (!m_windowClosed) {
if (!ShouldWaitForAppResumeEvents()) {
/* This is the normal way in which events should be pumped.
* 'ProcessAllIfPresent' will make ProcessEvents() process anywhere
* from zero to N events, and will then return.
*/
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
} else {
/* This style of event-pumping, with 'ProcessOneAndAllPending',
* will cause anywhere from one to N events to be processed. If
* at least one event is processed, the call will return. If
* no events are pending, then the call will wait until one is
* available, and will not return (to the caller) until this
* happens! This should only occur when the app is hidden.
*/
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
}
}
}
void SDL_WinRTApp::Uninitialize()
{
}
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
void SDL_WinRTApp::OnSettingsPaneCommandsRequested(
Windows::UI::ApplicationSettings::SettingsPane ^p,
Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^args)
{
using namespace Platform;
using namespace Windows::UI::ApplicationSettings;
using namespace Windows::UI::Popups;
String ^privacyPolicyURL = nullptr; // a URL to an app's Privacy Policy
String ^privacyPolicyLabel = nullptr; // label/link text
const char *tmpHintValue = NULL; // SDL_GetHint-retrieved value, used immediately
wchar_t *tmpStr = NULL; // used for UTF8 to UCS2 conversion
// Setup a 'Privacy Policy' link, if one is available (via SDL_GetHint):
tmpHintValue = SDL_GetHint(SDL_HINT_WINRT_PRIVACY_POLICY_URL);
if (tmpHintValue && tmpHintValue[0] != '\0') {
// Convert the privacy policy's URL to UCS2:
tmpStr = WIN_UTF8ToString(tmpHintValue);
privacyPolicyURL = ref new String(tmpStr);
SDL_free(tmpStr);
// Optionally retrieve custom label-text for the link. If this isn't
// available, a default value will be used instead.
tmpHintValue = SDL_GetHint(SDL_HINT_WINRT_PRIVACY_POLICY_LABEL);
if (tmpHintValue && tmpHintValue[0] != '\0') {
tmpStr = WIN_UTF8ToString(tmpHintValue);
privacyPolicyLabel = ref new String(tmpStr);
SDL_free(tmpStr);
} else {
privacyPolicyLabel = ref new String(L"Privacy Policy");
}
// Register the link, along with a handler to be called if and when it is
// clicked:
auto cmd = ref new SettingsCommand(L"privacyPolicy", privacyPolicyLabel,
ref new UICommandInvokedHandler([=](IUICommand ^) {
Windows::System::Launcher::LaunchUriAsync(ref new Uri(privacyPolicyURL));
}));
args->Request->ApplicationCommands->Append(cmd);
}
}
#endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
{
#if LOG_WINDOW_EVENTS==1
SDL_Log("%s, size={%f,%f}, bounds={%f,%f,%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
__FUNCTION__,
args->Size.Width, args->Size.Height,
sender->Bounds.X, sender->Bounds.Y, sender->Bounds.Width, sender->Bounds.Height,
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
WINRT_DISPLAY_PROPERTY(NativeOrientation),
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
(WINRT_GlobalSDLWindow ? "yes" : "no"));
#endif
WINRT_ProcessWindowSizeChange();
}
void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
{
#if LOG_WINDOW_EVENTS==1
SDL_Log("%s, visible?=%s, bounds={%f,%f,%f,%f}, WINRT_GlobalSDLWindow?=%s\n",
__FUNCTION__,
(args->Visible ? "yes" : "no"),
sender->Bounds.X, sender->Bounds.Y,
sender->Bounds.Width, sender->Bounds.Height,
(WINRT_GlobalSDLWindow ? "yes" : "no"));
#endif
m_windowVisible = args->Visible;
if (WINRT_GlobalSDLWindow) {
SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow->surface_valid;
Uint32 latestWindowFlags = WINRT_DetectWindowFlags(WINRT_GlobalSDLWindow);
if (args->Visible) {
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
if (latestWindowFlags & SDL_WINDOW_MAXIMIZED) {
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
} else {
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
} else {
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_HIDDEN, 0, 0);
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
}
// HACK: Prevent SDL's window-hide handling code, which currently
// triggers a fake window resize (possibly erronously), from
// marking the SDL window's surface as invalid.
//
// A better solution to this probably involves figuring out if the
// fake window resize can be prevented.
WINRT_GlobalSDLWindow->surface_valid = wasSDLWindowSurfaceValid;
}
}
void SDL_WinRTApp::OnWindowActivated(CoreWindow^ sender, WindowActivatedEventArgs^ args)
{
#if LOG_WINDOW_EVENTS==1
SDL_Log("%s, WINRT_GlobalSDLWindow?=%s\n\n",
__FUNCTION__,
(WINRT_GlobalSDLWindow ? "yes" : "no"));
#endif
/* There's no property in Win 8.x to tell whether a window is active or
not. [De]activation events are, however, sent to the app. We'll just
record those, in case the CoreWindow gets wrapped by an SDL_Window at
some future time.
*/
sender->CustomProperties->Insert("SDLHelperWindowActivationState", args->WindowActivationState);
SDL_Window * window = WINRT_GlobalSDLWindow;
if (window) {
if (args->WindowActivationState != CoreWindowActivationState::Deactivated) {
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
if (SDL_GetKeyboardFocus() != window) {
SDL_SetKeyboardFocus(window);
}
/* Send a mouse-motion event as appropriate.
This doesn't work when called from OnPointerEntered, at least
not in WinRT CoreWindow apps (as OnPointerEntered doesn't
appear to be called after window-reactivation, at least not
in Windows 10, Build 10586.3 (November 2015 update, non-beta).
Don't do it on WinPhone 8.0 though, as CoreWindow's 'PointerPosition'
property isn't available.
*/
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION >= NTDDI_WINBLUE)
Point cursorPos = WINRT_TransformCursorPosition(window, sender->PointerPosition, TransformToSDLWindowSize);
SDL_SendMouseMotion(window, 0, 0, (int)cursorPos.X, (int)cursorPos.Y);
#endif
/* TODO, WinRT: see if the Win32 bugfix from https://hg.libsdl.org/SDL/rev/d278747da408 needs to be applied (on window activation) */
//WIN_CheckAsyncMouseRelease(data);
/* TODO, WinRT: implement clipboard support, if possible */
///*
// * FIXME: Update keyboard state
// */
//WIN_CheckClipboardUpdate(data->videodata);
// HACK: Resetting the mouse-cursor here seems to fix
// https://bugzilla.libsdl.org/show_bug.cgi?id=3217, whereby a
// WinRT app's mouse cursor may switch to Windows' 'wait' cursor,
// after a user alt-tabs back into a full-screened SDL app.
// This bug does not appear to reproduce 100% of the time.
// It may be a bug in Windows itself (v.10.0.586.36, as tested,
// and the most-recent as of this writing).
SDL_SetCursor(NULL);
} else {
if (SDL_GetKeyboardFocus() == window) {
SDL_SetKeyboardFocus(NULL);
}
}
}
}
void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
{
#if LOG_WINDOW_EVENTS==1
SDL_Log("%s\n", __FUNCTION__);
#endif
m_windowClosed = true;
}
void SDL_WinRTApp::OnAppActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
{
CoreWindow::GetForCurrentThread()->Activate();
}
void SDL_WinRTApp::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
{
// Save app state asynchronously after requesting a deferral. Holding a deferral
// indicates that the application is busy performing suspending operations. Be
// aware that a deferral may not be held indefinitely. After about five seconds,
// the app will be forced to exit.
// ... but first, let the app know it's about to go to the background.
// The separation of events may be important, given that the deferral
// runs in a separate thread. This'll make SDL_APP_WILLENTERBACKGROUND
// the only event among the two that runs in the main thread. Given
// that a few WinRT operations can only be done from the main thread
// (things that access the WinRT CoreWindow are one example of this),
// this could be important.
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
create_task([this, deferral]()
{
// Send an app did-enter-background event immediately to observers.
// CoreDispatcher::ProcessEvents, which is the backbone on which
// SDL_WinRTApp::PumpEvents is built, will not return to its caller
// once it sends out a suspend event. Any events posted to SDL's
// event queue won't get received until the WinRT app is resumed.
// SDL_AddEventWatch() may be used to receive app-suspend events on
// WinRT.
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
// Let the Direct3D 11 renderer prepare for the app to be backgrounded.
// This is necessary for Windows 8.1, possibly elsewhere in the future.
// More details at: http://msdn.microsoft.com/en-us/library/windows/apps/Hh994929.aspx
#if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
if (WINRT_GlobalSDLWindow) {
SDL_Renderer * renderer = SDL_GetRenderer(WINRT_GlobalSDLWindow);
if (renderer && (SDL_strcmp(renderer->info.name, "direct3d11") == 0)) {
D3D11_Trim(renderer);
}
}
#endif
deferral->Complete();
});
}
void SDL_WinRTApp::OnResuming(Platform::Object^ sender, Platform::Object^ args)
{
// Restore any data or state that was unloaded on suspend. By default, data
// and state are persisted when resuming from suspend. Note that these events
// do not occur if the app was previously terminated.
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
}
void SDL_WinRTApp::OnExiting(Platform::Object^ sender, Platform::Object^ args)
{
SDL_SendAppEvent(SDL_APP_TERMINATING);
}
static void
WINRT_LogPointerEvent(const char * header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)
{
Uint8 button, pressed;
Windows::UI::Input::PointerPoint ^ pt = args->CurrentPoint;
WINRT_GetSDLButtonForPointerPoint(pt, &button, &pressed);
SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d pressed=%d\n",
header,
pt->Position.X, pt->Position.Y,
transformedPoint.X, transformedPoint.Y,
pt->Properties->MouseWheelDelta,
pt->FrameId,
pt->PointerId,
button,
pressed);
}
void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
{
#if LOG_POINTER_EVENTS
WINRT_LogPointerEvent("pointer pressed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
#endif
WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
}
void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
{
#if LOG_POINTER_EVENTS
WINRT_LogPointerEvent("pointer moved", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
#endif
WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
}
void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
{
#if LOG_POINTER_EVENTS
WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
#endif
WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
}
void SDL_WinRTApp::OnPointerEntered(CoreWindow^ sender, PointerEventArgs^ args)
{
#if LOG_POINTER_EVENTS
WINRT_LogPointerEvent("pointer entered", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
#endif
WINRT_ProcessPointerEnteredEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
}
void SDL_WinRTApp::OnPointerExited(CoreWindow^ sender, PointerEventArgs^ args)
{
#if LOG_POINTER_EVENTS
WINRT_LogPointerEvent("pointer exited", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
#endif
WINRT_ProcessPointerExitedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
}
void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
{
#if LOG_POINTER_EVENTS
WINRT_LogPointerEvent("pointer wheel changed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize));
#endif
WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
}
void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
{
WINRT_ProcessMouseMovedEvent(WINRT_GlobalSDLWindow, args);
}
void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
{
WINRT_ProcessKeyDownEvent(args);
}
void SDL_WinRTApp::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
{
WINRT_ProcessKeyUpEvent(args);
}
void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args)
{
WINRT_ProcessCharacterReceivedEvent(args);
}
template <typename BackButtonEventArgs>
static void WINRT_OnBackButtonPressed(BackButtonEventArgs ^ args)
{
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_AC_BACK);
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_AC_BACK);
if (SDL_GetHintBoolean(SDL_HINT_WINRT_HANDLE_BACK_BUTTON, SDL_FALSE)) {
args->Handled = true;
}
}
#if NTDDI_VERSION >= NTDDI_WIN10
void SDL_WinRTApp::OnBackButtonPressed(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ args)
{
WINRT_OnBackButtonPressed(args);
}
#elif WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
void SDL_WinRTApp::OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args)
{
WINRT_OnBackButtonPressed(args);
}
#endif
#if NTDDI_VERSION >= NTDDI_WIN10
void SDL_WinRTApp::OnGamepadAdded(Platform::Object ^sender, Windows::Gaming::Input::Gamepad ^gamepad)
{
/* HACK ALERT: Nothing needs to be done here, as this method currently
only exists to allow something to be registered with Win10's
GamepadAdded event, an operation that seems to be necessary to get
Xinput-based detection to work on Xbox One.
*/
}
#endif
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,92 +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.
*/
#include <Windows.h>
extern int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **));
ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFrameworkView
{
public:
SDL_WinRTApp();
// IFrameworkView Methods.
virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
virtual void Load(Platform::String^ entryPoint);
virtual void Run();
virtual void Uninitialize();
internal:
// SDL-specific methods
void PumpEvents();
protected:
bool ShouldWaitForAppResumeEvents();
// Event Handlers.
#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps)
void OnSettingsPaneCommandsRequested(
Windows::UI::ApplicationSettings::SettingsPane ^p,
Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^args);
#endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
#if NTDDI_VERSION > NTDDI_WIN8
void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
#else
void OnOrientationChanged(Platform::Object^ sender);
#endif
void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
void OnLogicalDpiChanged(Platform::Object^ sender);
void OnAppActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
void OnResuming(Platform::Object^ sender, Platform::Object^ args);
void OnExiting(Platform::Object^ sender, Platform::Object^ args);
void OnWindowActivated(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ args);
void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerExited(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouseDevice, Windows::Devices::Input::MouseEventArgs^ args);
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
void OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args);
#if NTDDI_VERSION >= NTDDI_WIN10
void OnBackButtonPressed(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ args);
#elif WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
void OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args);
#endif
#if NTDDI_VERSION >= NTDDI_WIN10
void OnGamepadAdded(Platform::Object ^sender, Windows::Gaming::Input::Gamepad ^gamepad);
#endif
private:
bool m_windowClosed;
bool m_windowVisible;
};
extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;

View File

@@ -1,160 +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.
*/
/* Windows includes */
#include <agile.h>
#include <Windows.h>
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
#include <windows.ui.xaml.media.dxinterop.h>
#endif
/* SDL includes */
#include "../../SDL_internal.h"
#include "SDL.h"
#include "../../video/winrt/SDL_winrtevents_c.h"
#include "../../video/winrt/SDL_winrtvideo_cpp.h"
#include "SDL_winrtapp_common.h"
#include "SDL_winrtapp_xaml.h"
/* SDL-internal globals: */
SDL_bool WINRT_XAMLWasEnabled = SDL_FALSE;
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
extern "C"
ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative = NULL;
static Windows::Foundation::EventRegistrationToken WINRT_XAMLAppEventToken;
#endif
/*
* Input event handlers (XAML)
*/
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
static void
WINRT_OnPointerPressedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
{
WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
}
static void
WINRT_OnPointerMovedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
{
WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
}
static void
WINRT_OnPointerReleasedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
{
WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
}
static void
WINRT_OnPointerWheelChangedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
{
WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
}
#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
/*
* XAML-to-SDL Rendering Callback
*/
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
static void
WINRT_OnRenderViaXAML(_In_ Platform::Object^ sender, _In_ Platform::Object^ args)
{
WINRT_CycleXAMLThread();
}
#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
/*
* SDL + XAML Initialization
*/
int
SDL_WinRTInitXAMLApp(int (*mainFunction)(int, char **), void * backgroundPanelAsIInspectable)
{
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
return SDL_SetError("XAML support is not yet available in Windows Phone.");
#else
// Declare C++/CX namespaces:
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
// Make sure we have a valid XAML element (to draw onto):
if ( ! backgroundPanelAsIInspectable) {
return SDL_InvalidParamError("backgroundPanelAsIInspectable");
}
Platform::Object ^ backgroundPanel = reinterpret_cast<Object ^>((IInspectable *) backgroundPanelAsIInspectable);
SwapChainBackgroundPanel ^swapChainBackgroundPanel = dynamic_cast<SwapChainBackgroundPanel ^>(backgroundPanel);
if ( ! swapChainBackgroundPanel) {
return SDL_SetError("An unknown or unsupported type of XAML control was specified.");
}
// Setup event handlers:
swapChainBackgroundPanel->PointerPressed += ref new PointerEventHandler(WINRT_OnPointerPressedViaXAML);
swapChainBackgroundPanel->PointerReleased += ref new PointerEventHandler(WINRT_OnPointerReleasedViaXAML);
swapChainBackgroundPanel->PointerWheelChanged += ref new PointerEventHandler(WINRT_OnPointerWheelChangedViaXAML);
swapChainBackgroundPanel->PointerMoved += ref new PointerEventHandler(WINRT_OnPointerMovedViaXAML);
// Setup for rendering:
IInspectable *panelInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(swapChainBackgroundPanel);
panelInspectable->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void **)&WINRT_GlobalSwapChainBackgroundPanelNative);
WINRT_XAMLAppEventToken = CompositionTarget::Rendering::add(ref new EventHandler<Object^>(WINRT_OnRenderViaXAML));
// Make sure the app is ready to call the SDL-centric main() function:
WINRT_SDLAppEntryPoint = mainFunction;
SDL_SetMainReady();
// Make sure video-init knows that we're initializing XAML:
SDL_bool oldXAMLWasEnabledValue = WINRT_XAMLWasEnabled;
WINRT_XAMLWasEnabled = SDL_TRUE;
// Make sure video modes are detected now, while we still have access to the WinRT
// CoreWindow. WinRT will not allow the app's CoreWindow to be accessed via the
// SDL/WinRT thread.
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
// SDL_InitSubSystem will, on error, set the SDL error. Let that propogate to
// the caller to here:
WINRT_XAMLWasEnabled = oldXAMLWasEnabledValue;
return -1;
}
// All done, for now.
return 0;
#endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP / else
}

View File

@@ -1,33 +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.
*/
#include "SDL_config.h"
#ifndef SDL_winrtapp_xaml_h_
#define SDL_winrtapp_xaml_h_
#include "SDL_stdinc.h"
#ifdef __cplusplus
extern SDL_bool WINRT_XAMLWasEnabled;
extern int SDL_WinRTInitXAMLApp(int (*mainFunction)(int, char **), void * backgroundPanelAsIInspectable);
#endif // ifdef __cplusplus
#endif // SDL_winrtapp_xaml_h_

View File

@@ -24,17 +24,9 @@
#include "../SDL_internal.h"
#endif
#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
#if defined(__WIN32__) || defined(__GDK__)
#include "../core/windows/SDL_windows.h"
#endif
#if defined(__OS2__)
#undef HAVE_SYSCTLBYNAME
#define INCL_DOS
#include <os2.h>
#ifndef QSV_NUMPROCESSORS
#define QSV_NUMPROCESSORS 26
#endif
#endif
/* CPU feature detection for SDL */
@@ -62,10 +54,6 @@
#include <setjmp.h>
#endif
#if defined(__QNXNTO__)
#include <sys/syspage.h>
#endif
#if (defined(__LINUX__) || defined(__ANDROID__)) && defined(__arm__)
#include <unistd.h>
#include <sys/types.h>
@@ -456,7 +444,7 @@ CPU_haveNEON(void)
query the OS kernel in a platform-specific way. :/ */
#if defined(SDL_CPUINFO_DISABLED)
return 0; /* disabled */
#elif (defined(__WINDOWS__) || defined(__WINRT__) || defined(__GDK__)) && (defined(_M_ARM) || defined(_M_ARM64))
#elif (defined(__WINDOWS__) || defined(__GDK__)) && (defined(_M_ARM) || defined(_M_ARM64))
/* Visual Studio, for ARM, doesn't define __ARM_ARCH. Handle this first. */
/* Seems to have been removed */
# if !defined(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)
@@ -468,6 +456,8 @@ CPU_haveNEON(void)
return 1; /* ARMv8 always has non-optional NEON support. */
#elif __VITA__
return 1;
#elif __3DS__
return 0;
#elif defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7)
/* (note that sysctlbyname("hw.optional.neon") doesn't work!) */
return 1; /* all Apple ARMv7 chips and later have NEON. */
@@ -482,8 +472,6 @@ CPU_haveNEON(void)
if (elf_aux_info(AT_HWCAP, (void *)&hasneon, (int)sizeof(hasneon)) != 0)
return 0;
return ((hasneon & HWCAP_NEON) == HWCAP_NEON);
#elif defined(__QNXNTO__)
return SYSPAGE_ENTRY(cpuinfo)->flags & ARM_CPU_FLAG_NEON;
#elif (defined(__LINUX__) || defined(__ANDROID__)) && defined(HAVE_GETAUXVAL)
return ((getauxval(AT_HWCAP) & HWCAP_NEON) == HWCAP_NEON);
#elif defined(__LINUX__)
@@ -678,12 +666,6 @@ SDL_GetCPUCount(void)
SDL_CPUCount = info.dwNumberOfProcessors;
}
#endif
#ifdef __OS2__
if (SDL_CPUCount <= 0) {
DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS,
&SDL_CPUCount, sizeof(SDL_CPUCount) );
}
#endif
#endif
/* There has to be at least 1, right? :) */
if (SDL_CPUCount <= 0) {
@@ -1062,13 +1044,6 @@ SDL_GetSystemRAM(void)
}
}
#endif
#ifdef __OS2__
if (SDL_SystemRAM <= 0) {
Uint32 sysram = 0;
DosQuerySysInfo(QSV_TOTPHYSMEM, QSV_TOTPHYSMEM, &sysram, 4);
SDL_SystemRAM = (int) (sysram / 0x100000U);
}
#endif
#ifdef __RISCOS__
if (SDL_SystemRAM <= 0) {
_kernel_swi_regs regs;
@@ -1150,8 +1125,6 @@ SDL_SIMDRealloc(void *mem, const size_t len)
}
if (mem) {
void **realptr = (void **) mem;
realptr--;
mem = *(((void **) mem) - 1);
/* Check the delta between the real pointer and user pointer */
@@ -1191,8 +1164,6 @@ void
SDL_SIMDFree(void *ptr)
{
if (ptr) {
void **realptr = (void **) ptr;
realptr--;
SDL_free(*(((void **) ptr) - 1));
}
}

View File

@@ -1,861 +0,0 @@
# Windows exports file for Watcom
# DO NOT EDIT THIS FILE BY HAND. It is autogenerated by gendynapi.pl.
++'_SDL_DYNAPI_entry'.'SDL2.dll'.'SDL_DYNAPI_entry'
++'_SDL_SetError'.'SDL2.dll'.'SDL_SetError'
++'_SDL_Log'.'SDL2.dll'.'SDL_Log'
++'_SDL_LogVerbose'.'SDL2.dll'.'SDL_LogVerbose'
++'_SDL_LogDebug'.'SDL2.dll'.'SDL_LogDebug'
++'_SDL_LogInfo'.'SDL2.dll'.'SDL_LogInfo'
++'_SDL_LogWarn'.'SDL2.dll'.'SDL_LogWarn'
++'_SDL_LogError'.'SDL2.dll'.'SDL_LogError'
++'_SDL_LogCritical'.'SDL2.dll'.'SDL_LogCritical'
++'_SDL_LogMessage'.'SDL2.dll'.'SDL_LogMessage'
++'_SDL_sscanf'.'SDL2.dll'.'SDL_sscanf'
++'_SDL_snprintf'.'SDL2.dll'.'SDL_snprintf'
++'_SDL_CreateThread'.'SDL2.dll'.'SDL_CreateThread'
++'_SDL_RWFromFP'.'SDL2.dll'.'SDL_RWFromFP'
++'_SDL_RegisterApp'.'SDL2.dll'.'SDL_RegisterApp'
++'_SDL_UnregisterApp'.'SDL2.dll'.'SDL_UnregisterApp'
++'_SDL_Direct3D9GetAdapterIndex'.'SDL2.dll'.'SDL_Direct3D9GetAdapterIndex'
++'_SDL_RenderGetD3D9Device'.'SDL2.dll'.'SDL_RenderGetD3D9Device'
# ++'_SDL_iPhoneSetAnimationCallback'.'SDL2.dll'.'SDL_iPhoneSetAnimationCallback'
# ++'_SDL_iPhoneSetEventPump'.'SDL2.dll'.'SDL_iPhoneSetEventPump'
# ++'_SDL_AndroidGetJNIEnv'.'SDL2.dll'.'SDL_AndroidGetJNIEnv'
# ++'_SDL_AndroidGetActivity'.'SDL2.dll'.'SDL_AndroidGetActivity'
# ++'_SDL_AndroidGetInternalStoragePath'.'SDL2.dll'.'SDL_AndroidGetInternalStoragePath'
# ++'_SDL_AndroidGetExternalStorageState'.'SDL2.dll'.'SDL_AndroidGetExternalStorageState'
# ++'_SDL_AndroidGetExternalStoragePath'.'SDL2.dll'.'SDL_AndroidGetExternalStoragePath'
++'_SDL_Init'.'SDL2.dll'.'SDL_Init'
++'_SDL_InitSubSystem'.'SDL2.dll'.'SDL_InitSubSystem'
++'_SDL_QuitSubSystem'.'SDL2.dll'.'SDL_QuitSubSystem'
++'_SDL_WasInit'.'SDL2.dll'.'SDL_WasInit'
++'_SDL_Quit'.'SDL2.dll'.'SDL_Quit'
++'_SDL_ReportAssertion'.'SDL2.dll'.'SDL_ReportAssertion'
++'_SDL_SetAssertionHandler'.'SDL2.dll'.'SDL_SetAssertionHandler'
++'_SDL_GetAssertionReport'.'SDL2.dll'.'SDL_GetAssertionReport'
++'_SDL_ResetAssertionReport'.'SDL2.dll'.'SDL_ResetAssertionReport'
++'_SDL_AtomicTryLock'.'SDL2.dll'.'SDL_AtomicTryLock'
++'_SDL_AtomicLock'.'SDL2.dll'.'SDL_AtomicLock'
++'_SDL_AtomicUnlock'.'SDL2.dll'.'SDL_AtomicUnlock'
++'_SDL_AtomicCAS'.'SDL2.dll'.'SDL_AtomicCAS'
++'_SDL_AtomicSet'.'SDL2.dll'.'SDL_AtomicSet'
++'_SDL_AtomicGet'.'SDL2.dll'.'SDL_AtomicGet'
++'_SDL_AtomicAdd'.'SDL2.dll'.'SDL_AtomicAdd'
++'_SDL_AtomicCASPtr'.'SDL2.dll'.'SDL_AtomicCASPtr'
++'_SDL_AtomicSetPtr'.'SDL2.dll'.'SDL_AtomicSetPtr'
++'_SDL_AtomicGetPtr'.'SDL2.dll'.'SDL_AtomicGetPtr'
++'_SDL_GetNumAudioDrivers'.'SDL2.dll'.'SDL_GetNumAudioDrivers'
++'_SDL_GetAudioDriver'.'SDL2.dll'.'SDL_GetAudioDriver'
++'_SDL_AudioInit'.'SDL2.dll'.'SDL_AudioInit'
++'_SDL_AudioQuit'.'SDL2.dll'.'SDL_AudioQuit'
++'_SDL_GetCurrentAudioDriver'.'SDL2.dll'.'SDL_GetCurrentAudioDriver'
++'_SDL_OpenAudio'.'SDL2.dll'.'SDL_OpenAudio'
++'_SDL_GetNumAudioDevices'.'SDL2.dll'.'SDL_GetNumAudioDevices'
++'_SDL_GetAudioDeviceName'.'SDL2.dll'.'SDL_GetAudioDeviceName'
++'_SDL_OpenAudioDevice'.'SDL2.dll'.'SDL_OpenAudioDevice'
++'_SDL_GetAudioStatus'.'SDL2.dll'.'SDL_GetAudioStatus'
++'_SDL_GetAudioDeviceStatus'.'SDL2.dll'.'SDL_GetAudioDeviceStatus'
++'_SDL_PauseAudio'.'SDL2.dll'.'SDL_PauseAudio'
++'_SDL_PauseAudioDevice'.'SDL2.dll'.'SDL_PauseAudioDevice'
++'_SDL_LoadWAV_RW'.'SDL2.dll'.'SDL_LoadWAV_RW'
++'_SDL_FreeWAV'.'SDL2.dll'.'SDL_FreeWAV'
++'_SDL_BuildAudioCVT'.'SDL2.dll'.'SDL_BuildAudioCVT'
++'_SDL_ConvertAudio'.'SDL2.dll'.'SDL_ConvertAudio'
++'_SDL_MixAudio'.'SDL2.dll'.'SDL_MixAudio'
++'_SDL_MixAudioFormat'.'SDL2.dll'.'SDL_MixAudioFormat'
++'_SDL_LockAudio'.'SDL2.dll'.'SDL_LockAudio'
++'_SDL_LockAudioDevice'.'SDL2.dll'.'SDL_LockAudioDevice'
++'_SDL_UnlockAudio'.'SDL2.dll'.'SDL_UnlockAudio'
++'_SDL_UnlockAudioDevice'.'SDL2.dll'.'SDL_UnlockAudioDevice'
++'_SDL_CloseAudio'.'SDL2.dll'.'SDL_CloseAudio'
++'_SDL_CloseAudioDevice'.'SDL2.dll'.'SDL_CloseAudioDevice'
++'_SDL_SetClipboardText'.'SDL2.dll'.'SDL_SetClipboardText'
++'_SDL_GetClipboardText'.'SDL2.dll'.'SDL_GetClipboardText'
++'_SDL_HasClipboardText'.'SDL2.dll'.'SDL_HasClipboardText'
++'_SDL_GetCPUCount'.'SDL2.dll'.'SDL_GetCPUCount'
++'_SDL_GetCPUCacheLineSize'.'SDL2.dll'.'SDL_GetCPUCacheLineSize'
++'_SDL_HasRDTSC'.'SDL2.dll'.'SDL_HasRDTSC'
++'_SDL_HasAltiVec'.'SDL2.dll'.'SDL_HasAltiVec'
++'_SDL_HasMMX'.'SDL2.dll'.'SDL_HasMMX'
++'_SDL_Has3DNow'.'SDL2.dll'.'SDL_Has3DNow'
++'_SDL_HasSSE'.'SDL2.dll'.'SDL_HasSSE'
++'_SDL_HasSSE2'.'SDL2.dll'.'SDL_HasSSE2'
++'_SDL_HasSSE3'.'SDL2.dll'.'SDL_HasSSE3'
++'_SDL_HasSSE41'.'SDL2.dll'.'SDL_HasSSE41'
++'_SDL_HasSSE42'.'SDL2.dll'.'SDL_HasSSE42'
++'_SDL_GetSystemRAM'.'SDL2.dll'.'SDL_GetSystemRAM'
++'_SDL_GetError'.'SDL2.dll'.'SDL_GetError'
++'_SDL_ClearError'.'SDL2.dll'.'SDL_ClearError'
++'_SDL_Error'.'SDL2.dll'.'SDL_Error'
++'_SDL_PumpEvents'.'SDL2.dll'.'SDL_PumpEvents'
++'_SDL_PeepEvents'.'SDL2.dll'.'SDL_PeepEvents'
++'_SDL_HasEvent'.'SDL2.dll'.'SDL_HasEvent'
++'_SDL_HasEvents'.'SDL2.dll'.'SDL_HasEvents'
++'_SDL_FlushEvent'.'SDL2.dll'.'SDL_FlushEvent'
++'_SDL_FlushEvents'.'SDL2.dll'.'SDL_FlushEvents'
++'_SDL_PollEvent'.'SDL2.dll'.'SDL_PollEvent'
++'_SDL_WaitEvent'.'SDL2.dll'.'SDL_WaitEvent'
++'_SDL_WaitEventTimeout'.'SDL2.dll'.'SDL_WaitEventTimeout'
++'_SDL_PushEvent'.'SDL2.dll'.'SDL_PushEvent'
++'_SDL_SetEventFilter'.'SDL2.dll'.'SDL_SetEventFilter'
++'_SDL_GetEventFilter'.'SDL2.dll'.'SDL_GetEventFilter'
++'_SDL_AddEventWatch'.'SDL2.dll'.'SDL_AddEventWatch'
++'_SDL_DelEventWatch'.'SDL2.dll'.'SDL_DelEventWatch'
++'_SDL_FilterEvents'.'SDL2.dll'.'SDL_FilterEvents'
++'_SDL_EventState'.'SDL2.dll'.'SDL_EventState'
++'_SDL_RegisterEvents'.'SDL2.dll'.'SDL_RegisterEvents'
++'_SDL_GetBasePath'.'SDL2.dll'.'SDL_GetBasePath'
++'_SDL_GetPrefPath'.'SDL2.dll'.'SDL_GetPrefPath'
++'_SDL_GameControllerAddMapping'.'SDL2.dll'.'SDL_GameControllerAddMapping'
++'_SDL_GameControllerMappingForGUID'.'SDL2.dll'.'SDL_GameControllerMappingForGUID'
++'_SDL_GameControllerMapping'.'SDL2.dll'.'SDL_GameControllerMapping'
++'_SDL_IsGameController'.'SDL2.dll'.'SDL_IsGameController'
++'_SDL_GameControllerNameForIndex'.'SDL2.dll'.'SDL_GameControllerNameForIndex'
++'_SDL_GameControllerOpen'.'SDL2.dll'.'SDL_GameControllerOpen'
++'_SDL_GameControllerName'.'SDL2.dll'.'SDL_GameControllerName'
++'_SDL_GameControllerGetAttached'.'SDL2.dll'.'SDL_GameControllerGetAttached'
++'_SDL_GameControllerGetJoystick'.'SDL2.dll'.'SDL_GameControllerGetJoystick'
++'_SDL_GameControllerEventState'.'SDL2.dll'.'SDL_GameControllerEventState'
++'_SDL_GameControllerUpdate'.'SDL2.dll'.'SDL_GameControllerUpdate'
++'_SDL_GameControllerGetAxisFromString'.'SDL2.dll'.'SDL_GameControllerGetAxisFromString'
++'_SDL_GameControllerGetStringForAxis'.'SDL2.dll'.'SDL_GameControllerGetStringForAxis'
++'_SDL_GameControllerGetBindForAxis'.'SDL2.dll'.'SDL_GameControllerGetBindForAxis'
++'_SDL_GameControllerGetAxis'.'SDL2.dll'.'SDL_GameControllerGetAxis'
++'_SDL_GameControllerGetButtonFromString'.'SDL2.dll'.'SDL_GameControllerGetButtonFromString'
++'_SDL_GameControllerGetStringForButton'.'SDL2.dll'.'SDL_GameControllerGetStringForButton'
++'_SDL_GameControllerGetBindForButton'.'SDL2.dll'.'SDL_GameControllerGetBindForButton'
++'_SDL_GameControllerGetButton'.'SDL2.dll'.'SDL_GameControllerGetButton'
++'_SDL_GameControllerClose'.'SDL2.dll'.'SDL_GameControllerClose'
++'_SDL_RecordGesture'.'SDL2.dll'.'SDL_RecordGesture'
++'_SDL_SaveAllDollarTemplates'.'SDL2.dll'.'SDL_SaveAllDollarTemplates'
++'_SDL_SaveDollarTemplate'.'SDL2.dll'.'SDL_SaveDollarTemplate'
++'_SDL_LoadDollarTemplates'.'SDL2.dll'.'SDL_LoadDollarTemplates'
++'_SDL_NumHaptics'.'SDL2.dll'.'SDL_NumHaptics'
++'_SDL_HapticName'.'SDL2.dll'.'SDL_HapticName'
++'_SDL_HapticOpen'.'SDL2.dll'.'SDL_HapticOpen'
++'_SDL_HapticOpened'.'SDL2.dll'.'SDL_HapticOpened'
++'_SDL_HapticIndex'.'SDL2.dll'.'SDL_HapticIndex'
++'_SDL_MouseIsHaptic'.'SDL2.dll'.'SDL_MouseIsHaptic'
++'_SDL_HapticOpenFromMouse'.'SDL2.dll'.'SDL_HapticOpenFromMouse'
++'_SDL_JoystickIsHaptic'.'SDL2.dll'.'SDL_JoystickIsHaptic'
++'_SDL_HapticOpenFromJoystick'.'SDL2.dll'.'SDL_HapticOpenFromJoystick'
++'_SDL_HapticClose'.'SDL2.dll'.'SDL_HapticClose'
++'_SDL_HapticNumEffects'.'SDL2.dll'.'SDL_HapticNumEffects'
++'_SDL_HapticNumEffectsPlaying'.'SDL2.dll'.'SDL_HapticNumEffectsPlaying'
++'_SDL_HapticQuery'.'SDL2.dll'.'SDL_HapticQuery'
++'_SDL_HapticNumAxes'.'SDL2.dll'.'SDL_HapticNumAxes'
++'_SDL_HapticEffectSupported'.'SDL2.dll'.'SDL_HapticEffectSupported'
++'_SDL_HapticNewEffect'.'SDL2.dll'.'SDL_HapticNewEffect'
++'_SDL_HapticUpdateEffect'.'SDL2.dll'.'SDL_HapticUpdateEffect'
++'_SDL_HapticRunEffect'.'SDL2.dll'.'SDL_HapticRunEffect'
++'_SDL_HapticStopEffect'.'SDL2.dll'.'SDL_HapticStopEffect'
++'_SDL_HapticDestroyEffect'.'SDL2.dll'.'SDL_HapticDestroyEffect'
++'_SDL_HapticGetEffectStatus'.'SDL2.dll'.'SDL_HapticGetEffectStatus'
++'_SDL_HapticSetGain'.'SDL2.dll'.'SDL_HapticSetGain'
++'_SDL_HapticSetAutocenter'.'SDL2.dll'.'SDL_HapticSetAutocenter'
++'_SDL_HapticPause'.'SDL2.dll'.'SDL_HapticPause'
++'_SDL_HapticUnpause'.'SDL2.dll'.'SDL_HapticUnpause'
++'_SDL_HapticStopAll'.'SDL2.dll'.'SDL_HapticStopAll'
++'_SDL_HapticRumbleSupported'.'SDL2.dll'.'SDL_HapticRumbleSupported'
++'_SDL_HapticRumbleInit'.'SDL2.dll'.'SDL_HapticRumbleInit'
++'_SDL_HapticRumblePlay'.'SDL2.dll'.'SDL_HapticRumblePlay'
++'_SDL_HapticRumbleStop'.'SDL2.dll'.'SDL_HapticRumbleStop'
++'_SDL_SetHintWithPriority'.'SDL2.dll'.'SDL_SetHintWithPriority'
++'_SDL_SetHint'.'SDL2.dll'.'SDL_SetHint'
++'_SDL_GetHint'.'SDL2.dll'.'SDL_GetHint'
++'_SDL_AddHintCallback'.'SDL2.dll'.'SDL_AddHintCallback'
++'_SDL_DelHintCallback'.'SDL2.dll'.'SDL_DelHintCallback'
++'_SDL_ClearHints'.'SDL2.dll'.'SDL_ClearHints'
++'_SDL_NumJoysticks'.'SDL2.dll'.'SDL_NumJoysticks'
++'_SDL_JoystickNameForIndex'.'SDL2.dll'.'SDL_JoystickNameForIndex'
++'_SDL_JoystickOpen'.'SDL2.dll'.'SDL_JoystickOpen'
++'_SDL_JoystickName'.'SDL2.dll'.'SDL_JoystickName'
++'_SDL_JoystickGetDeviceGUID'.'SDL2.dll'.'SDL_JoystickGetDeviceGUID'
++'_SDL_JoystickGetGUID'.'SDL2.dll'.'SDL_JoystickGetGUID'
++'_SDL_JoystickGetGUIDString'.'SDL2.dll'.'SDL_JoystickGetGUIDString'
++'_SDL_JoystickGetGUIDFromString'.'SDL2.dll'.'SDL_JoystickGetGUIDFromString'
++'_SDL_JoystickGetAttached'.'SDL2.dll'.'SDL_JoystickGetAttached'
++'_SDL_JoystickInstanceID'.'SDL2.dll'.'SDL_JoystickInstanceID'
++'_SDL_JoystickNumAxes'.'SDL2.dll'.'SDL_JoystickNumAxes'
++'_SDL_JoystickNumBalls'.'SDL2.dll'.'SDL_JoystickNumBalls'
++'_SDL_JoystickNumHats'.'SDL2.dll'.'SDL_JoystickNumHats'
++'_SDL_JoystickNumButtons'.'SDL2.dll'.'SDL_JoystickNumButtons'
++'_SDL_JoystickUpdate'.'SDL2.dll'.'SDL_JoystickUpdate'
++'_SDL_JoystickEventState'.'SDL2.dll'.'SDL_JoystickEventState'
++'_SDL_JoystickGetAxis'.'SDL2.dll'.'SDL_JoystickGetAxis'
++'_SDL_JoystickGetHat'.'SDL2.dll'.'SDL_JoystickGetHat'
++'_SDL_JoystickGetBall'.'SDL2.dll'.'SDL_JoystickGetBall'
++'_SDL_JoystickGetButton'.'SDL2.dll'.'SDL_JoystickGetButton'
++'_SDL_JoystickClose'.'SDL2.dll'.'SDL_JoystickClose'
++'_SDL_GetKeyboardFocus'.'SDL2.dll'.'SDL_GetKeyboardFocus'
++'_SDL_GetKeyboardState'.'SDL2.dll'.'SDL_GetKeyboardState'
++'_SDL_GetModState'.'SDL2.dll'.'SDL_GetModState'
++'_SDL_SetModState'.'SDL2.dll'.'SDL_SetModState'
++'_SDL_GetKeyFromScancode'.'SDL2.dll'.'SDL_GetKeyFromScancode'
++'_SDL_GetScancodeFromKey'.'SDL2.dll'.'SDL_GetScancodeFromKey'
++'_SDL_GetScancodeName'.'SDL2.dll'.'SDL_GetScancodeName'
++'_SDL_GetScancodeFromName'.'SDL2.dll'.'SDL_GetScancodeFromName'
++'_SDL_GetKeyName'.'SDL2.dll'.'SDL_GetKeyName'
++'_SDL_GetKeyFromName'.'SDL2.dll'.'SDL_GetKeyFromName'
++'_SDL_StartTextInput'.'SDL2.dll'.'SDL_StartTextInput'
++'_SDL_IsTextInputActive'.'SDL2.dll'.'SDL_IsTextInputActive'
++'_SDL_StopTextInput'.'SDL2.dll'.'SDL_StopTextInput'
++'_SDL_SetTextInputRect'.'SDL2.dll'.'SDL_SetTextInputRect'
++'_SDL_HasScreenKeyboardSupport'.'SDL2.dll'.'SDL_HasScreenKeyboardSupport'
++'_SDL_IsScreenKeyboardShown'.'SDL2.dll'.'SDL_IsScreenKeyboardShown'
++'_SDL_LoadObject'.'SDL2.dll'.'SDL_LoadObject'
++'_SDL_LoadFunction'.'SDL2.dll'.'SDL_LoadFunction'
++'_SDL_UnloadObject'.'SDL2.dll'.'SDL_UnloadObject'
++'_SDL_LogSetAllPriority'.'SDL2.dll'.'SDL_LogSetAllPriority'
++'_SDL_LogSetPriority'.'SDL2.dll'.'SDL_LogSetPriority'
++'_SDL_LogGetPriority'.'SDL2.dll'.'SDL_LogGetPriority'
++'_SDL_LogResetPriorities'.'SDL2.dll'.'SDL_LogResetPriorities'
++'_SDL_LogMessageV'.'SDL2.dll'.'SDL_LogMessageV'
++'_SDL_LogGetOutputFunction'.'SDL2.dll'.'SDL_LogGetOutputFunction'
++'_SDL_LogSetOutputFunction'.'SDL2.dll'.'SDL_LogSetOutputFunction'
++'_SDL_SetMainReady'.'SDL2.dll'.'SDL_SetMainReady'
++'_SDL_ShowMessageBox'.'SDL2.dll'.'SDL_ShowMessageBox'
++'_SDL_ShowSimpleMessageBox'.'SDL2.dll'.'SDL_ShowSimpleMessageBox'
++'_SDL_GetMouseFocus'.'SDL2.dll'.'SDL_GetMouseFocus'
++'_SDL_GetMouseState'.'SDL2.dll'.'SDL_GetMouseState'
++'_SDL_GetRelativeMouseState'.'SDL2.dll'.'SDL_GetRelativeMouseState'
++'_SDL_WarpMouseInWindow'.'SDL2.dll'.'SDL_WarpMouseInWindow'
++'_SDL_SetRelativeMouseMode'.'SDL2.dll'.'SDL_SetRelativeMouseMode'
++'_SDL_GetRelativeMouseMode'.'SDL2.dll'.'SDL_GetRelativeMouseMode'
++'_SDL_CreateCursor'.'SDL2.dll'.'SDL_CreateCursor'
++'_SDL_CreateColorCursor'.'SDL2.dll'.'SDL_CreateColorCursor'
++'_SDL_CreateSystemCursor'.'SDL2.dll'.'SDL_CreateSystemCursor'
++'_SDL_SetCursor'.'SDL2.dll'.'SDL_SetCursor'
++'_SDL_GetCursor'.'SDL2.dll'.'SDL_GetCursor'
++'_SDL_GetDefaultCursor'.'SDL2.dll'.'SDL_GetDefaultCursor'
++'_SDL_FreeCursor'.'SDL2.dll'.'SDL_FreeCursor'
++'_SDL_ShowCursor'.'SDL2.dll'.'SDL_ShowCursor'
++'_SDL_CreateMutex'.'SDL2.dll'.'SDL_CreateMutex'
++'_SDL_LockMutex'.'SDL2.dll'.'SDL_LockMutex'
++'_SDL_TryLockMutex'.'SDL2.dll'.'SDL_TryLockMutex'
++'_SDL_UnlockMutex'.'SDL2.dll'.'SDL_UnlockMutex'
++'_SDL_DestroyMutex'.'SDL2.dll'.'SDL_DestroyMutex'
++'_SDL_CreateSemaphore'.'SDL2.dll'.'SDL_CreateSemaphore'
++'_SDL_DestroySemaphore'.'SDL2.dll'.'SDL_DestroySemaphore'
++'_SDL_SemWait'.'SDL2.dll'.'SDL_SemWait'
++'_SDL_SemTryWait'.'SDL2.dll'.'SDL_SemTryWait'
++'_SDL_SemWaitTimeout'.'SDL2.dll'.'SDL_SemWaitTimeout'
++'_SDL_SemPost'.'SDL2.dll'.'SDL_SemPost'
++'_SDL_SemValue'.'SDL2.dll'.'SDL_SemValue'
++'_SDL_CreateCond'.'SDL2.dll'.'SDL_CreateCond'
++'_SDL_DestroyCond'.'SDL2.dll'.'SDL_DestroyCond'
++'_SDL_CondSignal'.'SDL2.dll'.'SDL_CondSignal'
++'_SDL_CondBroadcast'.'SDL2.dll'.'SDL_CondBroadcast'
++'_SDL_CondWait'.'SDL2.dll'.'SDL_CondWait'
++'_SDL_CondWaitTimeout'.'SDL2.dll'.'SDL_CondWaitTimeout'
++'_SDL_GetPixelFormatName'.'SDL2.dll'.'SDL_GetPixelFormatName'
++'_SDL_PixelFormatEnumToMasks'.'SDL2.dll'.'SDL_PixelFormatEnumToMasks'
++'_SDL_MasksToPixelFormatEnum'.'SDL2.dll'.'SDL_MasksToPixelFormatEnum'
++'_SDL_AllocFormat'.'SDL2.dll'.'SDL_AllocFormat'
++'_SDL_FreeFormat'.'SDL2.dll'.'SDL_FreeFormat'
++'_SDL_AllocPalette'.'SDL2.dll'.'SDL_AllocPalette'
++'_SDL_SetPixelFormatPalette'.'SDL2.dll'.'SDL_SetPixelFormatPalette'
++'_SDL_SetPaletteColors'.'SDL2.dll'.'SDL_SetPaletteColors'
++'_SDL_FreePalette'.'SDL2.dll'.'SDL_FreePalette'
++'_SDL_MapRGB'.'SDL2.dll'.'SDL_MapRGB'
++'_SDL_MapRGBA'.'SDL2.dll'.'SDL_MapRGBA'
++'_SDL_GetRGB'.'SDL2.dll'.'SDL_GetRGB'
++'_SDL_GetRGBA'.'SDL2.dll'.'SDL_GetRGBA'
++'_SDL_CalculateGammaRamp'.'SDL2.dll'.'SDL_CalculateGammaRamp'
++'_SDL_GetPlatform'.'SDL2.dll'.'SDL_GetPlatform'
++'_SDL_GetPowerInfo'.'SDL2.dll'.'SDL_GetPowerInfo'
++'_SDL_HasIntersection'.'SDL2.dll'.'SDL_HasIntersection'
++'_SDL_IntersectRect'.'SDL2.dll'.'SDL_IntersectRect'
++'_SDL_UnionRect'.'SDL2.dll'.'SDL_UnionRect'
++'_SDL_EnclosePoints'.'SDL2.dll'.'SDL_EnclosePoints'
++'_SDL_IntersectRectAndLine'.'SDL2.dll'.'SDL_IntersectRectAndLine'
++'_SDL_GetNumRenderDrivers'.'SDL2.dll'.'SDL_GetNumRenderDrivers'
++'_SDL_GetRenderDriverInfo'.'SDL2.dll'.'SDL_GetRenderDriverInfo'
++'_SDL_CreateWindowAndRenderer'.'SDL2.dll'.'SDL_CreateWindowAndRenderer'
++'_SDL_CreateRenderer'.'SDL2.dll'.'SDL_CreateRenderer'
++'_SDL_CreateSoftwareRenderer'.'SDL2.dll'.'SDL_CreateSoftwareRenderer'
++'_SDL_GetRenderer'.'SDL2.dll'.'SDL_GetRenderer'
++'_SDL_GetRendererInfo'.'SDL2.dll'.'SDL_GetRendererInfo'
++'_SDL_GetRendererOutputSize'.'SDL2.dll'.'SDL_GetRendererOutputSize'
++'_SDL_CreateTexture'.'SDL2.dll'.'SDL_CreateTexture'
++'_SDL_CreateTextureFromSurface'.'SDL2.dll'.'SDL_CreateTextureFromSurface'
++'_SDL_QueryTexture'.'SDL2.dll'.'SDL_QueryTexture'
++'_SDL_SetTextureColorMod'.'SDL2.dll'.'SDL_SetTextureColorMod'
++'_SDL_GetTextureColorMod'.'SDL2.dll'.'SDL_GetTextureColorMod'
++'_SDL_SetTextureAlphaMod'.'SDL2.dll'.'SDL_SetTextureAlphaMod'
++'_SDL_GetTextureAlphaMod'.'SDL2.dll'.'SDL_GetTextureAlphaMod'
++'_SDL_SetTextureBlendMode'.'SDL2.dll'.'SDL_SetTextureBlendMode'
++'_SDL_GetTextureBlendMode'.'SDL2.dll'.'SDL_GetTextureBlendMode'
++'_SDL_UpdateTexture'.'SDL2.dll'.'SDL_UpdateTexture'
++'_SDL_UpdateYUVTexture'.'SDL2.dll'.'SDL_UpdateYUVTexture'
++'_SDL_LockTexture'.'SDL2.dll'.'SDL_LockTexture'
++'_SDL_UnlockTexture'.'SDL2.dll'.'SDL_UnlockTexture'
++'_SDL_RenderTargetSupported'.'SDL2.dll'.'SDL_RenderTargetSupported'
++'_SDL_SetRenderTarget'.'SDL2.dll'.'SDL_SetRenderTarget'
++'_SDL_GetRenderTarget'.'SDL2.dll'.'SDL_GetRenderTarget'
++'_SDL_RenderSetLogicalSize'.'SDL2.dll'.'SDL_RenderSetLogicalSize'
++'_SDL_RenderGetLogicalSize'.'SDL2.dll'.'SDL_RenderGetLogicalSize'
++'_SDL_RenderSetViewport'.'SDL2.dll'.'SDL_RenderSetViewport'
++'_SDL_RenderGetViewport'.'SDL2.dll'.'SDL_RenderGetViewport'
++'_SDL_RenderSetClipRect'.'SDL2.dll'.'SDL_RenderSetClipRect'
++'_SDL_RenderGetClipRect'.'SDL2.dll'.'SDL_RenderGetClipRect'
++'_SDL_RenderSetScale'.'SDL2.dll'.'SDL_RenderSetScale'
++'_SDL_RenderGetScale'.'SDL2.dll'.'SDL_RenderGetScale'
++'_SDL_SetRenderDrawColor'.'SDL2.dll'.'SDL_SetRenderDrawColor'
++'_SDL_GetRenderDrawColor'.'SDL2.dll'.'SDL_GetRenderDrawColor'
++'_SDL_SetRenderDrawBlendMode'.'SDL2.dll'.'SDL_SetRenderDrawBlendMode'
++'_SDL_GetRenderDrawBlendMode'.'SDL2.dll'.'SDL_GetRenderDrawBlendMode'
++'_SDL_RenderClear'.'SDL2.dll'.'SDL_RenderClear'
++'_SDL_RenderDrawPoint'.'SDL2.dll'.'SDL_RenderDrawPoint'
++'_SDL_RenderDrawPoints'.'SDL2.dll'.'SDL_RenderDrawPoints'
++'_SDL_RenderDrawLine'.'SDL2.dll'.'SDL_RenderDrawLine'
++'_SDL_RenderDrawLines'.'SDL2.dll'.'SDL_RenderDrawLines'
++'_SDL_RenderDrawRect'.'SDL2.dll'.'SDL_RenderDrawRect'
++'_SDL_RenderDrawRects'.'SDL2.dll'.'SDL_RenderDrawRects'
++'_SDL_RenderFillRect'.'SDL2.dll'.'SDL_RenderFillRect'
++'_SDL_RenderFillRects'.'SDL2.dll'.'SDL_RenderFillRects'
++'_SDL_RenderCopy'.'SDL2.dll'.'SDL_RenderCopy'
++'_SDL_RenderCopyEx'.'SDL2.dll'.'SDL_RenderCopyEx'
++'_SDL_RenderReadPixels'.'SDL2.dll'.'SDL_RenderReadPixels'
++'_SDL_RenderPresent'.'SDL2.dll'.'SDL_RenderPresent'
++'_SDL_DestroyTexture'.'SDL2.dll'.'SDL_DestroyTexture'
++'_SDL_DestroyRenderer'.'SDL2.dll'.'SDL_DestroyRenderer'
++'_SDL_GL_BindTexture'.'SDL2.dll'.'SDL_GL_BindTexture'
++'_SDL_GL_UnbindTexture'.'SDL2.dll'.'SDL_GL_UnbindTexture'
++'_SDL_RWFromFile'.'SDL2.dll'.'SDL_RWFromFile'
++'_SDL_RWFromMem'.'SDL2.dll'.'SDL_RWFromMem'
++'_SDL_RWFromConstMem'.'SDL2.dll'.'SDL_RWFromConstMem'
++'_SDL_AllocRW'.'SDL2.dll'.'SDL_AllocRW'
++'_SDL_FreeRW'.'SDL2.dll'.'SDL_FreeRW'
++'_SDL_ReadU8'.'SDL2.dll'.'SDL_ReadU8'
++'_SDL_ReadLE16'.'SDL2.dll'.'SDL_ReadLE16'
++'_SDL_ReadBE16'.'SDL2.dll'.'SDL_ReadBE16'
++'_SDL_ReadLE32'.'SDL2.dll'.'SDL_ReadLE32'
++'_SDL_ReadBE32'.'SDL2.dll'.'SDL_ReadBE32'
++'_SDL_ReadLE64'.'SDL2.dll'.'SDL_ReadLE64'
++'_SDL_ReadBE64'.'SDL2.dll'.'SDL_ReadBE64'
++'_SDL_WriteU8'.'SDL2.dll'.'SDL_WriteU8'
++'_SDL_WriteLE16'.'SDL2.dll'.'SDL_WriteLE16'
++'_SDL_WriteBE16'.'SDL2.dll'.'SDL_WriteBE16'
++'_SDL_WriteLE32'.'SDL2.dll'.'SDL_WriteLE32'
++'_SDL_WriteBE32'.'SDL2.dll'.'SDL_WriteBE32'
++'_SDL_WriteLE64'.'SDL2.dll'.'SDL_WriteLE64'
++'_SDL_WriteBE64'.'SDL2.dll'.'SDL_WriteBE64'
++'_SDL_CreateShapedWindow'.'SDL2.dll'.'SDL_CreateShapedWindow'
++'_SDL_IsShapedWindow'.'SDL2.dll'.'SDL_IsShapedWindow'
++'_SDL_SetWindowShape'.'SDL2.dll'.'SDL_SetWindowShape'
++'_SDL_GetShapedWindowMode'.'SDL2.dll'.'SDL_GetShapedWindowMode'
++'_SDL_malloc'.'SDL2.dll'.'SDL_malloc'
++'_SDL_calloc'.'SDL2.dll'.'SDL_calloc'
++'_SDL_realloc'.'SDL2.dll'.'SDL_realloc'
++'_SDL_free'.'SDL2.dll'.'SDL_free'
++'_SDL_getenv'.'SDL2.dll'.'SDL_getenv'
++'_SDL_setenv'.'SDL2.dll'.'SDL_setenv'
++'_SDL_qsort'.'SDL2.dll'.'SDL_qsort'
++'_SDL_abs'.'SDL2.dll'.'SDL_abs'
++'_SDL_isdigit'.'SDL2.dll'.'SDL_isdigit'
++'_SDL_isspace'.'SDL2.dll'.'SDL_isspace'
++'_SDL_toupper'.'SDL2.dll'.'SDL_toupper'
++'_SDL_tolower'.'SDL2.dll'.'SDL_tolower'
++'_SDL_memset'.'SDL2.dll'.'SDL_memset'
++'_SDL_memcpy'.'SDL2.dll'.'SDL_memcpy'
++'_SDL_memmove'.'SDL2.dll'.'SDL_memmove'
++'_SDL_memcmp'.'SDL2.dll'.'SDL_memcmp'
++'_SDL_wcslen'.'SDL2.dll'.'SDL_wcslen'
++'_SDL_wcslcpy'.'SDL2.dll'.'SDL_wcslcpy'
++'_SDL_wcslcat'.'SDL2.dll'.'SDL_wcslcat'
++'_SDL_strlen'.'SDL2.dll'.'SDL_strlen'
++'_SDL_strlcpy'.'SDL2.dll'.'SDL_strlcpy'
++'_SDL_utf8strlcpy'.'SDL2.dll'.'SDL_utf8strlcpy'
++'_SDL_strlcat'.'SDL2.dll'.'SDL_strlcat'
++'_SDL_strdup'.'SDL2.dll'.'SDL_strdup'
++'_SDL_strrev'.'SDL2.dll'.'SDL_strrev'
++'_SDL_strupr'.'SDL2.dll'.'SDL_strupr'
++'_SDL_strlwr'.'SDL2.dll'.'SDL_strlwr'
++'_SDL_strchr'.'SDL2.dll'.'SDL_strchr'
++'_SDL_strrchr'.'SDL2.dll'.'SDL_strrchr'
++'_SDL_strstr'.'SDL2.dll'.'SDL_strstr'
++'_SDL_itoa'.'SDL2.dll'.'SDL_itoa'
++'_SDL_uitoa'.'SDL2.dll'.'SDL_uitoa'
++'_SDL_ltoa'.'SDL2.dll'.'SDL_ltoa'
++'_SDL_ultoa'.'SDL2.dll'.'SDL_ultoa'
++'_SDL_lltoa'.'SDL2.dll'.'SDL_lltoa'
++'_SDL_ulltoa'.'SDL2.dll'.'SDL_ulltoa'
++'_SDL_atoi'.'SDL2.dll'.'SDL_atoi'
++'_SDL_atof'.'SDL2.dll'.'SDL_atof'
++'_SDL_strtol'.'SDL2.dll'.'SDL_strtol'
++'_SDL_strtoul'.'SDL2.dll'.'SDL_strtoul'
++'_SDL_strtoll'.'SDL2.dll'.'SDL_strtoll'
++'_SDL_strtoull'.'SDL2.dll'.'SDL_strtoull'
++'_SDL_strtod'.'SDL2.dll'.'SDL_strtod'
++'_SDL_strcmp'.'SDL2.dll'.'SDL_strcmp'
++'_SDL_strncmp'.'SDL2.dll'.'SDL_strncmp'
++'_SDL_strcasecmp'.'SDL2.dll'.'SDL_strcasecmp'
++'_SDL_strncasecmp'.'SDL2.dll'.'SDL_strncasecmp'
++'_SDL_vsnprintf'.'SDL2.dll'.'SDL_vsnprintf'
++'_SDL_acos'.'SDL2.dll'.'SDL_acos'
++'_SDL_asin'.'SDL2.dll'.'SDL_asin'
++'_SDL_atan'.'SDL2.dll'.'SDL_atan'
++'_SDL_atan2'.'SDL2.dll'.'SDL_atan2'
++'_SDL_ceil'.'SDL2.dll'.'SDL_ceil'
++'_SDL_copysign'.'SDL2.dll'.'SDL_copysign'
++'_SDL_cos'.'SDL2.dll'.'SDL_cos'
++'_SDL_cosf'.'SDL2.dll'.'SDL_cosf'
++'_SDL_fabs'.'SDL2.dll'.'SDL_fabs'
++'_SDL_floor'.'SDL2.dll'.'SDL_floor'
++'_SDL_log'.'SDL2.dll'.'SDL_log'
++'_SDL_pow'.'SDL2.dll'.'SDL_pow'
++'_SDL_scalbn'.'SDL2.dll'.'SDL_scalbn'
++'_SDL_sin'.'SDL2.dll'.'SDL_sin'
++'_SDL_sinf'.'SDL2.dll'.'SDL_sinf'
++'_SDL_sqrt'.'SDL2.dll'.'SDL_sqrt'
++'_SDL_iconv_open'.'SDL2.dll'.'SDL_iconv_open'
++'_SDL_iconv_close'.'SDL2.dll'.'SDL_iconv_close'
++'_SDL_iconv'.'SDL2.dll'.'SDL_iconv'
++'_SDL_iconv_string'.'SDL2.dll'.'SDL_iconv_string'
++'_SDL_CreateRGBSurface'.'SDL2.dll'.'SDL_CreateRGBSurface'
++'_SDL_CreateRGBSurfaceFrom'.'SDL2.dll'.'SDL_CreateRGBSurfaceFrom'
++'_SDL_FreeSurface'.'SDL2.dll'.'SDL_FreeSurface'
++'_SDL_SetSurfacePalette'.'SDL2.dll'.'SDL_SetSurfacePalette'
++'_SDL_LockSurface'.'SDL2.dll'.'SDL_LockSurface'
++'_SDL_UnlockSurface'.'SDL2.dll'.'SDL_UnlockSurface'
++'_SDL_LoadBMP_RW'.'SDL2.dll'.'SDL_LoadBMP_RW'
++'_SDL_SaveBMP_RW'.'SDL2.dll'.'SDL_SaveBMP_RW'
++'_SDL_SetSurfaceRLE'.'SDL2.dll'.'SDL_SetSurfaceRLE'
++'_SDL_SetColorKey'.'SDL2.dll'.'SDL_SetColorKey'
++'_SDL_GetColorKey'.'SDL2.dll'.'SDL_GetColorKey'
++'_SDL_SetSurfaceColorMod'.'SDL2.dll'.'SDL_SetSurfaceColorMod'
++'_SDL_GetSurfaceColorMod'.'SDL2.dll'.'SDL_GetSurfaceColorMod'
++'_SDL_SetSurfaceAlphaMod'.'SDL2.dll'.'SDL_SetSurfaceAlphaMod'
++'_SDL_GetSurfaceAlphaMod'.'SDL2.dll'.'SDL_GetSurfaceAlphaMod'
++'_SDL_SetSurfaceBlendMode'.'SDL2.dll'.'SDL_SetSurfaceBlendMode'
++'_SDL_GetSurfaceBlendMode'.'SDL2.dll'.'SDL_GetSurfaceBlendMode'
++'_SDL_SetClipRect'.'SDL2.dll'.'SDL_SetClipRect'
++'_SDL_GetClipRect'.'SDL2.dll'.'SDL_GetClipRect'
++'_SDL_ConvertSurface'.'SDL2.dll'.'SDL_ConvertSurface'
++'_SDL_ConvertSurfaceFormat'.'SDL2.dll'.'SDL_ConvertSurfaceFormat'
++'_SDL_ConvertPixels'.'SDL2.dll'.'SDL_ConvertPixels'
++'_SDL_FillRect'.'SDL2.dll'.'SDL_FillRect'
++'_SDL_FillRects'.'SDL2.dll'.'SDL_FillRects'
++'_SDL_UpperBlit'.'SDL2.dll'.'SDL_UpperBlit'
++'_SDL_LowerBlit'.'SDL2.dll'.'SDL_LowerBlit'
++'_SDL_SoftStretch'.'SDL2.dll'.'SDL_SoftStretch'
++'_SDL_UpperBlitScaled'.'SDL2.dll'.'SDL_UpperBlitScaled'
++'_SDL_LowerBlitScaled'.'SDL2.dll'.'SDL_LowerBlitScaled'
++'_SDL_GetWindowWMInfo'.'SDL2.dll'.'SDL_GetWindowWMInfo'
++'_SDL_GetThreadName'.'SDL2.dll'.'SDL_GetThreadName'
++'_SDL_ThreadID'.'SDL2.dll'.'SDL_ThreadID'
++'_SDL_GetThreadID'.'SDL2.dll'.'SDL_GetThreadID'
++'_SDL_SetThreadPriority'.'SDL2.dll'.'SDL_SetThreadPriority'
++'_SDL_WaitThread'.'SDL2.dll'.'SDL_WaitThread'
++'_SDL_DetachThread'.'SDL2.dll'.'SDL_DetachThread'
++'_SDL_TLSCreate'.'SDL2.dll'.'SDL_TLSCreate'
++'_SDL_TLSGet'.'SDL2.dll'.'SDL_TLSGet'
++'_SDL_TLSSet'.'SDL2.dll'.'SDL_TLSSet'
++'_SDL_GetTicks'.'SDL2.dll'.'SDL_GetTicks'
++'_SDL_GetPerformanceCounter'.'SDL2.dll'.'SDL_GetPerformanceCounter'
++'_SDL_GetPerformanceFrequency'.'SDL2.dll'.'SDL_GetPerformanceFrequency'
++'_SDL_Delay'.'SDL2.dll'.'SDL_Delay'
++'_SDL_AddTimer'.'SDL2.dll'.'SDL_AddTimer'
++'_SDL_RemoveTimer'.'SDL2.dll'.'SDL_RemoveTimer'
++'_SDL_GetNumTouchDevices'.'SDL2.dll'.'SDL_GetNumTouchDevices'
++'_SDL_GetTouchDevice'.'SDL2.dll'.'SDL_GetTouchDevice'
++'_SDL_GetNumTouchFingers'.'SDL2.dll'.'SDL_GetNumTouchFingers'
++'_SDL_GetTouchFinger'.'SDL2.dll'.'SDL_GetTouchFinger'
++'_SDL_GetVersion'.'SDL2.dll'.'SDL_GetVersion'
++'_SDL_GetRevision'.'SDL2.dll'.'SDL_GetRevision'
++'_SDL_GetRevisionNumber'.'SDL2.dll'.'SDL_GetRevisionNumber'
++'_SDL_GetNumVideoDrivers'.'SDL2.dll'.'SDL_GetNumVideoDrivers'
++'_SDL_GetVideoDriver'.'SDL2.dll'.'SDL_GetVideoDriver'
++'_SDL_VideoInit'.'SDL2.dll'.'SDL_VideoInit'
++'_SDL_VideoQuit'.'SDL2.dll'.'SDL_VideoQuit'
++'_SDL_GetCurrentVideoDriver'.'SDL2.dll'.'SDL_GetCurrentVideoDriver'
++'_SDL_GetNumVideoDisplays'.'SDL2.dll'.'SDL_GetNumVideoDisplays'
++'_SDL_GetDisplayName'.'SDL2.dll'.'SDL_GetDisplayName'
++'_SDL_GetDisplayBounds'.'SDL2.dll'.'SDL_GetDisplayBounds'
++'_SDL_GetDisplayDPI'.'SDL2.dll'.'SDL_GetDisplayDPI'
++'_SDL_GetNumDisplayModes'.'SDL2.dll'.'SDL_GetNumDisplayModes'
++'_SDL_GetDisplayMode'.'SDL2.dll'.'SDL_GetDisplayMode'
++'_SDL_GetDesktopDisplayMode'.'SDL2.dll'.'SDL_GetDesktopDisplayMode'
++'_SDL_GetCurrentDisplayMode'.'SDL2.dll'.'SDL_GetCurrentDisplayMode'
++'_SDL_GetClosestDisplayMode'.'SDL2.dll'.'SDL_GetClosestDisplayMode'
++'_SDL_GetWindowDisplayIndex'.'SDL2.dll'.'SDL_GetWindowDisplayIndex'
++'_SDL_SetWindowDisplayMode'.'SDL2.dll'.'SDL_SetWindowDisplayMode'
++'_SDL_GetWindowDisplayMode'.'SDL2.dll'.'SDL_GetWindowDisplayMode'
++'_SDL_GetWindowPixelFormat'.'SDL2.dll'.'SDL_GetWindowPixelFormat'
++'_SDL_CreateWindow'.'SDL2.dll'.'SDL_CreateWindow'
++'_SDL_CreateWindowFrom'.'SDL2.dll'.'SDL_CreateWindowFrom'
++'_SDL_GetWindowID'.'SDL2.dll'.'SDL_GetWindowID'
++'_SDL_GetWindowFromID'.'SDL2.dll'.'SDL_GetWindowFromID'
++'_SDL_GetWindowFlags'.'SDL2.dll'.'SDL_GetWindowFlags'
++'_SDL_SetWindowTitle'.'SDL2.dll'.'SDL_SetWindowTitle'
++'_SDL_GetWindowTitle'.'SDL2.dll'.'SDL_GetWindowTitle'
++'_SDL_SetWindowIcon'.'SDL2.dll'.'SDL_SetWindowIcon'
++'_SDL_SetWindowData'.'SDL2.dll'.'SDL_SetWindowData'
++'_SDL_GetWindowData'.'SDL2.dll'.'SDL_GetWindowData'
++'_SDL_SetWindowPosition'.'SDL2.dll'.'SDL_SetWindowPosition'
++'_SDL_GetWindowPosition'.'SDL2.dll'.'SDL_GetWindowPosition'
++'_SDL_SetWindowSize'.'SDL2.dll'.'SDL_SetWindowSize'
++'_SDL_GetWindowSize'.'SDL2.dll'.'SDL_GetWindowSize'
++'_SDL_SetWindowMinimumSize'.'SDL2.dll'.'SDL_SetWindowMinimumSize'
++'_SDL_GetWindowMinimumSize'.'SDL2.dll'.'SDL_GetWindowMinimumSize'
++'_SDL_SetWindowMaximumSize'.'SDL2.dll'.'SDL_SetWindowMaximumSize'
++'_SDL_GetWindowMaximumSize'.'SDL2.dll'.'SDL_GetWindowMaximumSize'
++'_SDL_SetWindowBordered'.'SDL2.dll'.'SDL_SetWindowBordered'
++'_SDL_ShowWindow'.'SDL2.dll'.'SDL_ShowWindow'
++'_SDL_HideWindow'.'SDL2.dll'.'SDL_HideWindow'
++'_SDL_RaiseWindow'.'SDL2.dll'.'SDL_RaiseWindow'
++'_SDL_MaximizeWindow'.'SDL2.dll'.'SDL_MaximizeWindow'
++'_SDL_MinimizeWindow'.'SDL2.dll'.'SDL_MinimizeWindow'
++'_SDL_RestoreWindow'.'SDL2.dll'.'SDL_RestoreWindow'
++'_SDL_SetWindowFullscreen'.'SDL2.dll'.'SDL_SetWindowFullscreen'
++'_SDL_GetWindowSurface'.'SDL2.dll'.'SDL_GetWindowSurface'
++'_SDL_UpdateWindowSurface'.'SDL2.dll'.'SDL_UpdateWindowSurface'
++'_SDL_UpdateWindowSurfaceRects'.'SDL2.dll'.'SDL_UpdateWindowSurfaceRects'
++'_SDL_SetWindowGrab'.'SDL2.dll'.'SDL_SetWindowGrab'
++'_SDL_GetWindowGrab'.'SDL2.dll'.'SDL_GetWindowGrab'
++'_SDL_SetWindowBrightness'.'SDL2.dll'.'SDL_SetWindowBrightness'
++'_SDL_GetWindowBrightness'.'SDL2.dll'.'SDL_GetWindowBrightness'
++'_SDL_SetWindowGammaRamp'.'SDL2.dll'.'SDL_SetWindowGammaRamp'
++'_SDL_GetWindowGammaRamp'.'SDL2.dll'.'SDL_GetWindowGammaRamp'
++'_SDL_DestroyWindow'.'SDL2.dll'.'SDL_DestroyWindow'
++'_SDL_IsScreenSaverEnabled'.'SDL2.dll'.'SDL_IsScreenSaverEnabled'
++'_SDL_EnableScreenSaver'.'SDL2.dll'.'SDL_EnableScreenSaver'
++'_SDL_DisableScreenSaver'.'SDL2.dll'.'SDL_DisableScreenSaver'
++'_SDL_GL_LoadLibrary'.'SDL2.dll'.'SDL_GL_LoadLibrary'
++'_SDL_GL_GetProcAddress'.'SDL2.dll'.'SDL_GL_GetProcAddress'
++'_SDL_GL_UnloadLibrary'.'SDL2.dll'.'SDL_GL_UnloadLibrary'
++'_SDL_GL_ExtensionSupported'.'SDL2.dll'.'SDL_GL_ExtensionSupported'
++'_SDL_GL_SetAttribute'.'SDL2.dll'.'SDL_GL_SetAttribute'
++'_SDL_GL_GetAttribute'.'SDL2.dll'.'SDL_GL_GetAttribute'
++'_SDL_GL_CreateContext'.'SDL2.dll'.'SDL_GL_CreateContext'
++'_SDL_GL_MakeCurrent'.'SDL2.dll'.'SDL_GL_MakeCurrent'
++'_SDL_GL_GetCurrentWindow'.'SDL2.dll'.'SDL_GL_GetCurrentWindow'
++'_SDL_GL_GetCurrentContext'.'SDL2.dll'.'SDL_GL_GetCurrentContext'
++'_SDL_GL_GetDrawableSize'.'SDL2.dll'.'SDL_GL_GetDrawableSize'
++'_SDL_GL_SetSwapInterval'.'SDL2.dll'.'SDL_GL_SetSwapInterval'
++'_SDL_GL_GetSwapInterval'.'SDL2.dll'.'SDL_GL_GetSwapInterval'
++'_SDL_GL_SwapWindow'.'SDL2.dll'.'SDL_GL_SwapWindow'
++'_SDL_GL_DeleteContext'.'SDL2.dll'.'SDL_GL_DeleteContext'
++'_SDL_vsscanf'.'SDL2.dll'.'SDL_vsscanf'
++'_SDL_GameControllerAddMappingsFromRW'.'SDL2.dll'.'SDL_GameControllerAddMappingsFromRW'
++'_SDL_GL_ResetAttributes'.'SDL2.dll'.'SDL_GL_ResetAttributes'
++'_SDL_HasAVX'.'SDL2.dll'.'SDL_HasAVX'
++'_SDL_GetDefaultAssertionHandler'.'SDL2.dll'.'SDL_GetDefaultAssertionHandler'
++'_SDL_GetAssertionHandler'.'SDL2.dll'.'SDL_GetAssertionHandler'
++'_SDL_DXGIGetOutputInfo'.'SDL2.dll'.'SDL_DXGIGetOutputInfo'
++'_SDL_RenderIsClipEnabled'.'SDL2.dll'.'SDL_RenderIsClipEnabled'
# ++'_SDL_WinRTRunApp'.'SDL2.dll'.'SDL_WinRTRunApp'
++'_SDL_WarpMouseGlobal'.'SDL2.dll'.'SDL_WarpMouseGlobal'
# ++'_SDL_WinRTGetFSPathUNICODE'.'SDL2.dll'.'SDL_WinRTGetFSPathUNICODE'
# ++'_SDL_WinRTGetFSPathUTF8'.'SDL2.dll'.'SDL_WinRTGetFSPathUTF8'
++'_SDL_sqrtf'.'SDL2.dll'.'SDL_sqrtf'
++'_SDL_tan'.'SDL2.dll'.'SDL_tan'
++'_SDL_tanf'.'SDL2.dll'.'SDL_tanf'
++'_SDL_CaptureMouse'.'SDL2.dll'.'SDL_CaptureMouse'
++'_SDL_SetWindowHitTest'.'SDL2.dll'.'SDL_SetWindowHitTest'
++'_SDL_GetGlobalMouseState'.'SDL2.dll'.'SDL_GetGlobalMouseState'
++'_SDL_HasAVX2'.'SDL2.dll'.'SDL_HasAVX2'
++'_SDL_QueueAudio'.'SDL2.dll'.'SDL_QueueAudio'
++'_SDL_GetQueuedAudioSize'.'SDL2.dll'.'SDL_GetQueuedAudioSize'
++'_SDL_ClearQueuedAudio'.'SDL2.dll'.'SDL_ClearQueuedAudio'
++'_SDL_GetGrabbedWindow'.'SDL2.dll'.'SDL_GetGrabbedWindow'
++'_SDL_SetWindowsMessageHook'.'SDL2.dll'.'SDL_SetWindowsMessageHook'
++'_SDL_JoystickCurrentPowerLevel'.'SDL2.dll'.'SDL_JoystickCurrentPowerLevel'
++'_SDL_GameControllerFromInstanceID'.'SDL2.dll'.'SDL_GameControllerFromInstanceID'
++'_SDL_JoystickFromInstanceID'.'SDL2.dll'.'SDL_JoystickFromInstanceID'
++'_SDL_GetDisplayUsableBounds'.'SDL2.dll'.'SDL_GetDisplayUsableBounds'
++'_SDL_GetWindowBordersSize'.'SDL2.dll'.'SDL_GetWindowBordersSize'
++'_SDL_SetWindowOpacity'.'SDL2.dll'.'SDL_SetWindowOpacity'
++'_SDL_GetWindowOpacity'.'SDL2.dll'.'SDL_GetWindowOpacity'
++'_SDL_SetWindowInputFocus'.'SDL2.dll'.'SDL_SetWindowInputFocus'
++'_SDL_SetWindowModalFor'.'SDL2.dll'.'SDL_SetWindowModalFor'
++'_SDL_RenderSetIntegerScale'.'SDL2.dll'.'SDL_RenderSetIntegerScale'
++'_SDL_RenderGetIntegerScale'.'SDL2.dll'.'SDL_RenderGetIntegerScale'
++'_SDL_DequeueAudio'.'SDL2.dll'.'SDL_DequeueAudio'
++'_SDL_SetWindowResizable'.'SDL2.dll'.'SDL_SetWindowResizable'
++'_SDL_CreateRGBSurfaceWithFormat'.'SDL2.dll'.'SDL_CreateRGBSurfaceWithFormat'
++'_SDL_CreateRGBSurfaceWithFormatFrom'.'SDL2.dll'.'SDL_CreateRGBSurfaceWithFormatFrom'
++'_SDL_GetHintBoolean'.'SDL2.dll'.'SDL_GetHintBoolean'
++'_SDL_JoystickGetDeviceVendor'.'SDL2.dll'.'SDL_JoystickGetDeviceVendor'
++'_SDL_JoystickGetDeviceProduct'.'SDL2.dll'.'SDL_JoystickGetDeviceProduct'
++'_SDL_JoystickGetDeviceProductVersion'.'SDL2.dll'.'SDL_JoystickGetDeviceProductVersion'
++'_SDL_JoystickGetVendor'.'SDL2.dll'.'SDL_JoystickGetVendor'
++'_SDL_JoystickGetProduct'.'SDL2.dll'.'SDL_JoystickGetProduct'
++'_SDL_JoystickGetProductVersion'.'SDL2.dll'.'SDL_JoystickGetProductVersion'
++'_SDL_GameControllerGetVendor'.'SDL2.dll'.'SDL_GameControllerGetVendor'
++'_SDL_GameControllerGetProduct'.'SDL2.dll'.'SDL_GameControllerGetProduct'
++'_SDL_GameControllerGetProductVersion'.'SDL2.dll'.'SDL_GameControllerGetProductVersion'
++'_SDL_HasNEON'.'SDL2.dll'.'SDL_HasNEON'
++'_SDL_GameControllerNumMappings'.'SDL2.dll'.'SDL_GameControllerNumMappings'
++'_SDL_GameControllerMappingForIndex'.'SDL2.dll'.'SDL_GameControllerMappingForIndex'
++'_SDL_JoystickGetAxisInitialState'.'SDL2.dll'.'SDL_JoystickGetAxisInitialState'
++'_SDL_JoystickGetDeviceType'.'SDL2.dll'.'SDL_JoystickGetDeviceType'
++'_SDL_JoystickGetType'.'SDL2.dll'.'SDL_JoystickGetType'
++'_SDL_MemoryBarrierReleaseFunction'.'SDL2.dll'.'SDL_MemoryBarrierReleaseFunction'
++'_SDL_MemoryBarrierAcquireFunction'.'SDL2.dll'.'SDL_MemoryBarrierAcquireFunction'
++'_SDL_JoystickGetDeviceInstanceID'.'SDL2.dll'.'SDL_JoystickGetDeviceInstanceID'
++'_SDL_utf8strlen'.'SDL2.dll'.'SDL_utf8strlen'
++'_SDL_LoadFile_RW'.'SDL2.dll'.'SDL_LoadFile_RW'
++'_SDL_wcscmp'.'SDL2.dll'.'SDL_wcscmp'
++'_SDL_ComposeCustomBlendMode'.'SDL2.dll'.'SDL_ComposeCustomBlendMode'
++'_SDL_DuplicateSurface'.'SDL2.dll'.'SDL_DuplicateSurface'
++'_SDL_Vulkan_LoadLibrary'.'SDL2.dll'.'SDL_Vulkan_LoadLibrary'
++'_SDL_Vulkan_GetVkGetInstanceProcAddr'.'SDL2.dll'.'SDL_Vulkan_GetVkGetInstanceProcAddr'
++'_SDL_Vulkan_UnloadLibrary'.'SDL2.dll'.'SDL_Vulkan_UnloadLibrary'
++'_SDL_Vulkan_GetInstanceExtensions'.'SDL2.dll'.'SDL_Vulkan_GetInstanceExtensions'
++'_SDL_Vulkan_CreateSurface'.'SDL2.dll'.'SDL_Vulkan_CreateSurface'
++'_SDL_Vulkan_GetDrawableSize'.'SDL2.dll'.'SDL_Vulkan_GetDrawableSize'
++'_SDL_LockJoysticks'.'SDL2.dll'.'SDL_LockJoysticks'
++'_SDL_UnlockJoysticks'.'SDL2.dll'.'SDL_UnlockJoysticks'
++'_SDL_GetMemoryFunctions'.'SDL2.dll'.'SDL_GetMemoryFunctions'
++'_SDL_SetMemoryFunctions'.'SDL2.dll'.'SDL_SetMemoryFunctions'
++'_SDL_GetNumAllocations'.'SDL2.dll'.'SDL_GetNumAllocations'
++'_SDL_NewAudioStream'.'SDL2.dll'.'SDL_NewAudioStream'
++'_SDL_AudioStreamPut'.'SDL2.dll'.'SDL_AudioStreamPut'
++'_SDL_AudioStreamGet'.'SDL2.dll'.'SDL_AudioStreamGet'
++'_SDL_AudioStreamClear'.'SDL2.dll'.'SDL_AudioStreamClear'
++'_SDL_AudioStreamAvailable'.'SDL2.dll'.'SDL_AudioStreamAvailable'
++'_SDL_FreeAudioStream'.'SDL2.dll'.'SDL_FreeAudioStream'
++'_SDL_AudioStreamFlush'.'SDL2.dll'.'SDL_AudioStreamFlush'
++'_SDL_acosf'.'SDL2.dll'.'SDL_acosf'
++'_SDL_asinf'.'SDL2.dll'.'SDL_asinf'
++'_SDL_atanf'.'SDL2.dll'.'SDL_atanf'
++'_SDL_atan2f'.'SDL2.dll'.'SDL_atan2f'
++'_SDL_ceilf'.'SDL2.dll'.'SDL_ceilf'
++'_SDL_copysignf'.'SDL2.dll'.'SDL_copysignf'
++'_SDL_fabsf'.'SDL2.dll'.'SDL_fabsf'
++'_SDL_floorf'.'SDL2.dll'.'SDL_floorf'
++'_SDL_logf'.'SDL2.dll'.'SDL_logf'
++'_SDL_powf'.'SDL2.dll'.'SDL_powf'
++'_SDL_scalbnf'.'SDL2.dll'.'SDL_scalbnf'
++'_SDL_fmod'.'SDL2.dll'.'SDL_fmod'
++'_SDL_fmodf'.'SDL2.dll'.'SDL_fmodf'
++'_SDL_SetYUVConversionMode'.'SDL2.dll'.'SDL_SetYUVConversionMode'
++'_SDL_GetYUVConversionMode'.'SDL2.dll'.'SDL_GetYUVConversionMode'
++'_SDL_GetYUVConversionModeForResolution'.'SDL2.dll'.'SDL_GetYUVConversionModeForResolution'
++'_SDL_RenderGetMetalLayer'.'SDL2.dll'.'SDL_RenderGetMetalLayer'
++'_SDL_RenderGetMetalCommandEncoder'.'SDL2.dll'.'SDL_RenderGetMetalCommandEncoder'
# ++'_SDL_IsAndroidTV'.'SDL2.dll'.'SDL_IsAndroidTV'
# ++'_SDL_WinRTGetDeviceFamily'.'SDL2.dll'.'SDL_WinRTGetDeviceFamily'
++'_SDL_log10'.'SDL2.dll'.'SDL_log10'
++'_SDL_log10f'.'SDL2.dll'.'SDL_log10f'
++'_SDL_GameControllerMappingForDeviceIndex'.'SDL2.dll'.'SDL_GameControllerMappingForDeviceIndex'
# ++'_SDL_LinuxSetThreadPriority'.'SDL2.dll'.'SDL_LinuxSetThreadPriority'
++'_SDL_HasAVX512F'.'SDL2.dll'.'SDL_HasAVX512F'
# ++'_SDL_IsChromebook'.'SDL2.dll'.'SDL_IsChromebook'
# ++'_SDL_IsDeXMode'.'SDL2.dll'.'SDL_IsDeXMode'
# ++'_SDL_AndroidBackButton'.'SDL2.dll'.'SDL_AndroidBackButton'
++'_SDL_exp'.'SDL2.dll'.'SDL_exp'
++'_SDL_expf'.'SDL2.dll'.'SDL_expf'
++'_SDL_wcsdup'.'SDL2.dll'.'SDL_wcsdup'
++'_SDL_GameControllerRumble'.'SDL2.dll'.'SDL_GameControllerRumble'
++'_SDL_JoystickRumble'.'SDL2.dll'.'SDL_JoystickRumble'
++'_SDL_NumSensors'.'SDL2.dll'.'SDL_NumSensors'
++'_SDL_SensorGetDeviceName'.'SDL2.dll'.'SDL_SensorGetDeviceName'
++'_SDL_SensorGetDeviceType'.'SDL2.dll'.'SDL_SensorGetDeviceType'
++'_SDL_SensorGetDeviceNonPortableType'.'SDL2.dll'.'SDL_SensorGetDeviceNonPortableType'
++'_SDL_SensorGetDeviceInstanceID'.'SDL2.dll'.'SDL_SensorGetDeviceInstanceID'
++'_SDL_SensorOpen'.'SDL2.dll'.'SDL_SensorOpen'
++'_SDL_SensorFromInstanceID'.'SDL2.dll'.'SDL_SensorFromInstanceID'
++'_SDL_SensorGetName'.'SDL2.dll'.'SDL_SensorGetName'
++'_SDL_SensorGetType'.'SDL2.dll'.'SDL_SensorGetType'
++'_SDL_SensorGetNonPortableType'.'SDL2.dll'.'SDL_SensorGetNonPortableType'
++'_SDL_SensorGetInstanceID'.'SDL2.dll'.'SDL_SensorGetInstanceID'
++'_SDL_SensorGetData'.'SDL2.dll'.'SDL_SensorGetData'
++'_SDL_SensorClose'.'SDL2.dll'.'SDL_SensorClose'
++'_SDL_SensorUpdate'.'SDL2.dll'.'SDL_SensorUpdate'
++'_SDL_IsTablet'.'SDL2.dll'.'SDL_IsTablet'
++'_SDL_GetDisplayOrientation'.'SDL2.dll'.'SDL_GetDisplayOrientation'
++'_SDL_HasColorKey'.'SDL2.dll'.'SDL_HasColorKey'
++'_SDL_CreateThreadWithStackSize'.'SDL2.dll'.'SDL_CreateThreadWithStackSize'
++'_SDL_JoystickGetDevicePlayerIndex'.'SDL2.dll'.'SDL_JoystickGetDevicePlayerIndex'
++'_SDL_JoystickGetPlayerIndex'.'SDL2.dll'.'SDL_JoystickGetPlayerIndex'
++'_SDL_GameControllerGetPlayerIndex'.'SDL2.dll'.'SDL_GameControllerGetPlayerIndex'
++'_SDL_RenderFlush'.'SDL2.dll'.'SDL_RenderFlush'
++'_SDL_RenderDrawPointF'.'SDL2.dll'.'SDL_RenderDrawPointF'
++'_SDL_RenderDrawPointsF'.'SDL2.dll'.'SDL_RenderDrawPointsF'
++'_SDL_RenderDrawLineF'.'SDL2.dll'.'SDL_RenderDrawLineF'
++'_SDL_RenderDrawLinesF'.'SDL2.dll'.'SDL_RenderDrawLinesF'
++'_SDL_RenderDrawRectF'.'SDL2.dll'.'SDL_RenderDrawRectF'
++'_SDL_RenderDrawRectsF'.'SDL2.dll'.'SDL_RenderDrawRectsF'
++'_SDL_RenderFillRectF'.'SDL2.dll'.'SDL_RenderFillRectF'
++'_SDL_RenderFillRectsF'.'SDL2.dll'.'SDL_RenderFillRectsF'
++'_SDL_RenderCopyF'.'SDL2.dll'.'SDL_RenderCopyF'
++'_SDL_RenderCopyExF'.'SDL2.dll'.'SDL_RenderCopyExF'
++'_SDL_GetTouchDeviceType'.'SDL2.dll'.'SDL_GetTouchDeviceType'
# ++'_SDL_UIKitRunApp'.'SDL2.dll'.'SDL_UIKitRunApp'
++'_SDL_SIMDGetAlignment'.'SDL2.dll'.'SDL_SIMDGetAlignment'
++'_SDL_SIMDAlloc'.'SDL2.dll'.'SDL_SIMDAlloc'
++'_SDL_SIMDFree'.'SDL2.dll'.'SDL_SIMDFree'
++'_SDL_RWsize'.'SDL2.dll'.'SDL_RWsize'
++'_SDL_RWseek'.'SDL2.dll'.'SDL_RWseek'
++'_SDL_RWtell'.'SDL2.dll'.'SDL_RWtell'
++'_SDL_RWread'.'SDL2.dll'.'SDL_RWread'
++'_SDL_RWwrite'.'SDL2.dll'.'SDL_RWwrite'
++'_SDL_RWclose'.'SDL2.dll'.'SDL_RWclose'
++'_SDL_LoadFile'.'SDL2.dll'.'SDL_LoadFile'
++'_SDL_Metal_CreateView'.'SDL2.dll'.'SDL_Metal_CreateView'
++'_SDL_Metal_DestroyView'.'SDL2.dll'.'SDL_Metal_DestroyView'
++'_SDL_LockTextureToSurface'.'SDL2.dll'.'SDL_LockTextureToSurface'
++'_SDL_HasARMSIMD'.'SDL2.dll'.'SDL_HasARMSIMD'
++'_SDL_strtokr'.'SDL2.dll'.'SDL_strtokr'
++'_SDL_wcsstr'.'SDL2.dll'.'SDL_wcsstr'
++'_SDL_wcsncmp'.'SDL2.dll'.'SDL_wcsncmp'
++'_SDL_GameControllerTypeForIndex'.'SDL2.dll'.'SDL_GameControllerTypeForIndex'
++'_SDL_GameControllerGetType'.'SDL2.dll'.'SDL_GameControllerGetType'
++'_SDL_GameControllerFromPlayerIndex'.'SDL2.dll'.'SDL_GameControllerFromPlayerIndex'
++'_SDL_GameControllerSetPlayerIndex'.'SDL2.dll'.'SDL_GameControllerSetPlayerIndex'
++'_SDL_JoystickFromPlayerIndex'.'SDL2.dll'.'SDL_JoystickFromPlayerIndex'
++'_SDL_JoystickSetPlayerIndex'.'SDL2.dll'.'SDL_JoystickSetPlayerIndex'
++'_SDL_SetTextureScaleMode'.'SDL2.dll'.'SDL_SetTextureScaleMode'
++'_SDL_GetTextureScaleMode'.'SDL2.dll'.'SDL_GetTextureScaleMode'
++'_SDL_OnApplicationWillTerminate'.'SDL2.dll'.'SDL_OnApplicationWillTerminate'
++'_SDL_OnApplicationDidReceiveMemoryWarning'.'SDL2.dll'.'SDL_OnApplicationDidReceiveMemoryWarning'
++'_SDL_OnApplicationWillResignActive'.'SDL2.dll'.'SDL_OnApplicationWillResignActive'
++'_SDL_OnApplicationDidEnterBackground'.'SDL2.dll'.'SDL_OnApplicationDidEnterBackground'
++'_SDL_OnApplicationWillEnterForeground'.'SDL2.dll'.'SDL_OnApplicationWillEnterForeground'
++'_SDL_OnApplicationDidBecomeActive'.'SDL2.dll'.'SDL_OnApplicationDidBecomeActive'
# ++'_SDL_OnApplicationDidChangeStatusBarOrientation'.'SDL2.dll'.'SDL_OnApplicationDidChangeStatusBarOrientation'
# ++'_SDL_GetAndroidSDKVersion'.'SDL2.dll'.'SDL_GetAndroidSDKVersion'
++'_SDL_isupper'.'SDL2.dll'.'SDL_isupper'
++'_SDL_islower'.'SDL2.dll'.'SDL_islower'
++'_SDL_JoystickAttachVirtual'.'SDL2.dll'.'SDL_JoystickAttachVirtual'
++'_SDL_JoystickDetachVirtual'.'SDL2.dll'.'SDL_JoystickDetachVirtual'
++'_SDL_JoystickIsVirtual'.'SDL2.dll'.'SDL_JoystickIsVirtual'
++'_SDL_JoystickSetVirtualAxis'.'SDL2.dll'.'SDL_JoystickSetVirtualAxis'
++'_SDL_JoystickSetVirtualButton'.'SDL2.dll'.'SDL_JoystickSetVirtualButton'
++'_SDL_JoystickSetVirtualHat'.'SDL2.dll'.'SDL_JoystickSetVirtualHat'
++'_SDL_GetErrorMsg'.'SDL2.dll'.'SDL_GetErrorMsg'
++'_SDL_LockSensors'.'SDL2.dll'.'SDL_LockSensors'
++'_SDL_UnlockSensors'.'SDL2.dll'.'SDL_UnlockSensors'
++'_SDL_Metal_GetLayer'.'SDL2.dll'.'SDL_Metal_GetLayer'
++'_SDL_Metal_GetDrawableSize'.'SDL2.dll'.'SDL_Metal_GetDrawableSize'
++'_SDL_trunc'.'SDL2.dll'.'SDL_trunc'
++'_SDL_truncf'.'SDL2.dll'.'SDL_truncf'
++'_SDL_GetPreferredLocales'.'SDL2.dll'.'SDL_GetPreferredLocales'
++'_SDL_SIMDRealloc'.'SDL2.dll'.'SDL_SIMDRealloc'
# ++'_SDL_AndroidRequestPermission'.'SDL2.dll'.'SDL_AndroidRequestPermission'
++'_SDL_OpenURL'.'SDL2.dll'.'SDL_OpenURL'
++'_SDL_HasSurfaceRLE'.'SDL2.dll'.'SDL_HasSurfaceRLE'
++'_SDL_GameControllerHasLED'.'SDL2.dll'.'SDL_GameControllerHasLED'
++'_SDL_GameControllerSetLED'.'SDL2.dll'.'SDL_GameControllerSetLED'
++'_SDL_JoystickHasLED'.'SDL2.dll'.'SDL_JoystickHasLED'
++'_SDL_JoystickSetLED'.'SDL2.dll'.'SDL_JoystickSetLED'
++'_SDL_GameControllerRumbleTriggers'.'SDL2.dll'.'SDL_GameControllerRumbleTriggers'
++'_SDL_JoystickRumbleTriggers'.'SDL2.dll'.'SDL_JoystickRumbleTriggers'
++'_SDL_GameControllerHasAxis'.'SDL2.dll'.'SDL_GameControllerHasAxis'
++'_SDL_GameControllerHasButton'.'SDL2.dll'.'SDL_GameControllerHasButton'
++'_SDL_GameControllerGetNumTouchpads'.'SDL2.dll'.'SDL_GameControllerGetNumTouchpads'
++'_SDL_GameControllerGetNumTouchpadFingers'.'SDL2.dll'.'SDL_GameControllerGetNumTouchpadFingers'
++'_SDL_GameControllerGetTouchpadFinger'.'SDL2.dll'.'SDL_GameControllerGetTouchpadFinger'
++'_SDL_crc32'.'SDL2.dll'.'SDL_crc32'
++'_SDL_GameControllerGetSerial'.'SDL2.dll'.'SDL_GameControllerGetSerial'
++'_SDL_JoystickGetSerial'.'SDL2.dll'.'SDL_JoystickGetSerial'
++'_SDL_GameControllerHasSensor'.'SDL2.dll'.'SDL_GameControllerHasSensor'
++'_SDL_GameControllerSetSensorEnabled'.'SDL2.dll'.'SDL_GameControllerSetSensorEnabled'
++'_SDL_GameControllerIsSensorEnabled'.'SDL2.dll'.'SDL_GameControllerIsSensorEnabled'
++'_SDL_GameControllerGetSensorData'.'SDL2.dll'.'SDL_GameControllerGetSensorData'
++'_SDL_wcscasecmp'.'SDL2.dll'.'SDL_wcscasecmp'
++'_SDL_wcsncasecmp'.'SDL2.dll'.'SDL_wcsncasecmp'
++'_SDL_round'.'SDL2.dll'.'SDL_round'
++'_SDL_roundf'.'SDL2.dll'.'SDL_roundf'
++'_SDL_lround'.'SDL2.dll'.'SDL_lround'
++'_SDL_lroundf'.'SDL2.dll'.'SDL_lroundf'
++'_SDL_SoftStretchLinear'.'SDL2.dll'.'SDL_SoftStretchLinear'
++'_SDL_RenderGetD3D11Device'.'SDL2.dll'.'SDL_RenderGetD3D11Device'
++'_SDL_UpdateNVTexture'.'SDL2.dll'.'SDL_UpdateNVTexture'
++'_SDL_SetWindowKeyboardGrab'.'SDL2.dll'.'SDL_SetWindowKeyboardGrab'
++'_SDL_SetWindowMouseGrab'.'SDL2.dll'.'SDL_SetWindowMouseGrab'
++'_SDL_GetWindowKeyboardGrab'.'SDL2.dll'.'SDL_GetWindowKeyboardGrab'
++'_SDL_GetWindowMouseGrab'.'SDL2.dll'.'SDL_GetWindowMouseGrab'
++'_SDL_isalpha'.'SDL2.dll'.'SDL_isalpha'
++'_SDL_isalnum'.'SDL2.dll'.'SDL_isalnum'
++'_SDL_isblank'.'SDL2.dll'.'SDL_isblank'
++'_SDL_iscntrl'.'SDL2.dll'.'SDL_iscntrl'
++'_SDL_isxdigit'.'SDL2.dll'.'SDL_isxdigit'
++'_SDL_ispunct'.'SDL2.dll'.'SDL_ispunct'
++'_SDL_isprint'.'SDL2.dll'.'SDL_isprint'
++'_SDL_isgraph'.'SDL2.dll'.'SDL_isgraph'
# ++'_SDL_AndroidShowToast'.'SDL2.dll'.'SDL_AndroidShowToast'
++'_SDL_GetAudioDeviceSpec'.'SDL2.dll'.'SDL_GetAudioDeviceSpec'
++'_SDL_TLSCleanup'.'SDL2.dll'.'SDL_TLSCleanup'
++'_SDL_SetWindowAlwaysOnTop'.'SDL2.dll'.'SDL_SetWindowAlwaysOnTop'
++'_SDL_FlashWindow'.'SDL2.dll'.'SDL_FlashWindow'
++'_SDL_GameControllerSendEffect'.'SDL2.dll'.'SDL_GameControllerSendEffect'
++'_SDL_JoystickSendEffect'.'SDL2.dll'.'SDL_JoystickSendEffect'
++'_SDL_GameControllerGetSensorDataRate'.'SDL2.dll'.'SDL_GameControllerGetSensorDataRate'
++'_SDL_SetTextureUserData'.'SDL2.dll'.'SDL_SetTextureUserData'
++'_SDL_GetTextureUserData'.'SDL2.dll'.'SDL_GetTextureUserData'
++'_SDL_RenderGeometry'.'SDL2.dll'.'SDL_RenderGeometry'
++'_SDL_RenderGeometryRaw'.'SDL2.dll'.'SDL_RenderGeometryRaw'
++'_SDL_RenderSetVSync'.'SDL2.dll'.'SDL_RenderSetVSync'
++'_SDL_asprintf'.'SDL2.dll'.'SDL_asprintf'
++'_SDL_vasprintf'.'SDL2.dll'.'SDL_vasprintf'
++'_SDL_GetWindowICCProfile'.'SDL2.dll'.'SDL_GetWindowICCProfile'
++'_SDL_GetTicks64'.'SDL2.dll'.'SDL_GetTicks64'
# ++'_SDL_LinuxSetThreadPriorityAndPolicy'.'SDL2.dll'.'SDL_LinuxSetThreadPriorityAndPolicy'
++'_SDL_GameControllerGetAppleSFSymbolsNameForButton'.'SDL2.dll'.'SDL_GameControllerGetAppleSFSymbolsNameForButton'
++'_SDL_GameControllerGetAppleSFSymbolsNameForAxis'.'SDL2.dll'.'SDL_GameControllerGetAppleSFSymbolsNameForAxis'
++'_SDL_hid_init'.'SDL2.dll'.'SDL_hid_init'
++'_SDL_hid_exit'.'SDL2.dll'.'SDL_hid_exit'
++'_SDL_hid_device_change_count'.'SDL2.dll'.'SDL_hid_device_change_count'
++'_SDL_hid_enumerate'.'SDL2.dll'.'SDL_hid_enumerate'
++'_SDL_hid_free_enumeration'.'SDL2.dll'.'SDL_hid_free_enumeration'
++'_SDL_hid_open'.'SDL2.dll'.'SDL_hid_open'
++'_SDL_hid_open_path'.'SDL2.dll'.'SDL_hid_open_path'
++'_SDL_hid_write'.'SDL2.dll'.'SDL_hid_write'
++'_SDL_hid_read_timeout'.'SDL2.dll'.'SDL_hid_read_timeout'
++'_SDL_hid_read'.'SDL2.dll'.'SDL_hid_read'
++'_SDL_hid_set_nonblocking'.'SDL2.dll'.'SDL_hid_set_nonblocking'
++'_SDL_hid_send_feature_report'.'SDL2.dll'.'SDL_hid_send_feature_report'
++'_SDL_hid_get_feature_report'.'SDL2.dll'.'SDL_hid_get_feature_report'
++'_SDL_hid_close'.'SDL2.dll'.'SDL_hid_close'
++'_SDL_hid_get_manufacturer_string'.'SDL2.dll'.'SDL_hid_get_manufacturer_string'
++'_SDL_hid_get_product_string'.'SDL2.dll'.'SDL_hid_get_product_string'
++'_SDL_hid_get_serial_number_string'.'SDL2.dll'.'SDL_hid_get_serial_number_string'
++'_SDL_hid_get_indexed_string'.'SDL2.dll'.'SDL_hid_get_indexed_string'
++'_SDL_SetWindowMouseRect'.'SDL2.dll'.'SDL_SetWindowMouseRect'
++'_SDL_GetWindowMouseRect'.'SDL2.dll'.'SDL_GetWindowMouseRect'
++'_SDL_RenderWindowToLogical'.'SDL2.dll'.'SDL_RenderWindowToLogical'
++'_SDL_RenderLogicalToWindow'.'SDL2.dll'.'SDL_RenderLogicalToWindow'
++'_SDL_JoystickHasRumble'.'SDL2.dll'.'SDL_JoystickHasRumble'
++'_SDL_JoystickHasRumbleTriggers'.'SDL2.dll'.'SDL_JoystickHasRumbleTriggers'
++'_SDL_GameControllerHasRumble'.'SDL2.dll'.'SDL_GameControllerHasRumble'
++'_SDL_GameControllerHasRumbleTriggers'.'SDL2.dll'.'SDL_GameControllerHasRumbleTriggers'
++'_SDL_hid_ble_scan'.'SDL2.dll'.'SDL_hid_ble_scan'
++'_SDL_PremultiplyAlpha'.'SDL2.dll'.'SDL_PremultiplyAlpha'
# ++'_SDL_AndroidSendMessage'.'SDL2.dll'.'SDL_AndroidSendMessage'
++'_SDL_GetTouchName'.'SDL2.dll'.'SDL_GetTouchName'
++'_SDL_ClearComposition'.'SDL2.dll'.'SDL_ClearComposition'
++'_SDL_IsTextInputShown'.'SDL2.dll'.'SDL_IsTextInputShown'
++'_SDL_HasIntersectionF'.'SDL2.dll'.'SDL_HasIntersectionF'
++'_SDL_IntersectFRect'.'SDL2.dll'.'SDL_IntersectFRect'
++'_SDL_UnionFRect'.'SDL2.dll'.'SDL_UnionFRect'
++'_SDL_EncloseFPoints'.'SDL2.dll'.'SDL_EncloseFPoints'
++'_SDL_IntersectFRectAndLine'.'SDL2.dll'.'SDL_IntersectFRectAndLine'
++'_SDL_RenderGetWindow'.'SDL2.dll'.'SDL_RenderGetWindow'
++'_SDL_bsearch'.'SDL2.dll'.'SDL_bsearch'
++'_SDL_GameControllerPathForIndex'.'SDL2.dll'.'SDL_GameControllerPathForIndex'
++'_SDL_GameControllerPath'.'SDL2.dll'.'SDL_GameControllerPath'
++'_SDL_JoystickPathForIndex'.'SDL2.dll'.'SDL_JoystickPathForIndex'
++'_SDL_JoystickPath'.'SDL2.dll'.'SDL_JoystickPath'
++'_SDL_JoystickAttachVirtualEx'.'SDL2.dll'.'SDL_JoystickAttachVirtualEx'
++'_SDL_GameControllerGetFirmwareVersion'.'SDL2.dll'.'SDL_GameControllerGetFirmwareVersion'
++'_SDL_JoystickGetFirmwareVersion'.'SDL2.dll'.'SDL_JoystickGetFirmwareVersion'
++'_SDL_GUIDToString'.'SDL2.dll'.'SDL_GUIDToString'
++'_SDL_GUIDFromString'.'SDL2.dll'.'SDL_GUIDFromString'
++'_SDL_HasLSX'.'SDL2.dll'.'SDL_HasLSX'
++'_SDL_HasLASX'.'SDL2.dll'.'SDL_HasLASX'
++'_SDL_RenderGetD3D12Device'.'SDL2.dll'.'SDL_RenderGetD3D12Device'
++'_SDL_utf8strnlen'.'SDL2.dll'.'SDL_utf8strnlen'
# ++'_SDL_GDKGetTaskQueue'.'SDL2.dll'.'SDL_GDKGetTaskQueue'
# ++'_SDL_GDKRunApp'.'SDL2.dll'.'SDL_GDKRunApp'
++'_SDL_GetOriginalMemoryFunctions'.'SDL2.dll'.'SDL_GetOriginalMemoryFunctions'
++'_SDL_ResetKeyboard'.'SDL2.dll'.'SDL_ResetKeyboard'
++'_SDL_GetDefaultAudioInfo'.'SDL2.dll'.'SDL_GetDefaultAudioInfo'
++'_SDL_GetPointDisplayIndex'.'SDL2.dll'.'SDL_GetPointDisplayIndex'
++'_SDL_GetRectDisplayIndex'.'SDL2.dll'.'SDL_GetRectDisplayIndex'
++'_SDL_ResetHint'.'SDL2.dll'.'SDL_ResetHint'
++'_SDL_crc16'.'SDL2.dll'.'SDL_crc16'
++'_SDL_GetWindowSizeInPixels'.'SDL2.dll'.'SDL_GetWindowSizeInPixels'

View File

@@ -24,13 +24,6 @@
#if SDL_DYNAMIC_API
#if defined(__OS2__)
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#include <dos.h>
#endif
#include "SDL.h"
/* These headers have system specific definitions, so aren't included above */
@@ -50,7 +43,6 @@
static void SDL_InitDynamicAPI(void);
/* BE CAREFUL CALLING ANY SDL CODE IN HERE, IT WILL BLOW UP.
Even self-contained stuff might call SDL_Error and break everything. */
@@ -191,6 +183,79 @@ SDL_DYNAPI_VARARGS(,,)
#error Write me.
#endif
#define ENABLE_SDL_CALL_LOGGING 0
#if ENABLE_SDL_CALL_LOGGING
static int SDLCALL SDL_SetError_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) {
char buf[512]; /* !!! FIXME: dynamic allocation */ \
va_list ap;
SDL_Log_REAL("SDL3CALL SDL_SetError");
va_start(ap, fmt);
SDL_vsnprintf_REAL(buf, sizeof (buf), fmt, ap);
va_end(ap);
return SDL_SetError_REAL("%s", buf);
}
static int SDLCALL SDL_sscanf_LOGSDLCALLS(const char *buf, SDL_SCANF_FORMAT_STRING const char *fmt, ...) {
int retval;
va_list ap;
SDL_Log_REAL("SDL3CALL SDL_sscanf");
va_start(ap, fmt);
retval = SDL_vsscanf_REAL(buf, fmt, ap);
va_end(ap);
return retval;
}
static int SDLCALL SDL_snprintf_LOGSDLCALLS(SDL_OUT_Z_CAP(maxlen) char *buf, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) {
int retval;
va_list ap;
SDL_Log_REAL("SDL3CALL SDL_snprintf");
va_start(ap, fmt);
retval = SDL_vsnprintf_REAL(buf, maxlen, fmt, ap);
va_end(ap);
return retval;
}
static int SDLCALL SDL_asprintf_LOGSDLCALLS(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) {
int retval;
va_list ap;
SDL_Log_REAL("SDL3CALL SDL_asprintf");
va_start(ap, fmt);
retval = SDL_vasprintf_REAL(strp, fmt, ap);
va_end(ap);
return retval;
}
static void SDLCALL SDL_Log_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) {
va_list ap;
SDL_Log_REAL("SDL3CALL SDL_Log");
va_start(ap, fmt);
SDL_LogMessageV_REAL(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap); \
va_end(ap);
}
static void SDLCALL SDL_LogMessage_LOGSDLCALLS(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) {
va_list ap;
SDL_Log_REAL("SDL3CALL SDL_LogMessage");
va_start(ap, fmt);
SDL_LogMessageV_REAL(category, priority, fmt, ap);
va_end(ap);
}
#define SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(logname, prio) \
static void SDLCALL SDL_Log##logname##_LOGSDLCALLS(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { \
va_list ap; va_start(ap, fmt); \
SDL_Log_REAL("SDL3CALL SDL_Log%s", #logname); \
SDL_LogMessageV_REAL(category, SDL_LOG_PRIORITY_##prio, fmt, ap); \
va_end(ap); \
}
SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Verbose, VERBOSE)
SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Debug, DEBUG)
SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Info, INFO)
SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Warn, WARN)
SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Error, ERROR)
SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Critical, CRITICAL)
#define SDL_DYNAPI_PROC(rc,fn,params,args,ret) \
rc SDLCALL fn##_LOGSDLCALLS params { SDL_Log_REAL("SDL3CALL %s", #fn); ret fn##_REAL args; }
#define SDL_DYNAPI_PROC_NO_VARARGS 1
#include "SDL_dynapi_procs.h"
#undef SDL_DYNAPI_PROC
#undef SDL_DYNAPI_PROC_NO_VARARGS
#endif
/* we make this a static function so we can call the correct one without the
system's dynamic linker resolving to the wrong version of this. */
static Sint32
@@ -206,9 +271,25 @@ initialize_jumptable(Uint32 apiver, void *table, Uint32 tablesize)
}
/* Init our jump table first. */
#define SDL_DYNAPI_PROC(rc,fn,params,args,ret) jump_table.fn = fn##_REAL;
#include "SDL_dynapi_procs.h"
#undef SDL_DYNAPI_PROC
#if ENABLE_SDL_CALL_LOGGING
{
const char *env = SDL_getenv_REAL("SDL_DYNAPI_LOG_CALLS");
const SDL_bool log_calls = (env && SDL_atoi_REAL(env));
if (log_calls) {
#define SDL_DYNAPI_PROC(rc,fn,params,args,ret) jump_table.fn = fn##_LOGSDLCALLS;
#include "SDL_dynapi_procs.h"
#undef SDL_DYNAPI_PROC
} else {
#define SDL_DYNAPI_PROC(rc,fn,params,args,ret) jump_table.fn = fn##_REAL;
#include "SDL_dynapi_procs.h"
#undef SDL_DYNAPI_PROC
}
}
#else
#define SDL_DYNAPI_PROC(rc,fn,params,args,ret) jump_table.fn = fn##_REAL;
#include "SDL_dynapi_procs.h"
#undef SDL_DYNAPI_PROC
#endif
/* Then the external table... */
if (output_jump_table != &jump_table) {
@@ -253,7 +334,7 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
return retval;
}
#elif defined(unix) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) || defined(__QNX__)
#elif defined(unix) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
#include <dlfcn.h>
static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
{
@@ -268,20 +349,6 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
return retval;
}
#elif defined(__OS2__)
static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
{
HMODULE hmodule;
PFN retval = NULL;
char error[256];
if (DosLoadModule(error, sizeof(error), fname, &hmodule) == NO_ERROR) {
if (DosQueryProcAddr(hmodule, 0, sym, &retval) != NO_ERROR) {
DosFreeModule(hmodule);
}
}
return (void *)retval;
}
#else
#error Please define your platform.
#endif

View File

@@ -45,12 +45,10 @@
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE /* probably not useful on iOS. */
#define SDL_DYNAMIC_API 0
#elif defined(__native_client__) && __native_client__ /* probably not useful on NACL. */
#elif defined(__ANDROID__) /* probably not useful on Android. */
#define SDL_DYNAMIC_API 0
#elif defined(__EMSCRIPTEN__) && __EMSCRIPTEN__ /* probably not useful on Emscripten. */
#define SDL_DYNAMIC_API 0
#elif defined(SDL_BUILDING_WINRT) && SDL_BUILDING_WINRT /* probably not useful on WinRT, given current .dll loading restrictions */
#define SDL_DYNAMIC_API 0
#elif defined(__PS2__) && __PS2__
#define SDL_DYNAMIC_API 0
#elif defined(__PSP__) && __PSP__
@@ -63,6 +61,8 @@
#define SDL_DYNAMIC_API 0 /* vitasdk doesn't support dynamic linking */
#elif defined(__NGAGE__)
#define SDL_DYNAMIC_API 0 /* The N-Gage doesn't support dynamic linking either */
#elif defined(__3DS__)
#define SDL_DYNAMIC_API 0 /* devkitARM doesn't support dynamic linking */
#elif defined(DYNAPI_NEEDS_DLOPEN) && !defined(HAVE_DLOPEN)
#define SDL_DYNAMIC_API 0 /* we need dlopen(), but don't have it.... */
#endif

View File

@@ -571,10 +571,7 @@
#define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL
#define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL
#define SDL_RenderIsClipEnabled SDL_RenderIsClipEnabled_REAL
#define SDL_WinRTRunApp SDL_WinRTRunApp_REAL
#define SDL_WarpMouseGlobal SDL_WarpMouseGlobal_REAL
#define SDL_WinRTGetFSPathUNICODE SDL_WinRTGetFSPathUNICODE_REAL
#define SDL_WinRTGetFSPathUTF8 SDL_WinRTGetFSPathUTF8_REAL
#define SDL_sqrtf SDL_sqrtf_REAL
#define SDL_tan SDL_tan_REAL
#define SDL_tanf SDL_tanf_REAL
@@ -663,7 +660,6 @@
#define SDL_RenderGetMetalLayer SDL_RenderGetMetalLayer_REAL
#define SDL_RenderGetMetalCommandEncoder SDL_RenderGetMetalCommandEncoder_REAL
#define SDL_IsAndroidTV SDL_IsAndroidTV_REAL
#define SDL_WinRTGetDeviceFamily SDL_WinRTGetDeviceFamily_REAL
#define SDL_log10 SDL_log10_REAL
#define SDL_log10f SDL_log10f_REAL
#define SDL_GameControllerMappingForDeviceIndex SDL_GameControllerMappingForDeviceIndex_REAL
@@ -885,3 +881,11 @@
#define SDL_ResetHint SDL_ResetHint_REAL
#define SDL_crc16 SDL_crc16_REAL
#define SDL_GetWindowSizeInPixels SDL_GetWindowSizeInPixels_REAL
#define SDL_GetJoystickGUIDInfo SDL_GetJoystickGUIDInfo_REAL
#define SDL_SetPrimarySelectionText SDL_SetPrimarySelectionText_REAL
#define SDL_GetPrimarySelectionText SDL_GetPrimarySelectionText_REAL
#define SDL_HasPrimarySelectionText SDL_HasPrimarySelectionText_REAL
#define SDL_GameControllerGetSensorDataWithTimestamp SDL_GameControllerGetSensorDataWithTimestamp_REAL
#define SDL_SensorGetDataWithTimestamp SDL_SensorGetDataWithTimestamp_REAL
#define SDL_ResetHints SDL_ResetHints_REAL
#define SDL_strcasestr SDL_strcasestr_REAL

View File

@@ -50,8 +50,6 @@ SDL_DYNAPI_PROC(int,SDL_snprintf,(SDL_OUT_Z_CAP(b) char *a, size_t b, SDL_PRINTF
#if defined(__WIN32__) || defined(__GDK__)
SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThread,(SDL_ThreadFunction a, const char *b, void *c, pfnSDL_CurrentBeginThread d, pfnSDL_CurrentEndThread e),(a,b,c,d,e),return)
#elif defined(__OS2__)
SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThread,(SDL_ThreadFunction a, const char *b, void *c, pfnSDL_CurrentBeginThread d, pfnSDL_CurrentEndThread e),(a,b,c,d,e),return)
#else
SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThread,(SDL_ThreadFunction a, const char *b, void *c),(a,b,c),return)
#endif
@@ -606,11 +604,6 @@ SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),retu
SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(int a,int *b, int *c),(a,b,c),return)
#endif
SDL_DYNAPI_PROC(SDL_bool,SDL_RenderIsClipEnabled,(SDL_Renderer *a),(a),return)
#ifdef __WINRT__
SDL_DYNAPI_PROC(int,SDL_WinRTRunApp,(int a, char **b, void *c),(a,b,c),return)
SDL_DYNAPI_PROC(const wchar_t*,SDL_WinRTGetFSPathUNICODE,(SDL_WinRT_Path a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_WinRTGetFSPathUTF8,(SDL_WinRT_Path a),(a),return)
#endif
SDL_DYNAPI_PROC(int,SDL_WarpMouseGlobal,(int a, int b),(a,b),return)
SDL_DYNAPI_PROC(float,SDL_sqrtf,(float a),(a),return)
SDL_DYNAPI_PROC(double,SDL_tan,(double a),(a),return)
@@ -702,9 +695,6 @@ SDL_DYNAPI_PROC(SDL_YUV_CONVERSION_MODE,SDL_GetYUVConversionMode,(void),(),retur
SDL_DYNAPI_PROC(SDL_YUV_CONVERSION_MODE,SDL_GetYUVConversionModeForResolution,(int a, int b),(a,b),return)
SDL_DYNAPI_PROC(void*,SDL_RenderGetMetalLayer,(SDL_Renderer *a),(a),return)
SDL_DYNAPI_PROC(void*,SDL_RenderGetMetalCommandEncoder,(SDL_Renderer *a),(a),return)
#ifdef __WINRT__
SDL_DYNAPI_PROC(SDL_WinRT_DeviceFamily,SDL_WinRTGetDeviceFamily,(void),(),return)
#endif
#ifdef __ANDROID__
SDL_DYNAPI_PROC(SDL_bool,SDL_IsAndroidTV,(void),(),return)
#endif
@@ -749,8 +739,6 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasColorKey,(SDL_Surface *a),(a),return)
#if defined(__WIN32__) || defined(__GDK__)
SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d, pfnSDL_CurrentBeginThread e, pfnSDL_CurrentEndThread f),(a,b,c,d,e,f),return)
#elif defined(__OS2__)
SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d, pfnSDL_CurrentBeginThread e, pfnSDL_CurrentEndThread f),(a,b,c,d,e,f),return)
#else
SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d),(a,b,c,d),return)
#endif
@@ -968,3 +956,11 @@ SDL_DYNAPI_PROC(int,SDL_GetRectDisplayIndex,(const SDL_Rect *a),(a),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_ResetHint,(const char *a),(a),return)
SDL_DYNAPI_PROC(Uint16,SDL_crc16,(Uint16 a, const void *b, size_t c),(a,b,c),return)
SDL_DYNAPI_PROC(void,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a,b,c),)
SDL_DYNAPI_PROC(void,SDL_GetJoystickGUIDInfo,(SDL_JoystickGUID a, Uint16 *b, Uint16 *c, Uint16 *d, Uint16 *e),(a,b,c,d,e),)
SDL_DYNAPI_PROC(int,SDL_SetPrimarySelectionText,(const char *a),(a),return)
SDL_DYNAPI_PROC(char*,SDL_GetPrimarySelectionText,(void),(),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_HasPrimarySelectionText,(void),(),return)
SDL_DYNAPI_PROC(int,SDL_GameControllerGetSensorDataWithTimestamp,(SDL_GameController *a, SDL_SensorType b, Uint64 *c, float *d, int e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(int,SDL_SensorGetDataWithTimestamp,(SDL_Sensor *a, Uint64 *b, float *c, int d),(a,b,c,d),return)
SDL_DYNAPI_PROC(void,SDL_ResetHints,(void),(),)
SDL_DYNAPI_PROC(char*,SDL_strcasestr,(const char *a, const char *b),(a,b),return)

View File

@@ -33,7 +33,6 @@ use File::Basename;
chdir(dirname(__FILE__) . '/../..');
my $sdl_dynapi_procs_h = "src/dynapi/SDL_dynapi_procs.h";
my $sdl_dynapi_overrides_h = "src/dynapi/SDL_dynapi_overrides.h";
my $sdl2_exports = "src/dynapi/SDL2.exports";
my %existing = ();
if (-f $sdl_dynapi_procs_h) {
@@ -48,7 +47,6 @@ if (-f $sdl_dynapi_procs_h) {
open(SDL_DYNAPI_PROCS_H, '>>', $sdl_dynapi_procs_h) or die("Can't open $sdl_dynapi_procs_h: $!\n");
open(SDL_DYNAPI_OVERRIDES_H, '>>', $sdl_dynapi_overrides_h) or die("Can't open $sdl_dynapi_overrides_h: $!\n");
open(SDL2_EXPORTS, '>>', $sdl2_exports) or die("Can't open $sdl2_exports: $!\n");
opendir(HEADERS, 'include') or die("Can't open include dir: $!\n");
while (my $d = readdir(HEADERS)) {
@@ -135,7 +133,6 @@ while (my $d = readdir(HEADERS)) {
print("NEW: $decl\n");
print SDL_DYNAPI_PROCS_H "SDL_DYNAPI_PROC($rc,$fn,$paramstr,$argstr,$retstr)\n";
print SDL_DYNAPI_OVERRIDES_H "#define $fn ${fn}_REAL\n";
print SDL2_EXPORTS "++'_${fn}'.'SDL2.dll'.'${fn}'\n";
} else {
print("Failed to parse decl [$decl]!\n");
}
@@ -146,6 +143,5 @@ closedir(HEADERS);
close(SDL_DYNAPI_PROCS_H);
close(SDL_DYNAPI_OVERRIDES_H);
close(SDL2_EXPORTS);
# vi: set ts=4 sw=4 expandtab:

View File

@@ -86,7 +86,7 @@ typedef struct _SDL_SysWMEntry
static struct
{
SDL_mutex *lock;
SDL_atomic_t active;
SDL_bool active;
SDL_atomic_t count;
int max_events_seen;
SDL_EventEntry *head;
@@ -94,7 +94,7 @@ static struct
SDL_EventEntry *free;
SDL_SysWMEntry *wmmsg_used;
SDL_SysWMEntry *wmmsg_free;
} SDL_EventQ = { NULL, { 1 }, { 0 }, 0, NULL, NULL, NULL, NULL, NULL };
} SDL_EventQ = { NULL, SDL_FALSE, { 0 }, 0, NULL, NULL, NULL, NULL, NULL };
#if !SDL_JOYSTICK_DISABLED
@@ -147,7 +147,7 @@ SDL_AutoUpdateSensorsChanged(void *userdata, const char *name, const char *oldVa
static void SDLCALL
SDL_PollSentinelChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_EventState(SDL_POLLSENTINEL, SDL_GetStringBoolean(hint, SDL_TRUE) ? SDL_ENABLE : SDL_DISABLE);
(void)SDL_EventState(SDL_POLLSENTINEL, SDL_GetStringBoolean(hint, SDL_TRUE) ? SDL_ENABLE : SDL_DISABLE);
}
/**
@@ -406,7 +406,7 @@ SDL_LogEvent(const SDL_Event *event)
SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" gestureid=%"SDL_PRIs64" numfingers=%u error=%f x=%f y=%f)", \
(uint) event->dgesture.timestamp, (long long)event->dgesture.touchId, \
(long long)event->dgesture.gestureId, (uint) event->dgesture.numFingers, \
event->dgesture.error, event->dgesture.x, event->dgesture.y);
event->dgesture.error, event->dgesture.x, event->dgesture.y)
SDL_EVENT_CASE(SDL_DOLLARGESTURE) PRINT_DOLLAR_EVENT(event); break;
SDL_EVENT_CASE(SDL_DOLLARRECORD) PRINT_DOLLAR_EVENT(event); break;
#undef PRINT_DOLLAR_EVENT
@@ -425,7 +425,7 @@ SDL_LogEvent(const SDL_Event *event)
SDL_EVENT_CASE(SDL_DROPCOMPLETE) PRINT_DROP_EVENT(event); break;
#undef PRINT_DROP_EVENT
#define PRINT_AUDIODEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%u iscapture=%s)", (uint) event->adevice.timestamp, (uint) event->adevice.which, event->adevice.iscapture ? "true" : "false");
#define PRINT_AUDIODEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%u iscapture=%s)", (uint) event->adevice.timestamp, (uint) event->adevice.which, event->adevice.iscapture ? "true" : "false")
SDL_EVENT_CASE(SDL_AUDIODEVICEADDED) PRINT_AUDIODEV_EVENT(event); break;
SDL_EVENT_CASE(SDL_AUDIODEVICEREMOVED) PRINT_AUDIODEV_EVENT(event); break;
#undef PRINT_AUDIODEV_EVENT
@@ -474,7 +474,7 @@ SDL_StopEventLoop(void)
SDL_LockMutex(SDL_EventQ.lock);
}
SDL_AtomicSet(&SDL_EventQ.active, 0);
SDL_EventQ.active = SDL_FALSE;
if (report && SDL_atoi(report)) {
SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n",
@@ -554,26 +554,30 @@ SDL_StartEventLoop(void)
return -1;
}
}
SDL_LockMutex(SDL_EventQ.lock);
if (!SDL_event_watchers_lock) {
SDL_event_watchers_lock = SDL_CreateMutex();
if (SDL_event_watchers_lock == NULL) {
SDL_UnlockMutex(SDL_EventQ.lock);
return -1;
}
}
#endif /* !SDL_THREADS_DISABLED */
/* Process most event types */
SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
(void)SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
(void)SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
(void)SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
#if 0 /* Leave these events enabled so apps can respond to items being dragged onto them at startup */
SDL_EventState(SDL_DROPFILE, SDL_DISABLE);
SDL_EventState(SDL_DROPTEXT, SDL_DISABLE);
(void)SDL_EventState(SDL_DROPFILE, SDL_DISABLE);
(void)SDL_EventState(SDL_DROPTEXT, SDL_DISABLE);
#endif
SDL_AtomicSet(&SDL_EventQ.active, 1);
SDL_EventQ.active = SDL_TRUE;
if (SDL_EventQ.lock) {
SDL_UnlockMutex(SDL_EventQ.lock);
}
return 0;
}
@@ -692,17 +696,20 @@ SDL_PeepEventsInternal(SDL_Event * events, int numevents, SDL_eventaction action
{
int i, used, sentinels_expected = 0;
/* Don't look after we've quit */
if (!SDL_AtomicGet(&SDL_EventQ.active)) {
/* We get a few spurious events at shutdown, so don't warn then */
if (action == SDL_GETEVENT) {
SDL_SetError("The event system has been shut down");
}
return (-1);
}
/* Lock the event queue */
used = 0;
if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
/* Don't look after we've quit */
if (!SDL_EventQ.active) {
if (SDL_EventQ.lock) {
SDL_UnlockMutex(SDL_EventQ.lock);
}
/* We get a few spurious events at shutdown, so don't warn then */
if (action == SDL_GETEVENT) {
SDL_SetError("The event system has been shut down");
}
return (-1);
}
if (action == SDL_ADDEVENT) {
for (i = 0; i < numevents; ++i) {
used += SDL_AddEvent(&events[i]);
@@ -810,15 +817,12 @@ SDL_FlushEvent(Uint32 type)
void
SDL_FlushEvents(Uint32 minType, Uint32 maxType)
{
SDL_EventEntry *entry, *next;
Uint32 type;
/* !!! FIXME: we need to manually SDL_free() the strings in TEXTINPUT and
drag'n'drop events if we're flushing them without passing them to the
app, but I don't know if this is the right place to do that. */
/* Don't look after we've quit */
if (!SDL_AtomicGet(&SDL_EventQ.active)) {
return;
}
/* Make sure the events are current */
#if 0
/* Actually, we can't do this since we might be flushing while processing
@@ -829,8 +833,13 @@ SDL_FlushEvents(Uint32 minType, Uint32 maxType)
/* Lock the event queue */
if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
SDL_EventEntry *entry, *next;
Uint32 type;
/* Don't look after we've quit */
if (!SDL_EventQ.active) {
if (SDL_EventQ.lock) {
SDL_UnlockMutex(SDL_EventQ.lock);
}
return;
}
for (entry = SDL_EventQ.head; entry; entry = next) {
next = entry->next;
type = entry->event.type;

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,9 @@ extern int SDL_KeyboardInit(void);
/* Get the default keymap */
extern void SDL_GetDefaultKeymap(SDL_Keycode * keymap);
/* Get the default key code for a scancode */
extern SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode);
/* Set the mapping of scancode to key codes */
extern void SDL_SetKeymap(int start, const SDL_Keycode * keys, int length, SDL_bool send_event);
@@ -53,6 +56,10 @@ extern int SDL_SendKeyboardUnicodeKey(Uint32 ch);
extern int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode);
extern int SDL_SendKeyboardKeyAutoRelease(SDL_Scancode scancode);
/* This is for platforms that don't know the keymap but can report scancode and keycode directly.
Most platforms should prefer to optionally call SDL_SetKeymap and then use SDL_SendKeyboardKey. */
extern int SDL_SendKeyboardKeyAndKeycode(Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode);
/* Release all the autorelease keys */
extern void SDL_ReleaseAutoReleaseKeys(void);

View File

@@ -0,0 +1,441 @@
/*
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.
*/
#include "../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_X11
#include "SDL_keyboard_c.h"
#include "SDL_scancode_tables_c.h"
/* *INDENT-OFF* */ /* clang-format off */
static const struct {
Uint32 keysym;
SDL_Scancode scancode;
} KeySymToSDLScancode[] = {
{ 0xFF9C, SDL_SCANCODE_KP_1 }, /* XK_KP_End */
{ 0xFF99, SDL_SCANCODE_KP_2 }, /* XK_KP_Down */
{ 0xFF9B, SDL_SCANCODE_KP_3 }, /* XK_KP_Next */
{ 0xFF96, SDL_SCANCODE_KP_4 }, /* XK_KP_Left */
{ 0xFF9D, SDL_SCANCODE_KP_5 }, /* XK_KP_Begin */
{ 0xFF98, SDL_SCANCODE_KP_6 }, /* XK_KP_Right */
{ 0xFF95, SDL_SCANCODE_KP_7 }, /* XK_KP_Home */
{ 0xFF97, SDL_SCANCODE_KP_8 }, /* XK_KP_Up */
{ 0xFF9A, SDL_SCANCODE_KP_9 }, /* XK_KP_Prior */
{ 0xFF9E, SDL_SCANCODE_KP_0 }, /* XK_KP_Insert */
{ 0xFF9F, SDL_SCANCODE_KP_PERIOD }, /* XK_KP_Delete */
{ 0xFF62, SDL_SCANCODE_EXECUTE }, /* XK_Execute */
{ 0xFFEE, SDL_SCANCODE_APPLICATION }, /* XK_Hyper_R */
{ 0xFE03, SDL_SCANCODE_RALT }, /* XK_ISO_Level3_Shift */
{ 0xFFEB, SDL_SCANCODE_LGUI }, /* XK_Super_L */
{ 0xFFEC, SDL_SCANCODE_RGUI }, /* XK_Super_R */
{ 0xFF7E, SDL_SCANCODE_MODE }, /* XK_Mode_switch */
{ 0x1008FF65, SDL_SCANCODE_MENU }, /* XF86MenuKB */
{ 0x1008FF81, SDL_SCANCODE_F13 }, /* XF86Tools */
{ 0x1008FF45, SDL_SCANCODE_F14 }, /* XF86Launch5 */
{ 0x1008FF46, SDL_SCANCODE_F15 }, /* XF86Launch6 */
{ 0x1008FF47, SDL_SCANCODE_F16 }, /* XF86Launch7 */
{ 0x1008FF48, SDL_SCANCODE_F17 }, /* XF86Launch8 */
{ 0x1008FF49, SDL_SCANCODE_F18 }, /* XF86Launch9 */
};
/* This is a mapping from X keysym to Linux keycode */
static const Uint32 LinuxKeycodeKeysyms[] = {
/* 0, 0x000 */ 0x0, /* NoSymbol */
/* 1, 0x001 */ 0xFF1B, /* Escape */
/* 2, 0x002 */ 0x31, /* 1 */
/* 3, 0x003 */ 0x32, /* 2 */
/* 4, 0x004 */ 0x33, /* 3 */
/* 5, 0x005 */ 0x34, /* 4 */
/* 6, 0x006 */ 0x35, /* 5 */
/* 7, 0x007 */ 0x36, /* 6 */
/* 8, 0x008 */ 0x37, /* 7 */
/* 9, 0x009 */ 0x38, /* 8 */
/* 10, 0x00a */ 0x39, /* 9 */
/* 11, 0x00b */ 0x30, /* 0 */
/* 12, 0x00c */ 0x2D, /* minus */
/* 13, 0x00d */ 0x3D, /* equal */
/* 14, 0x00e */ 0xFF08, /* BackSpace */
/* 15, 0x00f */ 0xFF09, /* Tab */
/* 16, 0x010 */ 0x71, /* q */
/* 17, 0x011 */ 0x77, /* w */
/* 18, 0x012 */ 0x65, /* e */
/* 19, 0x013 */ 0x72, /* r */
/* 20, 0x014 */ 0x74, /* t */
/* 21, 0x015 */ 0x79, /* y */
/* 22, 0x016 */ 0x75, /* u */
/* 23, 0x017 */ 0x69, /* i */
/* 24, 0x018 */ 0x6F, /* o */
/* 25, 0x019 */ 0x70, /* p */
/* 26, 0x01a */ 0x5B, /* bracketleft */
/* 27, 0x01b */ 0x5D, /* bracketright */
/* 28, 0x01c */ 0xFF0D, /* Return */
/* 29, 0x01d */ 0xFFE3, /* Control_L */
/* 30, 0x01e */ 0x61, /* a */
/* 31, 0x01f */ 0x73, /* s */
/* 32, 0x020 */ 0x64, /* d */
/* 33, 0x021 */ 0x66, /* f */
/* 34, 0x022 */ 0x67, /* g */
/* 35, 0x023 */ 0x68, /* h */
/* 36, 0x024 */ 0x6A, /* j */
/* 37, 0x025 */ 0x6B, /* k */
/* 38, 0x026 */ 0x6C, /* l */
/* 39, 0x027 */ 0x3B, /* semicolon */
/* 40, 0x028 */ 0x27, /* apostrophe */
/* 41, 0x029 */ 0x60, /* grave */
/* 42, 0x02a */ 0xFFE1, /* Shift_L */
/* 43, 0x02b */ 0x5C, /* backslash */
/* 44, 0x02c */ 0x7A, /* z */
/* 45, 0x02d */ 0x78, /* x */
/* 46, 0x02e */ 0x63, /* c */
/* 47, 0x02f */ 0x76, /* v */
/* 48, 0x030 */ 0x62, /* b */
/* 49, 0x031 */ 0x6E, /* n */
/* 50, 0x032 */ 0x6D, /* m */
/* 51, 0x033 */ 0x2C, /* comma */
/* 52, 0x034 */ 0x2E, /* period */
/* 53, 0x035 */ 0x2F, /* slash */
/* 54, 0x036 */ 0xFFE2, /* Shift_R */
/* 55, 0x037 */ 0xFFAA, /* KP_Multiply */
/* 56, 0x038 */ 0xFFE9, /* Alt_L */
/* 57, 0x039 */ 0x20, /* space */
/* 58, 0x03a */ 0xFFE5, /* Caps_Lock */
/* 59, 0x03b */ 0xFFBE, /* F1 */
/* 60, 0x03c */ 0xFFBF, /* F2 */
/* 61, 0x03d */ 0xFFC0, /* F3 */
/* 62, 0x03e */ 0xFFC1, /* F4 */
/* 63, 0x03f */ 0xFFC2, /* F5 */
/* 64, 0x040 */ 0xFFC3, /* F6 */
/* 65, 0x041 */ 0xFFC4, /* F7 */
/* 66, 0x042 */ 0xFFC5, /* F8 */
/* 67, 0x043 */ 0xFFC6, /* F9 */
/* 68, 0x044 */ 0xFFC7, /* F10 */
/* 69, 0x045 */ 0xFF7F, /* Num_Lock */
/* 70, 0x046 */ 0xFF14, /* Scroll_Lock */
/* 71, 0x047 */ 0xFFB7, /* KP_7 */
/* 72, 0x048 */ 0XFFB8, /* KP_8 */
/* 73, 0x049 */ 0XFFB9, /* KP_9 */
/* 74, 0x04a */ 0xFFAD, /* KP_Subtract */
/* 75, 0x04b */ 0xFFB4, /* KP_4 */
/* 76, 0x04c */ 0xFFB5, /* KP_5 */
/* 77, 0x04d */ 0xFFB6, /* KP_6 */
/* 78, 0x04e */ 0xFFAB, /* KP_Add */
/* 79, 0x04f */ 0xFFB1, /* KP_1 */
/* 80, 0x050 */ 0xFFB2, /* KP_2 */
/* 81, 0x051 */ 0xFFB3, /* KP_3 */
/* 82, 0x052 */ 0xFFB0, /* KP_0 */
/* 83, 0x053 */ 0xFFAE, /* KP_Decimal */
/* 84, 0x054 */ 0x0, /* NoSymbol */
/* 85, 0x055 */ 0x0, /* NoSymbol */
/* 86, 0x056 */ 0x3C, /* less */
/* 87, 0x057 */ 0xFFC8, /* F11 */
/* 88, 0x058 */ 0xFFC9, /* F12 */
/* 89, 0x059 */ 0x0, /* NoSymbol */
/* 90, 0x05a */ 0xFF26, /* Katakana */
/* 91, 0x05b */ 0xFF25, /* Hiragana */
/* 92, 0x05c */ 0xFF23, /* Henkan_Mode */
/* 93, 0x05d */ 0xFF27, /* Hiragana_Katakana */
/* 94, 0x05e */ 0xFF22, /* Muhenkan */
/* 95, 0x05f */ 0x0, /* NoSymbol */
/* 96, 0x060 */ 0xFF8D, /* KP_Enter */
/* 97, 0x061 */ 0xFFE4, /* Control_R */
/* 98, 0x062 */ 0xFFAF, /* KP_Divide */
/* 99, 0x063 */ 0xFF15, /* Sys_Req */
/* 100, 0x064 */ 0xFFEA, /* Alt_R */
/* 101, 0x065 */ 0xFF0A, /* Linefeed */
/* 102, 0x066 */ 0xFF50, /* Home */
/* 103, 0x067 */ 0xFF52, /* Up */
/* 104, 0x068 */ 0xFF55, /* Prior */
/* 105, 0x069 */ 0xFF51, /* Left */
/* 106, 0x06a */ 0xFF53, /* Right */
/* 107, 0x06b */ 0xFF57, /* End */
/* 108, 0x06c */ 0xFF54, /* Down */
/* 109, 0x06d */ 0xFF56, /* Next */
/* 110, 0x06e */ 0xFF63, /* Insert */
/* 111, 0x06f */ 0xFFFF, /* Delete */
/* 112, 0x070 */ 0x0, /* NoSymbol */
/* 113, 0x071 */ 0x1008FF12, /* XF86AudioMute */
/* 114, 0x072 */ 0x1008FF11, /* XF86AudioLowerVolume */
/* 115, 0x073 */ 0x1008FF13, /* XF86AudioRaiseVolume */
/* 116, 0x074 */ 0x1008FF2A, /* XF86PowerOff */
/* 117, 0x075 */ 0xFFBD, /* KP_Equal */
/* 118, 0x076 */ 0xB1, /* plusminus */
/* 119, 0x077 */ 0xFF13, /* Pause */
/* 120, 0x078 */ 0x1008FF4A, /* XF86LaunchA */
/* 121, 0x079 */ 0xFFAC, /* KP_Separator */
/* 122, 0x07a */ 0xFF31, /* Hangul */
/* 123, 0x07b */ 0xFF34, /* Hangul_Hanja */
/* 124, 0x07c */ 0x0, /* NoSymbol */
/* 125, 0x07d */ 0xFFE7, /* Meta_L */
/* 126, 0x07e */ 0xFFE8, /* Meta_R */
/* 127, 0x07f */ 0xFF67, /* Menu */
/* 128, 0x080 */ 0x00, /* NoSymbol */
/* 129, 0x081 */ 0xFF66, /* Redo */
/* 130, 0x082 */ 0x1005FF70, /* SunProps */
/* 131, 0x083 */ 0xFF65, /* Undo */
/* 132, 0x084 */ 0x1005FF71, /* SunFront */
/* 133, 0x085 */ 0x1008FF57, /* XF86Copy */
/* 134, 0x086 */ 0x1008FF6B, /* XF86Open */
/* 135, 0x087 */ 0x1008FF6D, /* XF86Paste */
/* 136, 0x088 */ 0xFF68, /* Find */
/* 137, 0x089 */ 0x1008FF58, /* XF86Cut */
/* 138, 0x08a */ 0xFF6A, /* Help */
/* 139, 0x08b */ 0xFF67, /* Menu */
/* 140, 0x08c */ 0x1008FF1D, /* XF86Calculator */
/* 141, 0x08d */ 0x0, /* NoSymbol */
/* 142, 0x08e */ 0x1008FF2F, /* XF86Sleep */
/* 143, 0x08f */ 0x1008FF2B, /* XF86WakeUp */
/* 144, 0x090 */ 0x1008FF5D, /* XF86Explorer */
/* 145, 0x091 */ 0x1008FF7B, /* XF86Send */
/* 146, 0x092 */ 0x0, /* NoSymbol */
/* 147, 0x093 */ 0x1008FF8A, /* XF86Xfer */
/* 148, 0x094 */ 0x1008FF41, /* XF86Launch1 */
/* 149, 0x095 */ 0x1008FF42, /* XF86Launch2 */
/* 150, 0x096 */ 0x1008FF2E, /* XF86WWW */
/* 151, 0x097 */ 0x1008FF5A, /* XF86DOS */
/* 152, 0x098 */ 0x1008FF2D, /* XF86ScreenSaver */
/* 153, 0x099 */ 0x1008FF74, /* XF86RotateWindows */
/* 154, 0x09a */ 0x1008FF7F, /* XF86TaskPane */
/* 155, 0x09b */ 0x1008FF19, /* XF86Mail */
/* 156, 0x09c */ 0x1008FF30, /* XF86Favorites */
/* 157, 0x09d */ 0x1008FF33, /* XF86MyComputer */
/* 158, 0x09e */ 0x1008FF26, /* XF86Back */
/* 159, 0x09f */ 0x1008FF27, /* XF86Forward */
/* 160, 0x0a0 */ 0x0, /* NoSymbol */
/* 161, 0x0a1 */ 0x1008FF2C, /* XF86Eject */
/* 162, 0x0a2 */ 0x1008FF2C, /* XF86Eject */
/* 163, 0x0a3 */ 0x1008FF17, /* XF86AudioNext */
/* 164, 0x0a4 */ 0x1008FF14, /* XF86AudioPlay */
/* 165, 0x0a5 */ 0x1008FF16, /* XF86AudioPrev */
/* 166, 0x0a6 */ 0x1008FF15, /* XF86AudioStop */
/* 167, 0x0a7 */ 0x1008FF1C, /* XF86AudioRecord */
/* 168, 0x0a8 */ 0x1008FF3E, /* XF86AudioRewind */
/* 169, 0x0a9 */ 0x1008FF6E, /* XF86Phone */
/* 170, 0x0aa */ 0x0, /* NoSymbol */
/* 171, 0x0ab */ 0x1008FF81, /* XF86Tools */
/* 172, 0x0ac */ 0x1008FF18, /* XF86HomePage */
/* 173, 0x0ad */ 0x1008FF73, /* XF86Reload */
/* 174, 0x0ae */ 0x1008FF56, /* XF86Close */
/* 175, 0x0af */ 0x0, /* NoSymbol */
/* 176, 0x0b0 */ 0x0, /* NoSymbol */
/* 177, 0x0b1 */ 0x1008FF78, /* XF86ScrollUp */
/* 178, 0x0b2 */ 0x1008FF79, /* XF86ScrollDown */
/* 179, 0x0b3 */ 0x28, /* parenleft */
/* 180, 0x0b4 */ 0x29, /* parenright */
/* 181, 0x0b5 */ 0x1008FF68, /* XF86New */
/* 182, 0x0b6 */ 0xFF66, /* Redo */
/* 183, 0x0b7 */ 0xFFCA, /* F13 */
/* 184, 0x0b8 */ 0xFFCB, /* F14 */
/* 185, 0x0b9 */ 0xFFCC, /* F15 */
/* 186, 0x0ba */ 0xFFCD, /* F16 */
/* 187, 0x0bb */ 0xFFCE, /* F17 */
/* 188, 0x0bc */ 0xFFCF, /* F18 */
/* 189, 0x0bd */ 0xFFD0, /* F19 */
/* 190, 0x0be */ 0xFFD1, /* F20 */
/* 191, 0x0bf */ 0xFFD2, /* F21 */
/* 192, 0x0c0 */ 0xFFD3, /* F22 */
/* 193, 0x0c1 */ 0xFFD4, /* F23 */
/* 194, 0x0c2 */ 0xFFD5, /* F24 */
/* 195, 0x0c3 */ 0x0, /* NoSymbol */
/* 196, 0x0c4 */ 0x0, /* NoSymbol */
/* 197, 0x0c5 */ 0x0, /* NoSymbol */
/* 198, 0x0c6 */ 0x0, /* NoSymbol */
/* 199, 0x0c7 */ 0x0, /* NoSymbol */
/* 200, 0x0c8 */ 0x1008FF14, /* XF86AudioPlay */
/* 201, 0x0c9 */ 0x1008FF31, /* XF86AudioPause */
/* 202, 0x0ca */ 0x1008FF43, /* XF86Launch3 */
/* 203, 0x0cb */ 0x1008FF44, /* XF86Launch4 */
/* 204, 0x0cc */ 0x1008FF4B, /* XF86LaunchB */
/* 205, 0x0cd */ 0x1008FFA7, /* XF86Suspend */
/* 206, 0x0ce */ 0x1008FF56, /* XF86Close */
/* 207, 0x0cf */ 0x1008FF14, /* XF86AudioPlay */
/* 208, 0x0d0 */ 0x1008FF97, /* XF86AudioForward */
/* 209, 0x0d1 */ 0x0, /* NoSymbol */
/* 210, 0x0d2 */ 0xFF61, /* Print */
/* 211, 0x0d3 */ 0x0, /* NoSymbol */
/* 212, 0x0d4 */ 0x1008FF8F, /* XF86WebCam */
/* 213, 0x0d5 */ 0x1008FFB6, /* XF86AudioPreset */
/* 214, 0x0d6 */ 0x0, /* NoSymbol */
/* 215, 0x0d7 */ 0x1008FF19, /* XF86Mail */
/* 216, 0x0d8 */ 0x1008FF8E, /* XF86Messenger */
/* 217, 0x0d9 */ 0x1008FF1B, /* XF86Search */
/* 218, 0x0da */ 0x1008FF5F, /* XF86Go */
/* 219, 0x0db */ 0x1008FF3C, /* XF86Finance */
/* 220, 0x0dc */ 0x1008FF5E, /* XF86Game */
/* 221, 0x0dd */ 0x1008FF36, /* XF86Shop */
/* 222, 0x0de */ 0x0, /* NoSymbol */
/* 223, 0x0df */ 0xFF69, /* Cancel */
/* 224, 0x0e0 */ 0x1008FF03, /* XF86MonBrightnessDown */
/* 225, 0x0e1 */ 0x1008FF02, /* XF86MonBrightnessUp */
/* 226, 0x0e2 */ 0x1008FF32, /* XF86AudioMedia */
/* 227, 0x0e3 */ 0x1008FF59, /* XF86Display */
/* 228, 0x0e4 */ 0x1008FF04, /* XF86KbdLightOnOff */
/* 229, 0x0e5 */ 0x1008FF06, /* XF86KbdBrightnessDown */
/* 230, 0x0e6 */ 0x1008FF05, /* XF86KbdBrightnessUp */
/* 231, 0x0e7 */ 0x1008FF7B, /* XF86Send */
/* 232, 0x0e8 */ 0x1008FF72, /* XF86Reply */
/* 233, 0x0e9 */ 0x1008FF90, /* XF86MailForward */
/* 234, 0x0ea */ 0x1008FF77, /* XF86Save */
/* 235, 0x0eb */ 0x1008FF5B, /* XF86Documents */
/* 236, 0x0ec */ 0x1008FF93, /* XF86Battery */
/* 237, 0x0ed */ 0x1008FF94, /* XF86Bluetooth */
/* 238, 0x0ee */ 0x1008FF95, /* XF86WLAN */
/* 239, 0x0ef */ 0x1008FF96, /* XF86UWB */
/* 240, 0x0f0 */ 0x0, /* NoSymbol */
/* 241, 0x0f1 */ 0x1008FE22, /* XF86Next_VMode */
/* 242, 0x0f2 */ 0x1008FE23, /* XF86Prev_VMode */
/* 243, 0x0f3 */ 0x1008FF07, /* XF86MonBrightnessCycle */
/* 244, 0x0f4 */ 0x100810F4, /* XF86BrightnessAuto */
/* 245, 0x0f5 */ 0x100810F5, /* XF86DisplayOff */
/* 246, 0x0f6 */ 0x1008FFB4, /* XF86WWAN */
/* 247, 0x0f7 */ 0x1008FFB5, /* XF86RFKill */
};
#if 0 /* Here is a script to generate the ExtendedLinuxKeycodeKeysyms table */
#!/bin/bash
function process_line
{
sym=$(echo "$1" | awk '{print $3}')
code=$(echo "$1" | sed 's,.*_EVDEVK(\(0x[0-9A-Fa-f]*\)).*,\1,')
value=$(egrep "#define ${sym}\s" -R /usr/include/X11 | awk '{print $3}')
printf " { 0x%.8X, 0x%.3x }, /* $sym */\n" $value $code
}
fgrep "/* Use: " /usr/include/xkbcommon/xkbcommon-keysyms.h | fgrep _EVDEVK | while read line; do
process_line "$line"
done
#endif
static const struct {
Uint32 keysym;
int linux_keycode;
} ExtendedLinuxKeycodeKeysyms[] = {
{ 0x1008FF2C, 0x0a2 }, /* XF86XK_Eject */
{ 0x1008FF68, 0x0b5 }, /* XF86XK_New */
{ 0x0000FF66, 0x0b6 }, /* XK_Redo */
{ 0x1008FF4B, 0x0cc }, /* XF86XK_LaunchB */
{ 0x1008FF59, 0x0e3 }, /* XF86XK_Display */
{ 0x1008FF04, 0x0e4 }, /* XF86XK_KbdLightOnOff */
{ 0x1008FF06, 0x0e5 }, /* XF86XK_KbdBrightnessDown */
{ 0x1008FF05, 0x0e6 }, /* XF86XK_KbdBrightnessUp */
{ 0x1008FF7B, 0x0e7 }, /* XF86XK_Send */
{ 0x1008FF72, 0x0e8 }, /* XF86XK_Reply */
{ 0x1008FF90, 0x0e9 }, /* XF86XK_MailForward */
{ 0x1008FF77, 0x0ea }, /* XF86XK_Save */
{ 0x1008FF5B, 0x0eb }, /* XF86XK_Documents */
{ 0x1008FF93, 0x0ec }, /* XF86XK_Battery */
{ 0x1008FF94, 0x0ed }, /* XF86XK_Bluetooth */
{ 0x1008FF95, 0x0ee }, /* XF86XK_WLAN */
{ 0x1008FF96, 0x0ef }, /* XF86XK_UWB */
{ 0x1008FE22, 0x0f1 }, /* XF86XK_Next_VMode */
{ 0x1008FE23, 0x0f2 }, /* XF86XK_Prev_VMode */
{ 0x1008FF07, 0x0f3 }, /* XF86XK_MonBrightnessCycle */
{ 0x1008FFB4, 0x0f6 }, /* XF86XK_WWAN */
{ 0x1008FFB5, 0x0f7 }, /* XF86XK_RFKill */
{ 0x1008FFB2, 0x0f8 }, /* XF86XK_AudioMicMute */
{ 0x1008FF9C, 0x173 }, /* XF86XK_CycleAngle */
{ 0x1008FFB8, 0x174 }, /* XF86XK_FullScreen */
{ 0x1008FF87, 0x189 }, /* XF86XK_Video */
{ 0x1008FF20, 0x18d }, /* XF86XK_Calendar */
{ 0x1008FF99, 0x19a }, /* XF86XK_AudioRandomPlay */
{ 0x1008FF5E, 0x1a1 }, /* XF86XK_Game */
{ 0x1008FF8B, 0x1a2 }, /* XF86XK_ZoomIn */
{ 0x1008FF8C, 0x1a3 }, /* XF86XK_ZoomOut */
{ 0x1008FF89, 0x1a5 }, /* XF86XK_Word */
{ 0x1008FF5C, 0x1a7 }, /* XF86XK_Excel */
{ 0x1008FF69, 0x1ab }, /* XF86XK_News */
{ 0x1008FF8E, 0x1ae }, /* XF86XK_Messenger */
{ 0x1008FF61, 0x1b1 }, /* XF86XK_LogOff */
{ 0x00000024, 0x1b2 }, /* XK_dollar */
{ 0x000020AC, 0x1b3 }, /* XK_EuroSign */
{ 0x1008FF9D, 0x1b4 }, /* XF86XK_FrameBack */
{ 0x1008FF9E, 0x1b5 }, /* XF86XK_FrameForward */
{ 0x0000FFF1, 0x1f1 }, /* XK_braille_dot_1 */
{ 0x0000FFF2, 0x1f2 }, /* XK_braille_dot_2 */
{ 0x0000FFF3, 0x1f3 }, /* XK_braille_dot_3 */
{ 0x0000FFF4, 0x1f4 }, /* XK_braille_dot_4 */
{ 0x0000FFF5, 0x1f5 }, /* XK_braille_dot_5 */
{ 0x0000FFF6, 0x1f6 }, /* XK_braille_dot_6 */
{ 0x0000FFF7, 0x1f7 }, /* XK_braille_dot_7 */
{ 0x0000FFF8, 0x1f8 }, /* XK_braille_dot_8 */
{ 0x0000FFF9, 0x1f9 }, /* XK_braille_dot_9 */
{ 0x0000FFF1, 0x1fa }, /* XK_braille_dot_1 */
{ 0x1008FFA9, 0x212 }, /* XF86XK_TouchpadToggle */
{ 0x1008FFB0, 0x213 }, /* XF86XK_TouchpadOn */
{ 0x1008FFB1, 0x214 }, /* XF86XK_TouchpadOff */
{ 0x1008FFB7, 0x231 }, /* XF86XK_RotationLockToggle */
{ 0x0000FE08, 0x248 }, /* XK_ISO_Next_Group */
};
/* *INDENT-ON* */ /* clang-format on */
SDL_Scancode
SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode)
{
int i;
Uint32 linux_keycode = 0;
/* First check our custom list */
for (i = 0; i < SDL_arraysize(KeySymToSDLScancode); ++i) {
if (keysym == KeySymToSDLScancode[i].keysym) {
return KeySymToSDLScancode[i].scancode;
}
}
if (keysym >= 0x41 && keysym <= 0x5a) {
/* Normalize alphabetic keysyms to the lowercase form */
keysym += 0x20;
} else if (keysym >= 0x10081000 && keysym <= 0x10081FFF) {
/* The rest of the keysyms map to Linux keycodes, so use that mapping
* Per xkbcommon-keysyms.h, this is actually a linux keycode.
*/
linux_keycode = (keysym - 0x10081000);
}
if (!linux_keycode) {
/* See if this keysym is an exact match in our table */
i = (keycode - 8);
if (i >= 0 && i < SDL_arraysize(LinuxKeycodeKeysyms) && keysym == LinuxKeycodeKeysyms[i]) {
linux_keycode = i;
} else {
/* Scan the table for this keysym */
for (i = 0; i < SDL_arraysize(LinuxKeycodeKeysyms); ++i) {
if (keysym == LinuxKeycodeKeysyms[i]) {
linux_keycode = i;
break;
}
}
}
}
if (!linux_keycode) {
/* Scan the extended table for this keysym */
for (i = 0; i < SDL_arraysize(ExtendedLinuxKeycodeKeysyms); ++i) {
if (keysym == ExtendedLinuxKeycodeKeysyms[i].keysym) {
linux_keycode = ExtendedLinuxKeycodeKeysyms[i].linux_keycode;
break;
}
}
}
return SDL_GetScancodeFromTable(SDL_SCANCODE_TABLE_LINUX, linux_keycode);
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -18,16 +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"
#ifndef SDL_os2mouse_h_
#define SDL_os2mouse_h_
#ifndef SDL_keysym_to_scancode_c_h_
#define SDL_keysym_to_scancode_c_h_
extern HPOINTER hptrCursor;
#include "SDL_scancode.h"
extern void OS2_InitMouse(_THIS, ULONG hab);
extern void OS2_QuitMouse(_THIS);
/* This function only correctly maps letters and numbers for keyboards in US QWERTY layout */
extern SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode);
#endif /* SDL_os2mouse_h_ */
#endif /* SDL_keysym_to_scancode_c_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -31,10 +31,6 @@
#if defined(__WIN32__) || defined(__GDK__)
#include "../core/windows/SDL_windows.h" // For GetDoubleClickTime()
#endif
#if defined(__OS2__)
#define INCL_WIN
#include <os2.h>
#endif
/* #define DEBUG_MOUSE */
@@ -57,8 +53,6 @@ SDL_MouseDoubleClickTimeChanged(void *userdata, const char *name, const char *ol
} else {
#if defined(__WIN32__) || defined(__WINGDK__)
mouse->double_click_time = GetDoubleClickTime();
#elif defined(__OS2__)
mouse->double_click_time = WinQuerySysValue(HWND_DESKTOP, SV_DBLCLKTIME);
#else
mouse->double_click_time = 500;
#endif
@@ -266,6 +260,30 @@ SDL_GetMouseFocus(void)
return mouse->focus;
}
/* TODO RECONNECT: Hello from the Wayland video driver!
* This was once removed from SDL, but it's been added back in comment form
* because we will need it when Wayland adds compositor reconnect support.
* If you need this before we do, great! Otherwise, leave this alone, we'll
* uncomment it at the right time.
* -flibit
*/
#if 0
void
SDL_ResetMouse(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
Uint32 buttonState = GetButtonState(mouse, SDL_FALSE);
int i;
for (i = 1; i <= sizeof(buttonState)*8; ++i) {
if (buttonState & SDL_BUTTON(i)) {
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, i);
}
}
SDL_assert(GetButtonState(mouse, SDL_FALSE) == 0);
}
#endif /* 0 */
void
SDL_SetMouseFocus(SDL_Window * window)
{
@@ -868,6 +886,8 @@ SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, float x, float y, S
event.wheel.preciseX = x;
event.wheel.preciseY = y;
event.wheel.direction = (Uint32)direction;
event.wheel.mouseX = mouse->x;
event.wheel.mouseY = mouse->y;
posted = (SDL_PushEvent(&event) > 0);
}
return posted;

View File

@@ -25,8 +25,6 @@
#include "SDL_mouse.h"
typedef Uint32 SDL_MouseID;
struct SDL_Cursor
{
struct SDL_Cursor *next;
@@ -164,6 +162,11 @@ extern int SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, float x,
/* Warp the mouse within the window, potentially overriding relative mode */
extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, int x, int y, SDL_bool ignore_relative_mode);
/* TODO RECONNECT: Set mouse state to "zero" */
#if 0
extern void SDL_ResetMouse(void);
#endif /* 0 */
/* Shutdown the mouse subsystem */
extern void SDL_MouseQuit(void);

View File

@@ -0,0 +1,73 @@
/*
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.
*/
#include "../SDL_internal.h"
#if SDL_INPUT_LINUXEV || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_X11
#include "SDL_scancode_tables_c.h"
#include "scancodes_darwin.h"
#include "scancodes_linux.h"
#include "scancodes_xfree86.h"
static const struct
{
SDL_ScancodeTable table;
SDL_Scancode const *scancodes;
int num_entries;
} SDL_scancode_tables[] = {
{ SDL_SCANCODE_TABLE_DARWIN, darwin_scancode_table, SDL_arraysize(darwin_scancode_table) },
{ SDL_SCANCODE_TABLE_LINUX, linux_scancode_table, SDL_arraysize(linux_scancode_table) },
{ SDL_SCANCODE_TABLE_XFREE86_1, xfree86_scancode_table, SDL_arraysize(xfree86_scancode_table) },
{ SDL_SCANCODE_TABLE_XFREE86_2, xfree86_scancode_table2, SDL_arraysize(xfree86_scancode_table2) },
{ SDL_SCANCODE_TABLE_XVNC, xvnc_scancode_table, SDL_arraysize(xvnc_scancode_table) },
};
const SDL_Scancode *SDL_GetScancodeTable(SDL_ScancodeTable table, int *num_entries)
{
int i;
for (i = 0; i < SDL_arraysize(SDL_scancode_tables); ++i) {
if (table == SDL_scancode_tables[i].table) {
*num_entries = SDL_scancode_tables[i].num_entries;
return SDL_scancode_tables[i].scancodes;
}
}
*num_entries = 0;
return NULL;
}
SDL_Scancode SDL_GetScancodeFromTable(SDL_ScancodeTable table, int keycode)
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
int num_entries;
const SDL_Scancode *scancodes = SDL_GetScancodeTable(table, &num_entries);
if (keycode >= 0 && keycode < num_entries) {
scancode = scancodes[keycode];
}
return scancode;
}
#endif /* SDL_INPUT_LINUXEV || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,37 @@
/*
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.
*/
#include "../SDL_internal.h"
#include "../../include/SDL_scancode.h"
typedef enum
{
SDL_SCANCODE_TABLE_DARWIN,
SDL_SCANCODE_TABLE_LINUX,
SDL_SCANCODE_TABLE_XFREE86_1,
SDL_SCANCODE_TABLE_XFREE86_2,
SDL_SCANCODE_TABLE_XVNC,
} SDL_ScancodeTable;
extern const SDL_Scancode *SDL_GetScancodeTable(SDL_ScancodeTable table, int *num_entries);
extern SDL_Scancode SDL_GetScancodeFromTable(SDL_ScancodeTable table, int keycode);
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -456,10 +456,16 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
void
SDL_DelTouch(SDL_TouchID id)
{
int i;
int index = SDL_GetTouchIndex(id);
SDL_Touch *touch = SDL_GetTouch(id);
int i, index;
SDL_Touch *touch;
if (SDL_num_touch == 0) {
/* We've already cleaned up, we won't find this device */
return;
}
index = SDL_GetTouchIndex(id);
touch = SDL_GetTouch(id);
if (!touch) {
return;
}

View File

@@ -157,3 +157,5 @@ static const SDL_Scancode darwin_scancode_table[] = {
/* 127 */ SDL_SCANCODE_POWER
};
/* *INDENT-ON* */ /* clang-format on */
/* vi: set ts=4 sw=4 expandtab: */

File diff suppressed because it is too large Load Diff

View File

@@ -53,3 +53,5 @@ static const SDL_Scancode windows_scancode_table[] =
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL4, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL5, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_INTERNATIONAL3, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN /* 7 */
};
/* *INDENT-ON* */ /* clang-format on */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -179,247 +179,256 @@ static const SDL_Scancode xfree86_scancode_table[] = {
/* 146 */ SDL_SCANCODE_CUT,
};
/* for wireless usb keyboard (manufacturer TRUST) without numpad. */
/* This is largely identical to the Linux keycode mapping */
static const SDL_Scancode xfree86_scancode_table2[] = {
/* 0 */ SDL_SCANCODE_UNKNOWN,
/* 1 */ SDL_SCANCODE_ESCAPE,
/* 2 */ SDL_SCANCODE_1,
/* 3 */ SDL_SCANCODE_2,
/* 4 */ SDL_SCANCODE_3,
/* 5 */ SDL_SCANCODE_4,
/* 6 */ SDL_SCANCODE_5,
/* 7 */ SDL_SCANCODE_6,
/* 8 */ SDL_SCANCODE_7,
/* 9 */ SDL_SCANCODE_8,
/* 10 */ SDL_SCANCODE_9,
/* 11 */ SDL_SCANCODE_0,
/* 12 */ SDL_SCANCODE_MINUS,
/* 13 */ SDL_SCANCODE_EQUALS,
/* 14 */ SDL_SCANCODE_BACKSPACE,
/* 15 */ SDL_SCANCODE_TAB,
/* 16 */ SDL_SCANCODE_Q,
/* 17 */ SDL_SCANCODE_W,
/* 18 */ SDL_SCANCODE_E,
/* 19 */ SDL_SCANCODE_R,
/* 20 */ SDL_SCANCODE_T,
/* 21 */ SDL_SCANCODE_Y,
/* 22 */ SDL_SCANCODE_U,
/* 23 */ SDL_SCANCODE_I,
/* 24 */ SDL_SCANCODE_O,
/* 25 */ SDL_SCANCODE_P,
/* 26 */ SDL_SCANCODE_LEFTBRACKET,
/* 27 */ SDL_SCANCODE_RIGHTBRACKET,
/* 28 */ SDL_SCANCODE_RETURN,
/* 29 */ SDL_SCANCODE_LCTRL,
/* 30 */ SDL_SCANCODE_A,
/* 31 */ SDL_SCANCODE_S,
/* 32 */ SDL_SCANCODE_D,
/* 33 */ SDL_SCANCODE_F,
/* 34 */ SDL_SCANCODE_G,
/* 35 */ SDL_SCANCODE_H,
/* 36 */ SDL_SCANCODE_J,
/* 37 */ SDL_SCANCODE_K,
/* 38 */ SDL_SCANCODE_L,
/* 39 */ SDL_SCANCODE_SEMICOLON,
/* 40 */ SDL_SCANCODE_APOSTROPHE,
/* 41 */ SDL_SCANCODE_GRAVE,
/* 42 */ SDL_SCANCODE_LSHIFT,
/* 43 */ SDL_SCANCODE_BACKSLASH,
/* 44 */ SDL_SCANCODE_Z,
/* 45 */ SDL_SCANCODE_X,
/* 46 */ SDL_SCANCODE_C,
/* 47 */ SDL_SCANCODE_V,
/* 48 */ SDL_SCANCODE_B,
/* 49 */ SDL_SCANCODE_N,
/* 50 */ SDL_SCANCODE_M,
/* 51 */ SDL_SCANCODE_COMMA,
/* 52 */ SDL_SCANCODE_PERIOD,
/* 53 */ SDL_SCANCODE_SLASH,
/* 54 */ SDL_SCANCODE_RSHIFT,
/* 55 */ SDL_SCANCODE_KP_MULTIPLY,
/* 56 */ SDL_SCANCODE_LALT,
/* 57 */ SDL_SCANCODE_SPACE,
/* 58 */ SDL_SCANCODE_CAPSLOCK,
/* 59 */ SDL_SCANCODE_F1,
/* 60 */ SDL_SCANCODE_F2,
/* 61 */ SDL_SCANCODE_F3,
/* 62 */ SDL_SCANCODE_F4,
/* 63 */ SDL_SCANCODE_F5,
/* 64 */ SDL_SCANCODE_F6,
/* 65 */ SDL_SCANCODE_F7,
/* 66 */ SDL_SCANCODE_F8,
/* 67 */ SDL_SCANCODE_F9,
/* 68 */ SDL_SCANCODE_F10,
/* 69 */ SDL_SCANCODE_NUMLOCKCLEAR,
/* 70 */ SDL_SCANCODE_SCROLLLOCK,
/* 71 */ SDL_SCANCODE_KP_7,
/* 72 */ SDL_SCANCODE_KP_8,
/* 73 */ SDL_SCANCODE_KP_9,
/* 74 */ SDL_SCANCODE_KP_MINUS,
/* 75 */ SDL_SCANCODE_KP_4,
/* 76 */ SDL_SCANCODE_KP_5,
/* 77 */ SDL_SCANCODE_KP_6,
/* 78 */ SDL_SCANCODE_KP_PLUS,
/* 79 */ SDL_SCANCODE_KP_1,
/* 80 */ SDL_SCANCODE_KP_2,
/* 81 */ SDL_SCANCODE_KP_3,
/* 82 */ SDL_SCANCODE_KP_0,
/* 83 */ SDL_SCANCODE_KP_PERIOD,
/* 84 */ SDL_SCANCODE_SYSREQ, /* ???? */
/* 85 */ SDL_SCANCODE_MODE, /* ???? */
/* 86 */ SDL_SCANCODE_NONUSBACKSLASH,
/* 87 */ SDL_SCANCODE_F11,
/* 88 */ SDL_SCANCODE_F12,
/* 89 */ SDL_SCANCODE_INTERNATIONAL1, /* \_ */
/* 90 */ SDL_SCANCODE_UNKNOWN, /* Katakana */
/* 91 */ SDL_SCANCODE_UNKNOWN, /* Hiragana */
/* 92 */ SDL_SCANCODE_INTERNATIONAL4, /* Henkan_Mode */
/* 93 */ SDL_SCANCODE_INTERNATIONAL2, /* Hiragana_Katakana */
/* 94 */ SDL_SCANCODE_INTERNATIONAL5, /* Muhenkan */
/* 95 */ SDL_SCANCODE_UNKNOWN,
/* 96 */ SDL_SCANCODE_KP_ENTER,
/* 97 */ SDL_SCANCODE_RCTRL,
/* 98 */ SDL_SCANCODE_KP_DIVIDE,
/* 99 */ SDL_SCANCODE_PRINTSCREEN,
/* 100 */ SDL_SCANCODE_RALT, /* ISO_Level3_Shift, ALTGR, RALT */
/* 101 */ SDL_SCANCODE_UNKNOWN, /* Linefeed */
/* 102 */ SDL_SCANCODE_HOME,
/* 103 */ SDL_SCANCODE_UP,
/* 104 */ SDL_SCANCODE_PAGEUP,
/* 105 */ SDL_SCANCODE_LEFT,
/* 106 */ SDL_SCANCODE_RIGHT,
/* 107 */ SDL_SCANCODE_END,
/* 108 */ SDL_SCANCODE_DOWN,
/* 109 */ SDL_SCANCODE_PAGEDOWN,
/* 110 */ SDL_SCANCODE_INSERT,
/* 111 */ SDL_SCANCODE_DELETE,
/* 112 */ SDL_SCANCODE_UNKNOWN,
/* 113 */ SDL_SCANCODE_MUTE,
/* 114 */ SDL_SCANCODE_VOLUMEDOWN,
/* 115 */ SDL_SCANCODE_VOLUMEUP,
/* 116 */ SDL_SCANCODE_POWER,
/* 117 */ SDL_SCANCODE_KP_EQUALS,
/* 118 */ SDL_SCANCODE_KP_PLUSMINUS, /* plusminus */
/* 119 */ SDL_SCANCODE_PAUSE,
/* 120 */ SDL_SCANCODE_UNKNOWN, /* XF86LaunchA */
/* 121 */ SDL_SCANCODE_KP_COMMA, /* KP_Decimal */
/* 122 */ SDL_SCANCODE_LANG1, /* Hangul */
/* 123 */ SDL_SCANCODE_LANG2, /* Hangul_Hanja */
/* 124 */ SDL_SCANCODE_INTERNATIONAL3, /* Yen */
/* 125 */ SDL_SCANCODE_LGUI,
/* 126 */ SDL_SCANCODE_RGUI,
/* 127 */ SDL_SCANCODE_APPLICATION,
/* 128 */ SDL_SCANCODE_CANCEL,
/* 129 */ SDL_SCANCODE_AGAIN,
/* 130 */ SDL_SCANCODE_UNKNOWN, /* SunProps */
/* 131 */ SDL_SCANCODE_UNDO,
/* 132 */ SDL_SCANCODE_UNKNOWN, /* SunFront */
/* 133 */ SDL_SCANCODE_COPY,
/* 134 */ SDL_SCANCODE_UNKNOWN, /* SunOpen */
/* 135 */ SDL_SCANCODE_PASTE,
/* 136 */ SDL_SCANCODE_FIND,
/* 137 */ SDL_SCANCODE_CUT,
/* 138 */ SDL_SCANCODE_HELP,
/* 139 */ SDL_SCANCODE_MENU, /* XF86MenuKB */
/* 140 */ SDL_SCANCODE_CALCULATOR,
/* 141 */ SDL_SCANCODE_UNKNOWN,
/* 142 */ SDL_SCANCODE_SLEEP,
/* 143 */ SDL_SCANCODE_UNKNOWN, /* XF86WakeUp */
/* 144 */ SDL_SCANCODE_UNKNOWN, /* XF86Explorer */
/* 145 */ SDL_SCANCODE_UNKNOWN, /* XF86Send */
/* 146 */ SDL_SCANCODE_UNKNOWN,
/* 147 */ SDL_SCANCODE_UNKNOWN, /* XF86Xfer */
/* 148 */ SDL_SCANCODE_APP1, /* XF86Launch1 */
/* 149 */ SDL_SCANCODE_APP2, /* XF86Launch2 */
/* 150 */ SDL_SCANCODE_WWW,
/* 151 */ SDL_SCANCODE_UNKNOWN, /* XF86DOS */
/* 152 */ SDL_SCANCODE_UNKNOWN, /* XF86ScreenSaver */
/* 153 */ SDL_SCANCODE_UNKNOWN,
/* 154 */ SDL_SCANCODE_UNKNOWN, /* XF86RotateWindows */
/* 155 */ SDL_SCANCODE_MAIL,
/* 156 */ SDL_SCANCODE_AC_BOOKMARKS, /* XF86Favorites */
/* 157 */ SDL_SCANCODE_COMPUTER,
/* 158 */ SDL_SCANCODE_AC_BACK,
/* 159 */ SDL_SCANCODE_AC_FORWARD,
/* 160 */ SDL_SCANCODE_UNKNOWN,
/* 161 */ SDL_SCANCODE_EJECT,
/* 162 */ SDL_SCANCODE_EJECT,
/* 163 */ SDL_SCANCODE_AUDIONEXT,
/* 164 */ SDL_SCANCODE_AUDIOPLAY,
/* 165 */ SDL_SCANCODE_AUDIOPREV,
/* 166 */ SDL_SCANCODE_AUDIOSTOP,
/* 167 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioRecord */
/* 168 */ SDL_SCANCODE_AUDIOREWIND, /* XF86AudioRewind */
/* 169 */ SDL_SCANCODE_UNKNOWN, /* XF86Phone */
/* 170 */ SDL_SCANCODE_UNKNOWN,
/* 171 */ SDL_SCANCODE_F13, /* XF86Tools */
/* 172 */ SDL_SCANCODE_AC_HOME,
/* 173 */ SDL_SCANCODE_AC_REFRESH,
/* 174 */ SDL_SCANCODE_UNKNOWN, /* XF86Close */
/* 175 */ SDL_SCANCODE_UNKNOWN,
/* 176 */ SDL_SCANCODE_UNKNOWN,
/* 177 */ SDL_SCANCODE_UNKNOWN, /* XF86ScrollUp */
/* 178 */ SDL_SCANCODE_UNKNOWN, /* XF86ScrollDown */
/* 179 */ SDL_SCANCODE_KP_LEFTPAREN, /* parenleft */
/* 180 */ SDL_SCANCODE_KP_RIGHTPAREN, /* parenright */
/* 181 */ SDL_SCANCODE_UNKNOWN, /* XF86New */
/* 182 */ SDL_SCANCODE_AGAIN,
/* 183 */ SDL_SCANCODE_F13, /* XF86Tools */
/* 184 */ SDL_SCANCODE_F14, /* XF86Launch5 */
/* 185 */ SDL_SCANCODE_F15, /* XF86Launch6 */
/* 186 */ SDL_SCANCODE_F16, /* XF86Launch7 */
/* 187 */ SDL_SCANCODE_F17, /* XF86Launch8 */
/* 188 */ SDL_SCANCODE_F18, /* XF86Launch9 */
/* 189 */ SDL_SCANCODE_F19, /* null keysym */
/* 190 */ SDL_SCANCODE_F20,
/* 191 */ SDL_SCANCODE_UNKNOWN,
/* 192 */ SDL_SCANCODE_UNKNOWN, /* XF86TouchpadToggle */
/* 193 */ SDL_SCANCODE_UNKNOWN,
/* 194 */ SDL_SCANCODE_UNKNOWN,
/* 195 */ SDL_SCANCODE_MODE,
/* 196 */ SDL_SCANCODE_UNKNOWN,
/* 197 */ SDL_SCANCODE_UNKNOWN,
/* 198 */ SDL_SCANCODE_UNKNOWN,
/* 199 */ SDL_SCANCODE_UNKNOWN,
/* 200 */ SDL_SCANCODE_AUDIOPLAY,
/* 201 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioPause */
/* 202 */ SDL_SCANCODE_UNKNOWN, /* XF86Launch3 */
/* 203 */ SDL_SCANCODE_UNKNOWN, /* XF86Launch4 */
/* 204 */ SDL_SCANCODE_UNKNOWN, /* XF86LaunchB */
/* 205 */ SDL_SCANCODE_UNKNOWN, /* XF86Suspend */
/* 206 */ SDL_SCANCODE_UNKNOWN, /* XF86Close */
/* 207 */ SDL_SCANCODE_AUDIOPLAY,
/* 208 */ SDL_SCANCODE_AUDIOFASTFORWARD,
/* 209 */ SDL_SCANCODE_UNKNOWN,
/* 210 */ SDL_SCANCODE_PRINTSCREEN,
/* 211 */ SDL_SCANCODE_UNKNOWN,
/* 212 */ SDL_SCANCODE_UNKNOWN, /* XF86WebCam */
/* 213 */ SDL_SCANCODE_UNKNOWN,
/* 214 */ SDL_SCANCODE_UNKNOWN,
/* 215 */ SDL_SCANCODE_MAIL,
/* 216 */ SDL_SCANCODE_UNKNOWN,
/* 217 */ SDL_SCANCODE_AC_SEARCH,
/* 218 */ SDL_SCANCODE_UNKNOWN,
/* 219 */ SDL_SCANCODE_UNKNOWN, /* XF86Finance */
/* 220 */ SDL_SCANCODE_UNKNOWN,
/* 221 */ SDL_SCANCODE_UNKNOWN, /* XF86Shop */
/* 222 */ SDL_SCANCODE_UNKNOWN,
/* 223 */ SDL_SCANCODE_STOP,
/* 224 */ SDL_SCANCODE_BRIGHTNESSDOWN,
/* 225 */ SDL_SCANCODE_BRIGHTNESSUP,
/* 226 */ SDL_SCANCODE_MEDIASELECT,
/* 227 */ SDL_SCANCODE_DISPLAYSWITCH,
/* 228 */ SDL_SCANCODE_KBDILLUMTOGGLE,
/* 229 */ SDL_SCANCODE_KBDILLUMDOWN,
/* 230 */ SDL_SCANCODE_KBDILLUMUP,
/* 231 */ SDL_SCANCODE_UNKNOWN, /* XF86Send */
/* 232 */ SDL_SCANCODE_UNKNOWN, /* XF86Reply */
/* 233 */ SDL_SCANCODE_UNKNOWN, /* XF86MailForward */
/* 234 */ SDL_SCANCODE_UNKNOWN, /* XF86Save */
/* 235 */ SDL_SCANCODE_UNKNOWN, /* XF86Documents */
/* 236 */ SDL_SCANCODE_UNKNOWN, /* XF86Battery */
/* 237 */ SDL_SCANCODE_UNKNOWN, /* XF86Bluetooth */
/* 238 */ SDL_SCANCODE_UNKNOWN, /* XF86WLAN */
/* 0, 0x000 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 1, 0x001 */ SDL_SCANCODE_ESCAPE, /* Escape */
/* 2, 0x002 */ SDL_SCANCODE_1, /* 1 */
/* 3, 0x003 */ SDL_SCANCODE_2, /* 2 */
/* 4, 0x004 */ SDL_SCANCODE_3, /* 3 */
/* 5, 0x005 */ SDL_SCANCODE_4, /* 4 */
/* 6, 0x006 */ SDL_SCANCODE_5, /* 5 */
/* 7, 0x007 */ SDL_SCANCODE_6, /* 6 */
/* 8, 0x008 */ SDL_SCANCODE_7, /* 7 */
/* 9, 0x009 */ SDL_SCANCODE_8, /* 8 */
/* 10, 0x00a */ SDL_SCANCODE_9, /* 9 */
/* 11, 0x00b */ SDL_SCANCODE_0, /* 0 */
/* 12, 0x00c */ SDL_SCANCODE_MINUS, /* minus */
/* 13, 0x00d */ SDL_SCANCODE_EQUALS, /* equal */
/* 14, 0x00e */ SDL_SCANCODE_BACKSPACE, /* BackSpace */
/* 15, 0x00f */ SDL_SCANCODE_TAB, /* Tab */
/* 16, 0x010 */ SDL_SCANCODE_Q, /* q */
/* 17, 0x011 */ SDL_SCANCODE_W, /* w */
/* 18, 0x012 */ SDL_SCANCODE_E, /* e */
/* 19, 0x013 */ SDL_SCANCODE_R, /* r */
/* 20, 0x014 */ SDL_SCANCODE_T, /* t */
/* 21, 0x015 */ SDL_SCANCODE_Y, /* y */
/* 22, 0x016 */ SDL_SCANCODE_U, /* u */
/* 23, 0x017 */ SDL_SCANCODE_I, /* i */
/* 24, 0x018 */ SDL_SCANCODE_O, /* o */
/* 25, 0x019 */ SDL_SCANCODE_P, /* p */
/* 26, 0x01a */ SDL_SCANCODE_LEFTBRACKET, /* bracketleft */
/* 27, 0x01b */ SDL_SCANCODE_RIGHTBRACKET, /* bracketright */
/* 28, 0x01c */ SDL_SCANCODE_RETURN, /* Return */
/* 29, 0x01d */ SDL_SCANCODE_LCTRL, /* Control_L */
/* 30, 0x01e */ SDL_SCANCODE_A, /* a */
/* 31, 0x01f */ SDL_SCANCODE_S, /* s */
/* 32, 0x020 */ SDL_SCANCODE_D, /* d */
/* 33, 0x021 */ SDL_SCANCODE_F, /* f */
/* 34, 0x022 */ SDL_SCANCODE_G, /* g */
/* 35, 0x023 */ SDL_SCANCODE_H, /* h */
/* 36, 0x024 */ SDL_SCANCODE_J, /* j */
/* 37, 0x025 */ SDL_SCANCODE_K, /* k */
/* 38, 0x026 */ SDL_SCANCODE_L, /* l */
/* 39, 0x027 */ SDL_SCANCODE_SEMICOLON, /* semicolon */
/* 40, 0x028 */ SDL_SCANCODE_APOSTROPHE, /* apostrophe */
/* 41, 0x029 */ SDL_SCANCODE_GRAVE, /* grave */
/* 42, 0x02a */ SDL_SCANCODE_LSHIFT, /* Shift_L */
/* 43, 0x02b */ SDL_SCANCODE_BACKSLASH, /* backslash */
/* 44, 0x02c */ SDL_SCANCODE_Z, /* z */
/* 45, 0x02d */ SDL_SCANCODE_X, /* x */
/* 46, 0x02e */ SDL_SCANCODE_C, /* c */
/* 47, 0x02f */ SDL_SCANCODE_V, /* v */
/* 48, 0x030 */ SDL_SCANCODE_B, /* b */
/* 49, 0x031 */ SDL_SCANCODE_N, /* n */
/* 50, 0x032 */ SDL_SCANCODE_M, /* m */
/* 51, 0x033 */ SDL_SCANCODE_COMMA, /* comma */
/* 52, 0x034 */ SDL_SCANCODE_PERIOD, /* period */
/* 53, 0x035 */ SDL_SCANCODE_SLASH, /* slash */
/* 54, 0x036 */ SDL_SCANCODE_RSHIFT, /* Shift_R */
/* 55, 0x037 */ SDL_SCANCODE_KP_MULTIPLY, /* KP_Multiply */
/* 56, 0x038 */ SDL_SCANCODE_LALT, /* Alt_L */
/* 57, 0x039 */ SDL_SCANCODE_SPACE, /* space */
/* 58, 0x03a */ SDL_SCANCODE_CAPSLOCK, /* Caps_Lock */
/* 59, 0x03b */ SDL_SCANCODE_F1, /* F1 */
/* 60, 0x03c */ SDL_SCANCODE_F2, /* F2 */
/* 61, 0x03d */ SDL_SCANCODE_F3, /* F3 */
/* 62, 0x03e */ SDL_SCANCODE_F4, /* F4 */
/* 63, 0x03f */ SDL_SCANCODE_F5, /* F5 */
/* 64, 0x040 */ SDL_SCANCODE_F6, /* F6 */
/* 65, 0x041 */ SDL_SCANCODE_F7, /* F7 */
/* 66, 0x042 */ SDL_SCANCODE_F8, /* F8 */
/* 67, 0x043 */ SDL_SCANCODE_F9, /* F9 */
/* 68, 0x044 */ SDL_SCANCODE_F10, /* F10 */
/* 69, 0x045 */ SDL_SCANCODE_NUMLOCKCLEAR, /* Num_Lock */
/* 70, 0x046 */ SDL_SCANCODE_SCROLLLOCK, /* Scroll_Lock */
/* 71, 0x047 */ SDL_SCANCODE_KP_7, /* KP_Home */
/* 72, 0x048 */ SDL_SCANCODE_KP_8, /* KP_Up */
/* 73, 0x049 */ SDL_SCANCODE_KP_9, /* KP_Prior */
/* 74, 0x04a */ SDL_SCANCODE_KP_MINUS, /* KP_Subtract */
/* 75, 0x04b */ SDL_SCANCODE_KP_4, /* KP_Left */
/* 76, 0x04c */ SDL_SCANCODE_KP_5, /* KP_Begin */
/* 77, 0x04d */ SDL_SCANCODE_KP_6, /* KP_Right */
/* 78, 0x04e */ SDL_SCANCODE_KP_PLUS, /* KP_Add */
/* 79, 0x04f */ SDL_SCANCODE_KP_1, /* KP_End */
/* 80, 0x050 */ SDL_SCANCODE_KP_2, /* KP_Down */
/* 81, 0x051 */ SDL_SCANCODE_KP_3, /* KP_Next */
/* 82, 0x052 */ SDL_SCANCODE_KP_0, /* KP_Insert */
/* 83, 0x053 */ SDL_SCANCODE_KP_PERIOD, /* KP_Delete */
/* 84, 0x054 */ SDL_SCANCODE_RALT, /* ISO_Level3_Shift */
/* 85, 0x055 */ SDL_SCANCODE_MODE, /* ???? */
/* 86, 0x056 */ SDL_SCANCODE_NONUSBACKSLASH, /* less */
/* 87, 0x057 */ SDL_SCANCODE_F11, /* F11 */
/* 88, 0x058 */ SDL_SCANCODE_F12, /* F12 */
/* 89, 0x059 */ SDL_SCANCODE_INTERNATIONAL1, /* \_ */
/* 90, 0x05a */ SDL_SCANCODE_LANG3, /* Katakana */
/* 91, 0x05b */ SDL_SCANCODE_LANG4, /* Hiragana */
/* 92, 0x05c */ SDL_SCANCODE_INTERNATIONAL4, /* Henkan_Mode */
/* 93, 0x05d */ SDL_SCANCODE_INTERNATIONAL2, /* Hiragana_Katakana */
/* 94, 0x05e */ SDL_SCANCODE_INTERNATIONAL5, /* Muhenkan */
/* 95, 0x05f */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 96, 0x060 */ SDL_SCANCODE_KP_ENTER, /* KP_Enter */
/* 97, 0x061 */ SDL_SCANCODE_RCTRL, /* Control_R */
/* 98, 0x062 */ SDL_SCANCODE_KP_DIVIDE, /* KP_Divide */
/* 99, 0x063 */ SDL_SCANCODE_PRINTSCREEN, /* Print */
/* 100, 0x064 */ SDL_SCANCODE_RALT, /* ISO_Level3_Shift, ALTGR, RALT */
/* 101, 0x065 */ SDL_SCANCODE_UNKNOWN, /* Linefeed */
/* 102, 0x066 */ SDL_SCANCODE_HOME, /* Home */
/* 103, 0x067 */ SDL_SCANCODE_UP, /* Up */
/* 104, 0x068 */ SDL_SCANCODE_PAGEUP, /* Prior */
/* 105, 0x069 */ SDL_SCANCODE_LEFT, /* Left */
/* 106, 0x06a */ SDL_SCANCODE_RIGHT, /* Right */
/* 107, 0x06b */ SDL_SCANCODE_END, /* End */
/* 108, 0x06c */ SDL_SCANCODE_DOWN, /* Down */
/* 109, 0x06d */ SDL_SCANCODE_PAGEDOWN, /* Next */
/* 110, 0x06e */ SDL_SCANCODE_INSERT, /* Insert */
/* 111, 0x06f */ SDL_SCANCODE_DELETE, /* Delete */
/* 112, 0x070 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 113, 0x071 */ SDL_SCANCODE_MUTE, /* XF86AudioMute */
/* 114, 0x072 */ SDL_SCANCODE_VOLUMEDOWN, /* XF86AudioLowerVolume */
/* 115, 0x073 */ SDL_SCANCODE_VOLUMEUP, /* XF86AudioRaiseVolume */
/* 116, 0x074 */ SDL_SCANCODE_POWER, /* XF86PowerOff */
/* 117, 0x075 */ SDL_SCANCODE_KP_EQUALS, /* KP_Equal */
/* 118, 0x076 */ SDL_SCANCODE_KP_PLUSMINUS, /* plusminus */
/* 119, 0x077 */ SDL_SCANCODE_PAUSE, /* Pause */
/* 120, 0x078 */ SDL_SCANCODE_UNKNOWN, /* XF86LaunchA */
/* 121, 0x079 */ SDL_SCANCODE_KP_PERIOD, /* KP_Decimal */
/* 122, 0x07a */ SDL_SCANCODE_LANG1, /* Hangul */
/* 123, 0x07b */ SDL_SCANCODE_LANG2, /* Hangul_Hanja */
/* 124, 0x07c */ SDL_SCANCODE_INTERNATIONAL3, /* Yen */
/* 125, 0x07d */ SDL_SCANCODE_LGUI, /* Super_L */
/* 126, 0x07e */ SDL_SCANCODE_RGUI, /* Super_R */
/* 127, 0x07f */ SDL_SCANCODE_APPLICATION, /* Menu */
/* 128, 0x080 */ SDL_SCANCODE_CANCEL, /* Cancel */
/* 129, 0x081 */ SDL_SCANCODE_AGAIN, /* Redo */
/* 130, 0x082 */ SDL_SCANCODE_UNKNOWN, /* SunProps */
/* 131, 0x083 */ SDL_SCANCODE_UNDO, /* Undo */
/* 132, 0x084 */ SDL_SCANCODE_UNKNOWN, /* SunFront */
/* 133, 0x085 */ SDL_SCANCODE_COPY, /* XF86Copy */
/* 134, 0x086 */ SDL_SCANCODE_UNKNOWN, /* SunOpen, XF86Open */
/* 135, 0x087 */ SDL_SCANCODE_PASTE, /* XF86Paste */
/* 136, 0x088 */ SDL_SCANCODE_FIND, /* Find */
/* 137, 0x089 */ SDL_SCANCODE_CUT, /* XF86Cut */
/* 138, 0x08a */ SDL_SCANCODE_HELP, /* Help */
/* 139, 0x08b */ SDL_SCANCODE_MENU, /* XF86MenuKB */
/* 140, 0x08c */ SDL_SCANCODE_CALCULATOR, /* XF86Calculator */
/* 141, 0x08d */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 142, 0x08e */ SDL_SCANCODE_SLEEP, /* XF86Sleep */
/* 143, 0x08f */ SDL_SCANCODE_UNKNOWN, /* XF86WakeUp */
/* 144, 0x090 */ SDL_SCANCODE_UNKNOWN, /* XF86Explorer */
/* 145, 0x091 */ SDL_SCANCODE_UNKNOWN, /* XF86Send */
/* 146, 0x092 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 147, 0x093 */ SDL_SCANCODE_UNKNOWN, /* XF86Xfer */
/* 148, 0x094 */ SDL_SCANCODE_APP1, /* XF86Launch1 */
/* 149, 0x095 */ SDL_SCANCODE_APP2, /* XF86Launch2 */
/* 150, 0x096 */ SDL_SCANCODE_WWW, /* XF86WWW */
/* 151, 0x097 */ SDL_SCANCODE_UNKNOWN, /* XF86DOS */
/* 152, 0x098 */ SDL_SCANCODE_UNKNOWN, /* XF86ScreenSaver */
/* 153, 0x099 */ SDL_SCANCODE_UNKNOWN, /* XF86RotateWindows */
/* 154, 0x09a */ SDL_SCANCODE_UNKNOWN, /* XF86TaskPane */
/* 155, 0x09b */ SDL_SCANCODE_MAIL, /* XF86Mail */
/* 156, 0x09c */ SDL_SCANCODE_AC_BOOKMARKS, /* XF86Favorites */
/* 157, 0x09d */ SDL_SCANCODE_COMPUTER, /* XF86MyComputer */
/* 158, 0x09e */ SDL_SCANCODE_AC_BACK, /* XF86Back */
/* 159, 0x09f */ SDL_SCANCODE_AC_FORWARD, /* XF86Forward */
/* 160, 0x0a0 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 161, 0x0a1 */ SDL_SCANCODE_EJECT, /* XF86Eject */
/* 162, 0x0a2 */ SDL_SCANCODE_EJECT, /* XF86Eject */
/* 163, 0x0a3 */ SDL_SCANCODE_AUDIONEXT, /* XF86AudioNext */
/* 164, 0x0a4 */ SDL_SCANCODE_AUDIOPLAY, /* XF86AudioPlay */
/* 165, 0x0a5 */ SDL_SCANCODE_AUDIOPREV, /* XF86AudioPrev */
/* 166, 0x0a6 */ SDL_SCANCODE_AUDIOSTOP, /* XF86AudioStop */
/* 167, 0x0a7 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioRecord */
/* 168, 0x0a8 */ SDL_SCANCODE_AUDIOREWIND, /* XF86AudioRewind */
/* 169, 0x0a9 */ SDL_SCANCODE_UNKNOWN, /* XF86Phone */
/* 170, 0x0aa */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 171, 0x0ab */ SDL_SCANCODE_F13, /* XF86Tools */
/* 172, 0x0ac */ SDL_SCANCODE_AC_HOME, /* XF86HomePage */
/* 173, 0x0ad */ SDL_SCANCODE_AC_REFRESH, /* XF86Reload */
/* 174, 0x0ae */ SDL_SCANCODE_UNKNOWN, /* XF86Close */
/* 175, 0x0af */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 176, 0x0b0 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 177, 0x0b1 */ SDL_SCANCODE_UNKNOWN, /* XF86ScrollUp */
/* 178, 0x0b2 */ SDL_SCANCODE_UNKNOWN, /* XF86ScrollDown */
/* 179, 0x0b3 */ SDL_SCANCODE_KP_LEFTPAREN, /* parenleft */
/* 180, 0x0b4 */ SDL_SCANCODE_KP_RIGHTPAREN, /* parenright */
/* 181, 0x0b5 */ SDL_SCANCODE_UNKNOWN, /* XF86New */
/* 182, 0x0b6 */ SDL_SCANCODE_AGAIN, /* Redo */
/* 183, 0x0b7 */ SDL_SCANCODE_F13, /* XF86Tools */
/* 184, 0x0b8 */ SDL_SCANCODE_F14, /* XF86Launch5 */
/* 185, 0x0b9 */ SDL_SCANCODE_F15, /* XF86Launch6 */
/* 186, 0x0ba */ SDL_SCANCODE_F16, /* XF86Launch7 */
/* 187, 0x0bb */ SDL_SCANCODE_F17, /* XF86Launch8 */
/* 188, 0x0bc */ SDL_SCANCODE_F18, /* XF86Launch9 */
/* 189, 0x0bd */ SDL_SCANCODE_F19, /* NoSymbol */
/* 190, 0x0be */ SDL_SCANCODE_F20, /* XF86AudioMicMute */
/* 191, 0x0bf */ SDL_SCANCODE_UNKNOWN, /* XF86TouchpadToggle */
/* 192, 0x0c0 */ SDL_SCANCODE_UNKNOWN, /* XF86TouchpadOn */
/* 193, 0x0c1 */ SDL_SCANCODE_UNKNOWN, /* XF86TouchpadOff */
/* 194, 0x0c2 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 195, 0x0c3 */ SDL_SCANCODE_MODE, /* Mode_switch */
/* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 198, 0x0c6 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 199, 0x0c7 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 200, 0x0c8 */ SDL_SCANCODE_AUDIOPLAY, /* XF86AudioPlay */
/* 201, 0x0c9 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioPause */
/* 202, 0x0ca */ SDL_SCANCODE_UNKNOWN, /* XF86Launch3 */
/* 203, 0x0cb */ SDL_SCANCODE_UNKNOWN, /* XF86Launch4 */
/* 204, 0x0cc */ SDL_SCANCODE_UNKNOWN, /* XF86LaunchB */
/* 205, 0x0cd */ SDL_SCANCODE_UNKNOWN, /* XF86Suspend */
/* 206, 0x0ce */ SDL_SCANCODE_UNKNOWN, /* XF86Close */
/* 207, 0x0cf */ SDL_SCANCODE_AUDIOPLAY, /* XF86AudioPlay */
/* 208, 0x0d0 */ SDL_SCANCODE_AUDIOFASTFORWARD, /* XF86AudioForward */
/* 209, 0x0d1 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 210, 0x0d2 */ SDL_SCANCODE_PRINTSCREEN, /* Print */
/* 211, 0x0d3 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 212, 0x0d4 */ SDL_SCANCODE_UNKNOWN, /* XF86WebCam */
/* 213, 0x0d5 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioPreset */
/* 214, 0x0d6 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 215, 0x0d7 */ SDL_SCANCODE_MAIL, /* XF86Mail */
/* 216, 0x0d8 */ SDL_SCANCODE_UNKNOWN, /* XF86Messenger */
/* 217, 0x0d9 */ SDL_SCANCODE_AC_SEARCH, /* XF86Search */
/* 218, 0x0da */ SDL_SCANCODE_UNKNOWN, /* XF86Go */
/* 219, 0x0db */ SDL_SCANCODE_UNKNOWN, /* XF86Finance */
/* 220, 0x0dc */ SDL_SCANCODE_UNKNOWN, /* XF86Game */
/* 221, 0x0dd */ SDL_SCANCODE_UNKNOWN, /* XF86Shop */
/* 222, 0x0de */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 223, 0x0df */ SDL_SCANCODE_CANCEL, /* Cancel */
/* 224, 0x0e0 */ SDL_SCANCODE_BRIGHTNESSDOWN, /* XF86MonBrightnessDown */
/* 225, 0x0e1 */ SDL_SCANCODE_BRIGHTNESSUP, /* XF86MonBrightnessUp */
/* 226, 0x0e2 */ SDL_SCANCODE_MEDIASELECT, /* XF86AudioMedia */
/* 227, 0x0e3 */ SDL_SCANCODE_DISPLAYSWITCH, /* XF86Display */
/* 228, 0x0e4 */ SDL_SCANCODE_KBDILLUMTOGGLE, /* XF86KbdLightOnOff */
/* 229, 0x0e5 */ SDL_SCANCODE_KBDILLUMDOWN, /* XF86KbdBrightnessDown */
/* 230, 0x0e6 */ SDL_SCANCODE_KBDILLUMUP, /* XF86KbdBrightnessUp */
/* 231, 0x0e7 */ SDL_SCANCODE_UNKNOWN, /* XF86Send */
/* 232, 0x0e8 */ SDL_SCANCODE_UNKNOWN, /* XF86Reply */
/* 233, 0x0e9 */ SDL_SCANCODE_UNKNOWN, /* XF86MailForward */
/* 234, 0x0ea */ SDL_SCANCODE_UNKNOWN, /* XF86Save */
/* 235, 0x0eb */ SDL_SCANCODE_UNKNOWN, /* XF86Documents */
/* 236, 0x0ec */ SDL_SCANCODE_UNKNOWN, /* XF86Battery */
/* 237, 0x0ed */ SDL_SCANCODE_UNKNOWN, /* XF86Bluetooth */
/* 238, 0x0ee */ SDL_SCANCODE_UNKNOWN, /* XF86WLAN */
/* 239, 0x0ef */ SDL_SCANCODE_UNKNOWN, /* XF86UWB */
/* 240, 0x0f0 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */
/* 241, 0x0f1 */ SDL_SCANCODE_UNKNOWN, /* XF86Next_VMode */
/* 242, 0x0f2 */ SDL_SCANCODE_UNKNOWN, /* XF86Prev_VMode */
/* 243, 0x0f3 */ SDL_SCANCODE_UNKNOWN, /* XF86MonBrightnessCycle */
/* 244, 0x0f4 */ SDL_SCANCODE_UNKNOWN, /* XF86BrightnessAuto */
/* 245, 0x0f5 */ SDL_SCANCODE_UNKNOWN, /* XF86DisplayOff */
/* 246, 0x0f6 */ SDL_SCANCODE_UNKNOWN, /* XF86WWAN */
/* 247, 0x0f7 */ SDL_SCANCODE_UNKNOWN, /* XF86RFKill */
};
/* Xvnc / Xtightvnc scancodes from xmodmap -pk */
@@ -510,3 +519,5 @@ static const SDL_Scancode xvnc_scancode_table[] = {
#endif /* scancodes_xfree86_h_ */
/* *INDENT-ON* */ /* clang-format on */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -19,14 +19,10 @@
3. This notice may not be removed or altered from any source distribution.
*/
/* We won't get fseeko64 on QNX if _LARGEFILE64_SOURCE is defined, but the
configure script knows the C runtime has it and enables it. */
#ifndef __QNXNTO__
/* Need this so Linux systems define fseek64o, ftell64o and off64_t */
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#endif
#include "../SDL_internal.h"
@@ -37,7 +33,6 @@
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -53,15 +48,15 @@
#include "cocoa/SDL_rwopsbundlesupport.h"
#endif /* __APPLE__ */
#ifdef __3DS__
#include "n3ds/SDL_rwopsromfs.h"
#endif /* __3DS__ */
#ifdef __ANDROID__
#include "../core/android/SDL_android.h"
#include "SDL_system.h"
#endif
#if __NACL__
#include "nacl_io/nacl_io.h"
#endif
#if defined(__WIN32__) || defined(__GDK__)
/* Functions to read/write Win32 API file pointers */
@@ -598,9 +593,8 @@ SDL_RWFromFile(const char *file, const char *mode)
{
#if __APPLE__ && !SDL_FILE_DISABLED // TODO: add dummy?
FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode);
#elif __WINRT__
FILE *fp = NULL;
fopen_s(&fp, file, mode);
#elif __3DS__
FILE *fp = N3DS_FileOpen(file, mode);
#else
FILE *fp = fopen(file, mode);
#endif

View File

@@ -0,0 +1,97 @@
/*
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.
*/
#include "SDL_rwopsromfs.h"
#include "SDL_error.h"
/* Checks if the mode is a kind of reading */
SDL_FORCE_INLINE SDL_bool IsReadMode(const char *mode);
/* Checks if the file starts with the given prefix */
SDL_FORCE_INLINE SDL_bool HasPrefix(const char *file, const char *prefix);
SDL_FORCE_INLINE FILE *TryOpenFile(const char *file, const char *mode);
SDL_FORCE_INLINE FILE *TryOpenInRomfs(const char *file, const char *mode);
/* Nintendo 3DS applications may embed resources in the executable. The
resources are stored in a special read-only partition prefixed with
'romfs:/'. As such, when opening a file, we should first try the romfs
unless sdmc is specifically mentionned.
*/
FILE *
N3DS_FileOpen(const char *file, const char *mode)
{
/* romfs are read-only */
if (!IsReadMode(mode)) {
return fopen(file, mode);
}
/* If the path has an explicit prefix, we skip the guess work */
if (HasPrefix(file, "romfs:/") || HasPrefix(file, "sdmc:/")) {
return fopen(file, mode);
}
return TryOpenFile(file, mode);
}
SDL_FORCE_INLINE SDL_bool
IsReadMode(const char *mode)
{
return SDL_strchr(mode, 'r') != NULL;
}
SDL_FORCE_INLINE SDL_bool
HasPrefix(const char *file, const char *prefix)
{
return SDL_strncmp(prefix, file, SDL_strlen(prefix)) == 0;
}
SDL_FORCE_INLINE FILE *
TryOpenFile(const char *file, const char *mode)
{
FILE *fp = NULL;
fp = TryOpenInRomfs(file, mode);
if (fp == NULL) {
fp = fopen(file, mode);
}
return fp;
}
SDL_FORCE_INLINE FILE *
TryOpenInRomfs(const char *file, const char *mode)
{
FILE *fp = NULL;
char *prefixed_filepath = NULL;
if (SDL_asprintf(&prefixed_filepath, "romfs:/%s", file) < 0) {
SDL_OutOfMemory();
return NULL;
}
fp = fopen(prefixed_filepath, mode);
SDL_free(prefixed_filepath);
return fp;
}
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -20,10 +20,11 @@
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_OS2
#ifndef SDL_rwopsromfs_h_
#define SDL_rwopsromfs_h_
extern int OS2_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
FILE *N3DS_FileOpen(const char *file, const char *mode);
#endif /* SDL_VIDEO_DRIVER_OS2 */
#endif /* SDL_rwopsromfs_h_ */
/* vi: set ts=4 sw=4 expandtab: */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,91 @@
/*
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.
*/
#include "../../SDL_internal.h"
#ifdef SDL_FILESYSTEM_N3DS
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* System dependent filesystem routines */
#include <3ds.h>
#include <dirent.h>
#include <errno.h>
#include "SDL_error.h"
#include "SDL_filesystem.h"
SDL_FORCE_INLINE char *MakePrefPath(const char *app);
SDL_FORCE_INLINE int CreatePrefPathDir(const char *pref);
char *
SDL_GetBasePath(void)
{
char *base_path = SDL_strdup("romfs:/");
return base_path;
}
char *
SDL_GetPrefPath(const char *org, const char *app)
{
char *pref_path = NULL;
if (app == NULL) {
SDL_InvalidParamError("app");
return NULL;
}
pref_path = MakePrefPath(app);
if (pref_path == NULL) {
return NULL;
}
if (CreatePrefPathDir(pref_path) < 0) {
SDL_free(pref_path);
return NULL;
}
return pref_path;
}
SDL_FORCE_INLINE char *
MakePrefPath(const char *app)
{
char *pref_path;
if (SDL_asprintf(&pref_path, "sdmc:/3ds/%s/", app) < 0) {
SDL_OutOfMemory();
return NULL;
}
return pref_path;
}
SDL_FORCE_INLINE int
CreatePrefPathDir(const char *pref)
{
int result = mkdir(pref, 0666);
if (result == -1 && errno != EEXIST) {
return SDL_SetError("Failed to create '%s' (%s)", pref, strerror(errno));
}
return 0;
}
#endif /* SDL_FILESYSTEM_N3DS */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -1,131 +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.
*/
#include "../../SDL_internal.h"
#ifdef SDL_FILESYSTEM_OS2
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* System dependent filesystem routines */
#include "../../core/os2/SDL_os2.h"
#include "SDL_error.h"
#include "SDL_filesystem.h"
#define INCL_DOSFILEMGR
#define INCL_DOSPROCESS
#define INCL_DOSMODULEMGR
#define INCL_DOSERRORS
#include <os2.h>
char *
SDL_GetBasePath(void)
{
PTIB tib;
PPIB pib;
ULONG ulRC = DosGetInfoBlocks(&tib, &pib);
PCHAR pcEnd;
CHAR acBuf[CCHMAXPATH];
if (ulRC != NO_ERROR) {
SDL_SetError("Can't get process information block (E%lu)", ulRC);
return NULL;
}
ulRC = DosQueryModuleName(pib->pib_hmte, sizeof(acBuf), acBuf);
if (ulRC != NO_ERROR) {
SDL_SetError("Can't query the module name (E%lu)", ulRC);
return NULL;
}
pcEnd = SDL_strrchr(acBuf, '\\');
if (pcEnd != NULL)
pcEnd[1] = '\0';
else {
if (acBuf[1] == ':') /* e.g. "C:FOO" */
acBuf[2] = '\0';
else {
SDL_SetError("No path in module name");
return NULL;
}
}
return OS2_SysToUTF8(acBuf);
}
char *
SDL_GetPrefPath(const char *org, const char *app)
{
PSZ pszPath;
CHAR acBuf[CCHMAXPATH];
int lPosApp, lPosOrg;
PSZ pszApp, pszOrg;
if (!app) {
SDL_InvalidParamError("app");
return NULL;
}
pszPath = SDL_getenv("HOME");
if (!pszPath) {
pszPath = SDL_getenv("ETC");
if (!pszPath) {
SDL_SetError("HOME or ETC environment not set");
return NULL;
}
}
if (!org) {
lPosApp = SDL_snprintf(acBuf, sizeof(acBuf) - 1, "%s", pszPath);
} else {
pszOrg = OS2_UTF8ToSys(org);
if (!pszOrg) {
SDL_OutOfMemory();
return NULL;
}
lPosApp = SDL_snprintf(acBuf, sizeof(acBuf) - 1, "%s\\%s", pszPath, pszOrg);
SDL_free(pszOrg);
}
if (lPosApp < 0)
return NULL;
DosCreateDir(acBuf, NULL);
pszApp = OS2_UTF8ToSys(app);
if (!pszApp) {
SDL_OutOfMemory();
return NULL;
}
lPosOrg = SDL_snprintf(&acBuf[lPosApp], sizeof(acBuf) - lPosApp - 1, "\\%s", pszApp);
SDL_free(pszApp);
if (lPosOrg < 0)
return NULL;
DosCreateDir(acBuf, NULL);
*((PUSHORT)&acBuf[lPosApp + lPosOrg]) = (USHORT)'\0\\';
return OS2_SysToUTF8(acBuf);
}
#endif /* SDL_FILESYSTEM_OS2 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -43,8 +43,6 @@
#include "SDL_filesystem.h"
#include "SDL_rwops.h"
/* QNX's /proc/self/exefile is a text file and not a symlink. */
#if !defined(__QNXNTO__)
static char *
readSymLink(const char *path)
{
@@ -76,8 +74,6 @@ readSymLink(const char *path)
SDL_free(retval);
return NULL;
}
#endif
#if defined(__OPENBSD__)
static char *search_path_for_binary(const char *bin)
@@ -228,8 +224,6 @@ SDL_GetBasePath(void)
retval = readSymLink("/proc/curproc/file");
#elif defined(__NETBSD__)
retval = readSymLink("/proc/curproc/exe");
#elif defined(__QNXNTO__)
retval = SDL_LoadFile("/proc/self/exefile", NULL);
#else
retval = readSymLink("/proc/self/exe"); /* linux. */
if (retval == NULL) {

Some files were not shown because too many files have changed in this diff Show More