mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-04-26 11:23:43 +02:00
Merge branch 'main' into em-webgl-selector-hint
This commit is contained in:
68
src/SDL.c
68
src/SDL.c
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
363
src/audio/n3ds/SDL_n3dsaudio.c
Normal file
363
src/audio/n3ds/SDL_n3dsaudio.c
Normal 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(¤t_priority, CUR_THREAD_HANDLE);
|
||||
current_priority--;
|
||||
/* 0x18 is reserved for video, 0x30 is the default for main thread */
|
||||
current_priority = SDL_clamp(current_priority, 0x19, 0x2F);
|
||||
svcSetThreadPriority(CUR_THREAD_HANDLE, current_priority);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
N3DSAUDIO_Init(SDL_AudioDriverImpl *impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = N3DSAUDIO_OpenDevice;
|
||||
impl->PlayDevice = N3DSAUDIO_PlayDevice;
|
||||
impl->WaitDevice = N3DSAUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = N3DSAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = N3DSAUDIO_CloseDevice;
|
||||
impl->ThreadInit = N3DSAUDIO_ThreadInit;
|
||||
impl->LockDevice = N3DSAUD_LockAudio;
|
||||
impl->UnlockDevice = N3DSAUD_UnlockAudio;
|
||||
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
|
||||
|
||||
/* Should be possible, but micInit would fail */
|
||||
impl->HasCaptureSupport = SDL_FALSE;
|
||||
impl->CaptureFromDevice = N3DSAUDIO_CaptureFromDevice;
|
||||
|
||||
return SDL_TRUE; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap N3DSAUDIO_bootstrap = {
|
||||
N3DSAUDIO_DRIVER_NAME,
|
||||
"SDL N3DS audio driver",
|
||||
N3DSAUDIO_Init,
|
||||
0
|
||||
};
|
||||
|
||||
/**
|
||||
* Cleans up all allocated memory, safe to call with null pointers
|
||||
*/
|
||||
static void
|
||||
FreePrivateData(_THIS)
|
||||
{
|
||||
if (!this->hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->hidden->waveBuf[0].data_vaddr) {
|
||||
linearFree((void *) this->hidden->waveBuf[0].data_vaddr);
|
||||
}
|
||||
|
||||
if (this->hidden->mixbuf) {
|
||||
SDL_free(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
FindAudioFormat(_THIS)
|
||||
{
|
||||
SDL_bool found_valid_format = SDL_FALSE;
|
||||
Uint16 test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
|
||||
while (!found_valid_format && test_format) {
|
||||
this->spec.format = test_format;
|
||||
switch (test_format) {
|
||||
case AUDIO_S8:
|
||||
/* Signed 8-bit audio supported */
|
||||
this->hidden->format = (this->spec.channels == 2) ? NDSP_FORMAT_STEREO_PCM8 : NDSP_FORMAT_MONO_PCM8;
|
||||
this->hidden->isSigned = 1;
|
||||
this->hidden->bytePerSample = this->spec.channels;
|
||||
found_valid_format = SDL_TRUE;
|
||||
break;
|
||||
case AUDIO_S16:
|
||||
/* Signed 16-bit audio supported */
|
||||
this->hidden->format = (this->spec.channels == 2) ? NDSP_FORMAT_STEREO_PCM16 : NDSP_FORMAT_MONO_PCM16;
|
||||
this->hidden->isSigned = 1;
|
||||
this->hidden->bytePerSample = this->spec.channels * 2;
|
||||
found_valid_format = SDL_TRUE;
|
||||
break;
|
||||
default:
|
||||
test_format = SDL_NextAudioFormat();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found_valid_format ? 0 : -1;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_N3DS */
|
||||
|
||||
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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, ¶m) != -1) {
|
||||
param.sched_priority = param.sched_curpriority + 15;
|
||||
SchedSet(0, 0, SCHED_NOCHANGE, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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) {
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -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: */
|
||||
@@ -1,4 +0,0 @@
|
||||
# OpenWatcom exports file for libiconv
|
||||
++'libiconv'.'ICONV2'..'_libiconv'
|
||||
++'libiconv_close'.'ICONV2'..'_libiconv_close'
|
||||
++'libiconv_open'.'ICONV2'..'_libiconv_open'
|
||||
@@ -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: */
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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: */
|
||||
@@ -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;
|
||||
@@ -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
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
441
src/events/SDL_keysym_to_scancode.c
Normal file
441
src/events/SDL_keysym_to_scancode.c
Normal 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: */
|
||||
@@ -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: */
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
73
src/events/SDL_scancode_tables.c
Normal file
73
src/events/SDL_scancode_tables.c
Normal 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: */
|
||||
37
src/events/SDL_scancode_tables_c.h
Normal file
37
src/events/SDL_scancode_tables_c.h
Normal 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: */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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: */
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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
|
||||
|
||||
97
src/file/n3ds/SDL_rwopsromfs.c
Normal file
97
src/file/n3ds/SDL_rwopsromfs.c
Normal 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: */
|
||||
@@ -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: */
|
||||
91
src/filesystem/n3ds/SDL_sysfilesystem.c
Normal file
91
src/filesystem/n3ds/SDL_sysfilesystem.c
Normal 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: */
|
||||
@@ -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: */
|
||||
@@ -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
Reference in New Issue
Block a user