mirror of
https://github.com/love2d/megasource.git
synced 2026-08-18 19:54:37 +02:00
Added SDL 1c0f6952e65e.
This commit is contained in:
@@ -405,6 +405,8 @@ SDL_GetPlatform()
|
||||
return "BSDI";
|
||||
#elif __DREAMCAST__
|
||||
return "Dreamcast";
|
||||
#elif __EMSCRIPTEN__
|
||||
return "Emscripten";
|
||||
#elif __FREEBSD__
|
||||
return "FreeBSD";
|
||||
#elif __HAIKU__
|
||||
@@ -421,6 +423,8 @@ SDL_GetPlatform()
|
||||
return "MacOS Classic";
|
||||
#elif __MACOSX__
|
||||
return "Mac OS X";
|
||||
#elif __NACL__
|
||||
return "NaCl";
|
||||
#elif __NETBSD__
|
||||
return "NetBSD";
|
||||
#elif __OPENBSD__
|
||||
@@ -437,6 +441,8 @@ SDL_GetPlatform()
|
||||
return "Solaris";
|
||||
#elif __WIN32__
|
||||
return "Windows";
|
||||
#elif __WINRT__
|
||||
return "WinRT";
|
||||
#elif __IPHONEOS__
|
||||
return "iOS";
|
||||
#elif __PSP__
|
||||
|
||||
@@ -50,7 +50,7 @@ SDL_LookupString(const char *key)
|
||||
/* Public functions */
|
||||
|
||||
int
|
||||
SDL_SetError(const char *fmt, ...)
|
||||
SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
SDL_error *error;
|
||||
|
||||
@@ -137,6 +137,10 @@ SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
|
||||
SDL_DelHintCallback(name, callback, userdata);
|
||||
|
||||
entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry));
|
||||
if (!entry) {
|
||||
SDL_OutOfMemory();
|
||||
return;
|
||||
}
|
||||
entry->callback = callback;
|
||||
entry->userdata = userdata;
|
||||
|
||||
@@ -149,6 +153,8 @@ SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
|
||||
/* Need to add a hint entry for this watcher */
|
||||
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
|
||||
if (!hint) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_free(entry);
|
||||
return;
|
||||
}
|
||||
hint->name = SDL_strdup(name);
|
||||
|
||||
+12
-11
@@ -26,6 +26,7 @@
|
||||
|
||||
/* Simple log messages in SDL */
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_log.h"
|
||||
|
||||
#if HAVE_STDIO_H
|
||||
@@ -41,9 +42,6 @@
|
||||
#define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO
|
||||
#define DEFAULT_TEST_PRIORITY SDL_LOG_PRIORITY_VERBOSE
|
||||
|
||||
/* Forward definition of error function */
|
||||
extern int SDL_SetError(const char *fmt, ...);
|
||||
|
||||
typedef struct SDL_LogLevel
|
||||
{
|
||||
int category;
|
||||
@@ -172,7 +170,7 @@ SDL_LogResetPriorities(void)
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Log(const char *fmt, ...)
|
||||
SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -182,7 +180,7 @@ SDL_Log(const char *fmt, ...)
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogVerbose(int category, const char *fmt, ...)
|
||||
SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -192,7 +190,7 @@ SDL_LogVerbose(int category, const char *fmt, ...)
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogDebug(int category, const char *fmt, ...)
|
||||
SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -202,7 +200,7 @@ SDL_LogDebug(int category, const char *fmt, ...)
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogInfo(int category, const char *fmt, ...)
|
||||
SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -212,7 +210,7 @@ SDL_LogInfo(int category, const char *fmt, ...)
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogWarn(int category, const char *fmt, ...)
|
||||
SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -222,7 +220,7 @@ SDL_LogWarn(int category, const char *fmt, ...)
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogError(int category, const char *fmt, ...)
|
||||
SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -232,7 +230,7 @@ SDL_LogError(int category, const char *fmt, ...)
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogCritical(int category, const char *fmt, ...)
|
||||
SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -242,7 +240,7 @@ SDL_LogCritical(int category, const char *fmt, ...)
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...)
|
||||
SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -415,6 +413,9 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
||||
#endif
|
||||
#if HAVE_STDIO_H
|
||||
fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||
#if __NACL__
|
||||
fflush(stderr);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#include <libkern/OSAtomic.h>
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__)
|
||||
#include <atomic.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
If any of the operations are not provided then we must emulate some
|
||||
of them. That means we need a nice implementation of spin locks
|
||||
@@ -54,7 +58,7 @@
|
||||
Contributed by Bob Pendleton, bob@pendleton.com
|
||||
*/
|
||||
|
||||
#if !defined(HAVE_MSC_ATOMICS) && !defined(HAVE_GCC_ATOMICS) && !defined(__MACOSX__)
|
||||
#if !defined(HAVE_MSC_ATOMICS) && !defined(HAVE_GCC_ATOMICS) && !defined(__MACOSX__) && !defined(__SOLARIS__)
|
||||
#define EMULATE_CAS 1
|
||||
#endif
|
||||
|
||||
@@ -88,6 +92,10 @@ SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval)
|
||||
return (SDL_bool) OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value);
|
||||
#elif defined(HAVE_GCC_ATOMICS)
|
||||
return (SDL_bool) __sync_bool_compare_and_swap(&a->value, oldval, newval);
|
||||
#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 EMULATE_CAS
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
@@ -117,6 +125,8 @@ SDL_AtomicCASPtr(void **a, void *oldval, void *newval)
|
||||
return (SDL_bool) OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t*) a);
|
||||
#elif defined(HAVE_GCC_ATOMICS)
|
||||
return __sync_bool_compare_and_swap(a, oldval, newval);
|
||||
#elif defined(__SOLARIS__)
|
||||
return (SDL_bool) (atomic_cas_ptr(a, oldval, newval) == oldval);
|
||||
#elif EMULATE_CAS
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
@@ -140,6 +150,10 @@ SDL_AtomicSet(SDL_atomic_t *a, int v)
|
||||
return _InterlockedExchange((long*)&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);
|
||||
#else
|
||||
int value;
|
||||
do {
|
||||
@@ -158,6 +172,8 @@ SDL_AtomicSetPtr(void **a, void *v)
|
||||
return _InterlockedExchangePointer(a, v);
|
||||
#elif defined(HAVE_GCC_ATOMICS)
|
||||
return __sync_lock_test_and_set(a, v);
|
||||
#elif defined(__SOLARIS__)
|
||||
return atomic_swap_ptr(a, v);
|
||||
#else
|
||||
void *value;
|
||||
do {
|
||||
@@ -174,6 +190,15 @@ SDL_AtomicAdd(SDL_atomic_t *a, int v)
|
||||
return _InterlockedExchangeAdd((long*)&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
|
||||
return pv;
|
||||
#else
|
||||
int value;
|
||||
do {
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__)
|
||||
#include <atomic.h>
|
||||
#endif
|
||||
|
||||
/* This function is where all the magic happens... */
|
||||
SDL_bool
|
||||
@@ -86,9 +89,13 @@ SDL_AtomicTryLock(SDL_SpinLock *lock)
|
||||
/* Maybe used for PowerPC, but the Intel asm or gcc atomics are favored. */
|
||||
return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
|
||||
|
||||
#elif HAVE_PTHREAD_SPINLOCK
|
||||
/* pthread instructions */
|
||||
return (pthread_spin_trylock(lock) == 0);
|
||||
#elif defined(__SOLARIS__) && defined(_LP64)
|
||||
/* Used for Solaris with non-gcc compilers. */
|
||||
return (SDL_bool) ((int) atomic_cas_64((volatile uint64_t*)lock, 0, 1) == 0);
|
||||
|
||||
#elif defined(__SOLARIS__) && !defined(_LP64)
|
||||
/* Used for Solaris with non-gcc compilers. */
|
||||
return (SDL_bool) ((int) atomic_cas_32((volatile uint32_t*)lock, 0, 1) == 0);
|
||||
|
||||
#else
|
||||
#error Please implement for your platform.
|
||||
@@ -115,8 +122,10 @@ SDL_AtomicUnlock(SDL_SpinLock *lock)
|
||||
#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
|
||||
__sync_lock_release(lock);
|
||||
|
||||
#elif HAVE_PTHREAD_SPINLOCK
|
||||
pthread_spin_unlock(lock);
|
||||
#elif defined(__SOLARIS__)
|
||||
/* Used for Solaris when not using gcc. */
|
||||
*lock = 0;
|
||||
membar_producer();
|
||||
|
||||
#else
|
||||
*lock = 0;
|
||||
|
||||
+261
-30
@@ -51,6 +51,7 @@ extern AudioBootStrap QSAAUDIO_bootstrap;
|
||||
extern AudioBootStrap SUNAUDIO_bootstrap;
|
||||
extern AudioBootStrap ARTS_bootstrap;
|
||||
extern AudioBootStrap ESD_bootstrap;
|
||||
extern AudioBootStrap NACLAUD_bootstrap;
|
||||
extern AudioBootStrap NAS_bootstrap;
|
||||
extern AudioBootStrap XAUDIO2_bootstrap;
|
||||
extern AudioBootStrap DSOUND_bootstrap;
|
||||
@@ -68,6 +69,8 @@ extern AudioBootStrap FUSIONSOUND_bootstrap;
|
||||
extern AudioBootStrap ANDROIDAUD_bootstrap;
|
||||
extern AudioBootStrap PSPAUD_bootstrap;
|
||||
extern AudioBootStrap SNDIO_bootstrap;
|
||||
extern AudioBootStrap EmscriptenAudio_bootstrap;
|
||||
|
||||
|
||||
/* Available audio drivers */
|
||||
static const AudioBootStrap *const bootstrap[] = {
|
||||
@@ -98,6 +101,9 @@ static const AudioBootStrap *const bootstrap[] = {
|
||||
#if SDL_AUDIO_DRIVER_ESD
|
||||
&ESD_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_NACL
|
||||
&NACLAUD_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_NAS
|
||||
&NAS_bootstrap,
|
||||
#endif
|
||||
@@ -133,6 +139,9 @@ static const AudioBootStrap *const bootstrap[] = {
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_PSP
|
||||
&PSPAUD_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_EMSCRIPTEN
|
||||
&EmscriptenAudio_bootstrap,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@@ -171,6 +180,12 @@ SDL_AudioPlayDevice_Default(_THIS)
|
||||
{ /* no-op. */
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_AudioGetPendingBytes_Default(_THIS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
SDL_AudioGetDeviceBuf_Default(_THIS)
|
||||
{
|
||||
@@ -198,22 +213,34 @@ SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static SDL_INLINE SDL_bool
|
||||
is_in_audio_device_thread(SDL_AudioDevice * device)
|
||||
{
|
||||
/* The device thread locks the same mutex, but not through the public API.
|
||||
This check is in case the application, in the audio callback,
|
||||
tries to lock the thread that we've already locked from the
|
||||
device thread...just in case we only have non-recursive mutexes. */
|
||||
if (device->thread && (SDL_ThreadID() == device->threadid)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
|
||||
{
|
||||
if (device->thread && (SDL_ThreadID() == device->threadid)) {
|
||||
return;
|
||||
if (!is_in_audio_device_thread(device)) {
|
||||
SDL_LockMutex(device->mixer_lock);
|
||||
}
|
||||
SDL_LockMutex(device->mixer_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
|
||||
{
|
||||
if (device->thread && (SDL_ThreadID() == device->threadid)) {
|
||||
return;
|
||||
if (!is_in_audio_device_thread(device)) {
|
||||
SDL_UnlockMutex(device->mixer_lock);
|
||||
}
|
||||
SDL_UnlockMutex(device->mixer_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -234,6 +261,7 @@ finalize_audio_entry_points(void)
|
||||
FILL_STUB(ThreadInit);
|
||||
FILL_STUB(WaitDevice);
|
||||
FILL_STUB(PlayDevice);
|
||||
FILL_STUB(GetPendingBytes);
|
||||
FILL_STUB(GetDeviceBuf);
|
||||
FILL_STUB(WaitDone);
|
||||
FILL_STUB(CloseDevice);
|
||||
@@ -243,6 +271,7 @@ finalize_audio_entry_points(void)
|
||||
#undef FILL_STUB
|
||||
}
|
||||
|
||||
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
|
||||
/* Streaming functions (for when the input and output buffer sizes are different) */
|
||||
/* Write [length] bytes from buf into the streamer */
|
||||
static void
|
||||
@@ -302,8 +331,184 @@ SDL_StreamDeinit(SDL_AudioStreamer * stream)
|
||||
{
|
||||
SDL_free(stream->buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID)
|
||||
|
||||
/* buffer queueing support... */
|
||||
|
||||
/* this expects that you managed thread safety elsewhere. */
|
||||
static void
|
||||
free_audio_queue(SDL_AudioBufferQueue *buffer)
|
||||
{
|
||||
while (buffer) {
|
||||
SDL_AudioBufferQueue *next = buffer->next;
|
||||
SDL_free(buffer);
|
||||
buffer = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
|
||||
{
|
||||
/* this function always holds the mixer lock before being called. */
|
||||
Uint32 len = (Uint32) _len;
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
|
||||
SDL_AudioBufferQueue *buffer;
|
||||
|
||||
SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
|
||||
SDL_assert(_len >= 0); /* this shouldn't ever happen, right?! */
|
||||
|
||||
while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
|
||||
const Uint32 avail = buffer->datalen - buffer->startpos;
|
||||
const Uint32 cpy = SDL_min(len, avail);
|
||||
SDL_assert(device->queued_bytes >= avail);
|
||||
|
||||
SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
|
||||
buffer->startpos += cpy;
|
||||
stream += cpy;
|
||||
device->queued_bytes -= cpy;
|
||||
len -= cpy;
|
||||
|
||||
if (buffer->startpos == buffer->datalen) { /* packet is done, put it in the pool. */
|
||||
device->buffer_queue_head = buffer->next;
|
||||
SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
|
||||
buffer->next = device->buffer_queue_pool;
|
||||
device->buffer_queue_pool = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
|
||||
|
||||
if (len > 0) { /* fill any remaining space in the stream with silence. */
|
||||
SDL_assert(device->buffer_queue_head == NULL);
|
||||
SDL_memset(stream, device->spec.silence, len);
|
||||
}
|
||||
|
||||
if (device->buffer_queue_head == NULL) {
|
||||
device->buffer_queue_tail = NULL; /* in case we drained the queue entirely. */
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
|
||||
{
|
||||
SDL_AudioDevice *device = get_audio_device(devid);
|
||||
const Uint8 *data = (const Uint8 *) _data;
|
||||
SDL_AudioBufferQueue *orighead;
|
||||
SDL_AudioBufferQueue *origtail;
|
||||
Uint32 origlen;
|
||||
Uint32 datalen;
|
||||
|
||||
if (!device) {
|
||||
return -1; /* get_audio_device() will have set the error state */
|
||||
}
|
||||
|
||||
if (device->spec.callback != SDL_BufferQueueDrainCallback) {
|
||||
return SDL_SetError("Audio device has a callback, queueing not allowed");
|
||||
}
|
||||
|
||||
current_audio.impl.LockDevice(device);
|
||||
|
||||
orighead = device->buffer_queue_head;
|
||||
origtail = device->buffer_queue_tail;
|
||||
origlen = origtail ? origtail->datalen : 0;
|
||||
|
||||
while (len > 0) {
|
||||
SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
|
||||
SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
|
||||
if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
|
||||
/* tail packet missing or completely full; we need a new packet. */
|
||||
packet = device->buffer_queue_pool;
|
||||
if (packet != NULL) {
|
||||
/* we have one available in the pool. */
|
||||
device->buffer_queue_pool = packet->next;
|
||||
} else {
|
||||
/* Have to allocate a new one! */
|
||||
packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
|
||||
if (packet == NULL) {
|
||||
/* uhoh, reset so we've queued nothing new, free what we can. */
|
||||
if (!origtail) {
|
||||
packet = device->buffer_queue_head; /* whole queue. */
|
||||
} else {
|
||||
packet = origtail->next; /* what we added to existing queue. */
|
||||
origtail->next = NULL;
|
||||
origtail->datalen = origlen;
|
||||
}
|
||||
device->buffer_queue_head = orighead;
|
||||
device->buffer_queue_tail = origtail;
|
||||
device->buffer_queue_pool = NULL;
|
||||
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
|
||||
free_audio_queue(packet); /* give back what we can. */
|
||||
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
}
|
||||
packet->datalen = 0;
|
||||
packet->startpos = 0;
|
||||
packet->next = NULL;
|
||||
|
||||
SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
|
||||
if (device->buffer_queue_tail == NULL) {
|
||||
device->buffer_queue_head = packet;
|
||||
} else {
|
||||
device->buffer_queue_tail->next = packet;
|
||||
}
|
||||
device->buffer_queue_tail = packet;
|
||||
}
|
||||
|
||||
datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
|
||||
SDL_memcpy(packet->data + packet->datalen, data, datalen);
|
||||
data += datalen;
|
||||
len -= datalen;
|
||||
packet->datalen += datalen;
|
||||
device->queued_bytes += datalen;
|
||||
}
|
||||
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
|
||||
{
|
||||
Uint32 retval = 0;
|
||||
SDL_AudioDevice *device = get_audio_device(devid);
|
||||
|
||||
/* Nothing to do unless we're set up for queueing. */
|
||||
if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
|
||||
current_audio.impl.LockDevice(device);
|
||||
retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
|
||||
{
|
||||
SDL_AudioDevice *device = get_audio_device(devid);
|
||||
SDL_AudioBufferQueue *buffer = NULL;
|
||||
if (!device) {
|
||||
return; /* nothing to do. */
|
||||
}
|
||||
|
||||
/* Blank out the device and release the mutex. Free it afterwards. */
|
||||
current_audio.impl.LockDevice(device);
|
||||
buffer = device->buffer_queue_head;
|
||||
device->buffer_queue_tail = NULL;
|
||||
device->buffer_queue_head = NULL;
|
||||
device->queued_bytes = 0;
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
|
||||
free_audio_queue(buffer);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
@@ -317,9 +522,12 @@ SDL_RunAudio(void *devicep)
|
||||
void *udata;
|
||||
void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
|
||||
Uint32 delay;
|
||||
|
||||
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
|
||||
/* For streaming when the buffer sizes don't match up */
|
||||
Uint8 *istream;
|
||||
int istream_len = 0;
|
||||
#endif
|
||||
|
||||
/* The audio mixing is always a high priority thread */
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
|
||||
@@ -367,6 +575,7 @@ SDL_RunAudio(void *devicep)
|
||||
delay = ((device->spec.samples * 1000) / device->spec.freq);
|
||||
|
||||
/* Determine if the streamer is necessary here */
|
||||
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
|
||||
if (device->use_streamer == 1) {
|
||||
/* This code is almost the same as the old code. The difference is, instead of reading
|
||||
directly from the callback into "stream", then converting and sending the audio off,
|
||||
@@ -455,7 +664,9 @@ SDL_RunAudio(void *devicep)
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Otherwise, do not use the streamer. This is the old code. */
|
||||
const int silence = (int) device->spec.silence;
|
||||
|
||||
@@ -510,10 +721,12 @@ SDL_RunAudio(void *devicep)
|
||||
current_audio.impl.WaitDone(device);
|
||||
|
||||
/* If necessary, deinit the streamer */
|
||||
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
|
||||
if (device->use_streamer == 1)
|
||||
SDL_StreamDeinit(&device->streamer);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -546,16 +759,16 @@ SDL_ParseAudioFormat(const char *string)
|
||||
int
|
||||
SDL_GetNumAudioDrivers(void)
|
||||
{
|
||||
return (SDL_arraysize(bootstrap) - 1);
|
||||
return SDL_arraysize(bootstrap) - 1;
|
||||
}
|
||||
|
||||
const char *
|
||||
SDL_GetAudioDriver(int index)
|
||||
{
|
||||
if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
|
||||
return (bootstrap[index]->name);
|
||||
return bootstrap[index]->name;
|
||||
}
|
||||
return (NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -603,12 +816,12 @@ SDL_AudioInit(const char *driver_name)
|
||||
}
|
||||
|
||||
SDL_memset(¤t_audio, 0, sizeof(current_audio));
|
||||
return (-1); /* No driver was available, so fail. */
|
||||
return -1; /* No driver was available, so fail. */
|
||||
}
|
||||
|
||||
finalize_audio_entry_points();
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -771,6 +984,10 @@ close_audio_device(SDL_AudioDevice * device)
|
||||
current_audio.impl.CloseDevice(device);
|
||||
device->opened = 0;
|
||||
}
|
||||
|
||||
free_audio_queue(device->buffer_queue_head);
|
||||
free_audio_queue(device->buffer_queue_pool);
|
||||
|
||||
SDL_FreeAudioMem(device);
|
||||
}
|
||||
|
||||
@@ -785,11 +1002,6 @@ prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
|
||||
{
|
||||
SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
|
||||
|
||||
if (orig->callback == NULL) {
|
||||
SDL_SetError("SDL_OpenAudio() passed a NULL callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (orig->freq == 0) {
|
||||
const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
|
||||
if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
|
||||
@@ -842,7 +1054,6 @@ prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static SDL_AudioDeviceID
|
||||
open_audio_device(const char *devname, int iscapture,
|
||||
const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
|
||||
@@ -921,7 +1132,7 @@ open_audio_device(const char *devname, int iscapture,
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(device, '\0', sizeof(SDL_AudioDevice));
|
||||
SDL_zerop(device);
|
||||
device->spec = *obtained;
|
||||
device->enabled = 1;
|
||||
device->paused = 1;
|
||||
@@ -939,8 +1150,9 @@ open_audio_device(const char *devname, int iscapture,
|
||||
|
||||
/* force a device detection if we haven't done one yet. */
|
||||
if ( ((iscapture) && (current_audio.inputDevices == NULL)) ||
|
||||
((!iscapture) && (current_audio.outputDevices == NULL)) )
|
||||
((!iscapture) && (current_audio.outputDevices == NULL)) ) {
|
||||
SDL_GetNumAudioDevices(iscapture);
|
||||
}
|
||||
|
||||
if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
|
||||
close_audio_device(device);
|
||||
@@ -1014,6 +1226,25 @@ open_audio_device(const char *devname, int iscapture,
|
||||
}
|
||||
}
|
||||
|
||||
if (device->spec.callback == NULL) { /* use buffer queueing? */
|
||||
/* pool a few packets to start. Enough for two callbacks. */
|
||||
const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
|
||||
const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
|
||||
const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
|
||||
for (i = 0; i < wantpackets; i++) {
|
||||
SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
|
||||
if (packet) { /* don't care if this fails, we'll deal later. */
|
||||
packet->datalen = 0;
|
||||
packet->startpos = 0;
|
||||
packet->next = device->buffer_queue_pool;
|
||||
device->buffer_queue_pool = packet;
|
||||
}
|
||||
}
|
||||
|
||||
device->spec.callback = SDL_BufferQueueDrainCallback;
|
||||
device->spec.userdata = device;
|
||||
}
|
||||
|
||||
/* Find an available device ID and store the structure... */
|
||||
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
|
||||
if (open_devices[id] == NULL) {
|
||||
@@ -1063,25 +1294,25 @@ SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
|
||||
/* Start up the audio driver, if necessary. This is legacy behaviour! */
|
||||
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
|
||||
if (open_devices[0] != NULL) {
|
||||
SDL_SetError("Audio device is already opened");
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (obtained) {
|
||||
id = open_audio_device(NULL, 0, desired, obtained,
|
||||
SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
|
||||
} else {
|
||||
id = open_audio_device(NULL, 0, desired, desired, 0, 1);
|
||||
id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
|
||||
}
|
||||
|
||||
SDL_assert((id == 0) || (id == 1));
|
||||
return ((id == 0) ? -1 : 0);
|
||||
return (id == 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
SDL_AudioDeviceID
|
||||
@@ -1105,7 +1336,7 @@ SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
|
||||
status = SDL_AUDIO_PLAYING;
|
||||
}
|
||||
}
|
||||
return (status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -1241,16 +1472,16 @@ SDL_FirstAudioFormat(SDL_AudioFormat format)
|
||||
}
|
||||
}
|
||||
format_idx_sub = 0;
|
||||
return (SDL_NextAudioFormat());
|
||||
return SDL_NextAudioFormat();
|
||||
}
|
||||
|
||||
SDL_AudioFormat
|
||||
SDL_NextAudioFormat(void)
|
||||
{
|
||||
if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
return (format_list[format_idx][format_idx_sub++]);
|
||||
return format_list[format_idx][format_idx_sub++];
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -2300,7 +2300,7 @@ SDL_Upsample_U8_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 16;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/1)) * cvt->rate_incr) * 1;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = ((Uint8 *) (cvt->buf + dstsize)) - 1;
|
||||
const Uint8 *src = ((Uint8 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -2332,7 +2332,7 @@ SDL_Downsample_U8_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 16;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/1)) * cvt->rate_incr) * 1;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = (Uint8 *) cvt->buf;
|
||||
const Uint8 *src = (Uint8 *) cvt->buf;
|
||||
@@ -2364,7 +2364,7 @@ SDL_Upsample_U8_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = ((Uint8 *) (cvt->buf + dstsize)) - 2;
|
||||
const Uint8 *src = ((Uint8 *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -2401,7 +2401,7 @@ SDL_Downsample_U8_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = (Uint8 *) cvt->buf;
|
||||
const Uint8 *src = (Uint8 *) cvt->buf;
|
||||
@@ -2438,7 +2438,7 @@ SDL_Upsample_U8_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = ((Uint8 *) (cvt->buf + dstsize)) - 4;
|
||||
const Uint8 *src = ((Uint8 *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -2485,7 +2485,7 @@ SDL_Downsample_U8_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = (Uint8 *) cvt->buf;
|
||||
const Uint8 *src = (Uint8 *) cvt->buf;
|
||||
@@ -2532,7 +2532,7 @@ SDL_Upsample_U8_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 96;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/6)) * cvt->rate_incr) * 6;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = ((Uint8 *) (cvt->buf + dstsize)) - 6;
|
||||
const Uint8 *src = ((Uint8 *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -2589,7 +2589,7 @@ SDL_Downsample_U8_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 96;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/6)) * cvt->rate_incr) * 6;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = (Uint8 *) cvt->buf;
|
||||
const Uint8 *src = (Uint8 *) cvt->buf;
|
||||
@@ -2646,7 +2646,7 @@ SDL_Upsample_U8_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = ((Uint8 *) (cvt->buf + dstsize)) - 8;
|
||||
const Uint8 *src = ((Uint8 *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -2713,7 +2713,7 @@ SDL_Downsample_U8_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Uint8 *dst = (Uint8 *) cvt->buf;
|
||||
const Uint8 *src = (Uint8 *) cvt->buf;
|
||||
@@ -2780,7 +2780,7 @@ SDL_Upsample_S8_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 16;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/1)) * cvt->rate_incr) * 1;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = ((Sint8 *) (cvt->buf + dstsize)) - 1;
|
||||
const Sint8 *src = ((Sint8 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -2812,7 +2812,7 @@ SDL_Downsample_S8_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 16;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/1)) * cvt->rate_incr) * 1;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = (Sint8 *) cvt->buf;
|
||||
const Sint8 *src = (Sint8 *) cvt->buf;
|
||||
@@ -2844,7 +2844,7 @@ SDL_Upsample_S8_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = ((Sint8 *) (cvt->buf + dstsize)) - 2;
|
||||
const Sint8 *src = ((Sint8 *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -2881,7 +2881,7 @@ SDL_Downsample_S8_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = (Sint8 *) cvt->buf;
|
||||
const Sint8 *src = (Sint8 *) cvt->buf;
|
||||
@@ -2918,7 +2918,7 @@ SDL_Upsample_S8_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = ((Sint8 *) (cvt->buf + dstsize)) - 4;
|
||||
const Sint8 *src = ((Sint8 *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -2965,7 +2965,7 @@ SDL_Downsample_S8_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = (Sint8 *) cvt->buf;
|
||||
const Sint8 *src = (Sint8 *) cvt->buf;
|
||||
@@ -3012,7 +3012,7 @@ SDL_Upsample_S8_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 96;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/6)) * cvt->rate_incr) * 6;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = ((Sint8 *) (cvt->buf + dstsize)) - 6;
|
||||
const Sint8 *src = ((Sint8 *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -3069,7 +3069,7 @@ SDL_Downsample_S8_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 96;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/6)) * cvt->rate_incr) * 6;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = (Sint8 *) cvt->buf;
|
||||
const Sint8 *src = (Sint8 *) cvt->buf;
|
||||
@@ -3126,7 +3126,7 @@ SDL_Upsample_S8_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = ((Sint8 *) (cvt->buf + dstsize)) - 8;
|
||||
const Sint8 *src = ((Sint8 *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -3193,7 +3193,7 @@ SDL_Downsample_S8_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint8 *dst = (Sint8 *) cvt->buf;
|
||||
const Sint8 *src = (Sint8 *) cvt->buf;
|
||||
@@ -3260,7 +3260,7 @@ SDL_Upsample_U16LSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 1;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -3292,7 +3292,7 @@ SDL_Downsample_U16LSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -3324,7 +3324,7 @@ SDL_Upsample_U16LSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 2;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -3361,7 +3361,7 @@ SDL_Downsample_U16LSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -3398,7 +3398,7 @@ SDL_Upsample_U16LSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 4;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -3445,7 +3445,7 @@ SDL_Downsample_U16LSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -3492,7 +3492,7 @@ SDL_Upsample_U16LSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 192;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/12)) * cvt->rate_incr) * 12;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 6;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -3549,7 +3549,7 @@ SDL_Downsample_U16LSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 192;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/12)) * cvt->rate_incr) * 12;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -3606,7 +3606,7 @@ SDL_Upsample_U16LSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 8;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -3673,7 +3673,7 @@ SDL_Downsample_U16LSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -3740,7 +3740,7 @@ SDL_Upsample_S16LSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 1;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -3772,7 +3772,7 @@ SDL_Downsample_S16LSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -3804,7 +3804,7 @@ SDL_Upsample_S16LSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 2;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -3841,7 +3841,7 @@ SDL_Downsample_S16LSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -3878,7 +3878,7 @@ SDL_Upsample_S16LSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 4;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -3925,7 +3925,7 @@ SDL_Downsample_S16LSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -3972,7 +3972,7 @@ SDL_Upsample_S16LSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 192;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/12)) * cvt->rate_incr) * 12;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 6;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -4029,7 +4029,7 @@ SDL_Downsample_S16LSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 192;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/12)) * cvt->rate_incr) * 12;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -4086,7 +4086,7 @@ SDL_Upsample_S16LSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 8;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -4153,7 +4153,7 @@ SDL_Downsample_S16LSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -4220,7 +4220,7 @@ SDL_Upsample_U16MSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 1;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -4252,7 +4252,7 @@ SDL_Downsample_U16MSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -4284,7 +4284,7 @@ SDL_Upsample_U16MSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 2;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -4321,7 +4321,7 @@ SDL_Downsample_U16MSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -4358,7 +4358,7 @@ SDL_Upsample_U16MSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 4;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -4405,7 +4405,7 @@ SDL_Downsample_U16MSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -4452,7 +4452,7 @@ SDL_Upsample_U16MSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 192;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/12)) * cvt->rate_incr) * 12;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 6;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -4509,7 +4509,7 @@ SDL_Downsample_U16MSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 192;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/12)) * cvt->rate_incr) * 12;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -4566,7 +4566,7 @@ SDL_Upsample_U16MSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = ((Uint16 *) (cvt->buf + dstsize)) - 8;
|
||||
const Uint16 *src = ((Uint16 *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -4633,7 +4633,7 @@ SDL_Downsample_U16MSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
const Uint16 *src = (Uint16 *) cvt->buf;
|
||||
@@ -4700,7 +4700,7 @@ SDL_Upsample_S16MSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 1;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -4732,7 +4732,7 @@ SDL_Downsample_S16MSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 32;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/2)) * cvt->rate_incr) * 2;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -4764,7 +4764,7 @@ SDL_Upsample_S16MSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 2;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -4801,7 +4801,7 @@ SDL_Downsample_S16MSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -4838,7 +4838,7 @@ SDL_Upsample_S16MSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 4;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -4885,7 +4885,7 @@ SDL_Downsample_S16MSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -4932,7 +4932,7 @@ SDL_Upsample_S16MSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 192;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/12)) * cvt->rate_incr) * 12;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 6;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -4989,7 +4989,7 @@ SDL_Downsample_S16MSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 192;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/12)) * cvt->rate_incr) * 12;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -5046,7 +5046,7 @@ SDL_Upsample_S16MSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = ((Sint16 *) (cvt->buf + dstsize)) - 8;
|
||||
const Sint16 *src = ((Sint16 *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -5113,7 +5113,7 @@ SDL_Downsample_S16MSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
const Sint16 *src = (Sint16 *) cvt->buf;
|
||||
@@ -5180,7 +5180,7 @@ SDL_Upsample_S32LSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 1;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -5212,7 +5212,7 @@ SDL_Downsample_S32LSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -5244,7 +5244,7 @@ SDL_Upsample_S32LSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 2;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -5281,7 +5281,7 @@ SDL_Downsample_S32LSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -5318,7 +5318,7 @@ SDL_Upsample_S32LSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 4;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -5365,7 +5365,7 @@ SDL_Downsample_S32LSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -5412,7 +5412,7 @@ SDL_Upsample_S32LSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 384;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/24)) * cvt->rate_incr) * 24;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 6;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -5469,7 +5469,7 @@ SDL_Downsample_S32LSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 384;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/24)) * cvt->rate_incr) * 24;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -5526,7 +5526,7 @@ SDL_Upsample_S32LSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 512;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/32)) * cvt->rate_incr) * 32;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 8;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -5593,7 +5593,7 @@ SDL_Downsample_S32LSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 512;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/32)) * cvt->rate_incr) * 32;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -5660,7 +5660,7 @@ SDL_Upsample_S32MSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 1;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -5692,7 +5692,7 @@ SDL_Downsample_S32MSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -5724,7 +5724,7 @@ SDL_Upsample_S32MSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 2;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -5761,7 +5761,7 @@ SDL_Downsample_S32MSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -5798,7 +5798,7 @@ SDL_Upsample_S32MSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 4;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -5845,7 +5845,7 @@ SDL_Downsample_S32MSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -5892,7 +5892,7 @@ SDL_Upsample_S32MSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 384;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/24)) * cvt->rate_incr) * 24;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 6;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -5949,7 +5949,7 @@ SDL_Downsample_S32MSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 384;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/24)) * cvt->rate_incr) * 24;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -6006,7 +6006,7 @@ SDL_Upsample_S32MSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 512;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/32)) * cvt->rate_incr) * 32;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = ((Sint32 *) (cvt->buf + dstsize)) - 8;
|
||||
const Sint32 *src = ((Sint32 *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -6073,7 +6073,7 @@ SDL_Downsample_S32MSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 512;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/32)) * cvt->rate_incr) * 32;
|
||||
register int eps = 0;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
const Sint32 *src = (Sint32 *) cvt->buf;
|
||||
@@ -6140,7 +6140,7 @@ SDL_Upsample_F32LSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 1;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -6172,7 +6172,7 @@ SDL_Downsample_F32LSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6204,7 +6204,7 @@ SDL_Upsample_F32LSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 2;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -6241,7 +6241,7 @@ SDL_Downsample_F32LSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6278,7 +6278,7 @@ SDL_Upsample_F32LSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 4;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -6325,7 +6325,7 @@ SDL_Downsample_F32LSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6372,7 +6372,7 @@ SDL_Upsample_F32LSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 384;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/24)) * cvt->rate_incr) * 24;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 6;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -6429,7 +6429,7 @@ SDL_Downsample_F32LSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 384;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/24)) * cvt->rate_incr) * 24;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6486,7 +6486,7 @@ SDL_Upsample_F32LSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 512;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/32)) * cvt->rate_incr) * 32;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 8;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -6553,7 +6553,7 @@ SDL_Downsample_F32LSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 512;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/32)) * cvt->rate_incr) * 32;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6620,7 +6620,7 @@ SDL_Upsample_F32MSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 1;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
@@ -6652,7 +6652,7 @@ SDL_Downsample_F32MSB_1c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 64;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/4)) * cvt->rate_incr) * 4;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6684,7 +6684,7 @@ SDL_Upsample_F32MSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 2;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 2;
|
||||
@@ -6721,7 +6721,7 @@ SDL_Downsample_F32MSB_2c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 128;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/8)) * cvt->rate_incr) * 8;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6758,7 +6758,7 @@ SDL_Upsample_F32MSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 4;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 4;
|
||||
@@ -6805,7 +6805,7 @@ SDL_Downsample_F32MSB_4c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 256;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/16)) * cvt->rate_incr) * 16;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6852,7 +6852,7 @@ SDL_Upsample_F32MSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 384;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/24)) * cvt->rate_incr) * 24;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 6;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 6;
|
||||
@@ -6909,7 +6909,7 @@ SDL_Downsample_F32MSB_6c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 384;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/24)) * cvt->rate_incr) * 24;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
@@ -6966,7 +6966,7 @@ SDL_Upsample_F32MSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 512;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/32)) * cvt->rate_incr) * 32;
|
||||
register int eps = 0;
|
||||
float *dst = ((float *) (cvt->buf + dstsize)) - 8;
|
||||
const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 8;
|
||||
@@ -7033,7 +7033,7 @@ SDL_Downsample_F32MSB_8c(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - 512;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/32)) * cvt->rate_incr) * 32;
|
||||
register int eps = 0;
|
||||
float *dst = (float *) cvt->buf;
|
||||
const float *src = (float *) cvt->buf;
|
||||
|
||||
@@ -33,6 +33,26 @@ typedef struct SDL_AudioDevice SDL_AudioDevice;
|
||||
/* Used by audio targets during DetectDevices() */
|
||||
typedef void (*SDL_AddAudioDevice)(const char *name);
|
||||
|
||||
/* This is the size of a packet when using SDL_QueueAudio(). We allocate
|
||||
these as necessary and pool them, under the assumption that we'll
|
||||
eventually end up with a handful that keep recycling, meeting whatever
|
||||
the app needs. We keep packing data tightly as more arrives to avoid
|
||||
wasting space, and if we get a giant block of data, we'll split them
|
||||
into multiple packets behind the scenes. My expectation is that most
|
||||
apps will have 2-3 of these in the pool. 8k should cover most needs, but
|
||||
if this is crippling for some embedded system, we can #ifdef this.
|
||||
The system preallocates enough packets for 2 callbacks' worth of data. */
|
||||
#define SDL_AUDIOBUFFERQUEUE_PACKETLEN (8 * 1024)
|
||||
|
||||
/* Used by apps that queue audio instead of using the callback. */
|
||||
typedef struct SDL_AudioBufferQueue
|
||||
{
|
||||
Uint8 data[SDL_AUDIOBUFFERQUEUE_PACKETLEN]; /* packet data. */
|
||||
Uint32 datalen; /* bytes currently in use in this packet. */
|
||||
Uint32 startpos; /* bytes currently consumed in this packet. */
|
||||
struct SDL_AudioBufferQueue *next; /* next item in linked list. */
|
||||
} SDL_AudioBufferQueue;
|
||||
|
||||
typedef struct SDL_AudioDriverImpl
|
||||
{
|
||||
void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn);
|
||||
@@ -40,6 +60,7 @@ typedef struct SDL_AudioDriverImpl
|
||||
void (*ThreadInit) (_THIS); /* Called by audio thread at start */
|
||||
void (*WaitDevice) (_THIS);
|
||||
void (*PlayDevice) (_THIS);
|
||||
int (*GetPendingBytes) (_THIS);
|
||||
Uint8 *(*GetDeviceBuf) (_THIS);
|
||||
void (*WaitDone) (_THIS);
|
||||
void (*CloseDevice) (_THIS);
|
||||
@@ -119,6 +140,12 @@ struct SDL_AudioDevice
|
||||
SDL_Thread *thread;
|
||||
SDL_threadID threadid;
|
||||
|
||||
/* Queued buffers (if app not using callback). */
|
||||
SDL_AudioBufferQueue *buffer_queue_head; /* device fed from here. */
|
||||
SDL_AudioBufferQueue *buffer_queue_tail; /* queue fills to here. */
|
||||
SDL_AudioBufferQueue *buffer_queue_pool; /* these are unused packets. */
|
||||
Uint32 queued_bytes; /* number of bytes of audio data in the queue. */
|
||||
|
||||
/* * * */
|
||||
/* Data private to this driver */
|
||||
struct SDL_PrivateAudioData *hidden;
|
||||
|
||||
@@ -121,7 +121,8 @@ MS_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
|
||||
struct MS_ADPCM_decodestate *state[2];
|
||||
Uint8 *freeable, *encoded, *decoded;
|
||||
Sint32 encoded_len, samplesleft;
|
||||
Sint8 nybble, stereo;
|
||||
Sint8 nybble;
|
||||
Uint8 stereo;
|
||||
Sint16 *coeff[2];
|
||||
Sint32 new_sample;
|
||||
|
||||
@@ -278,7 +279,8 @@ IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state, Uint8 nybble)
|
||||
} else if (state->index < 0) {
|
||||
state->index = 0;
|
||||
}
|
||||
step = step_table[state->index];
|
||||
/* explicit cast to avoid gcc warning about using 'char' as array index */
|
||||
step = step_table[(int)state->index];
|
||||
delta = step >> 3;
|
||||
if (nybble & 0x04)
|
||||
delta += step;
|
||||
@@ -343,8 +345,8 @@ IMA_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
|
||||
/* Check to make sure we have enough variables in the state array */
|
||||
channels = IMA_ADPCM_state.wavefmt.channels;
|
||||
if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
|
||||
SDL_SetError("IMA ADPCM decoder can only handle %d channels",
|
||||
SDL_arraysize(IMA_ADPCM_state.state));
|
||||
SDL_SetError("IMA ADPCM decoder can only handle %u channels",
|
||||
(unsigned int)SDL_arraysize(IMA_ADPCM_state.state));
|
||||
return (-1);
|
||||
}
|
||||
state = IMA_ADPCM_state.state;
|
||||
@@ -458,7 +460,7 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
|
||||
}
|
||||
/* 2 Uint32's for chunk header+len, plus the lenread */
|
||||
headerDiff += lenread + 2 * sizeof(Uint32);
|
||||
} while ((chunk.magic == FACT) || (chunk.magic == LIST));
|
||||
} while ((chunk.magic == FACT) || (chunk.magic == LIST) || (chunk.magic == BEXT) || (chunk.magic == JUNK));
|
||||
|
||||
/* Decode the audio data format */
|
||||
format = (WaveFMT *) chunk.data;
|
||||
@@ -493,8 +495,7 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
|
||||
IMA_ADPCM_encoded = 1;
|
||||
break;
|
||||
case MP3_CODE:
|
||||
SDL_SetError("MPEG Layer 3 data not supported",
|
||||
SDL_SwapLE16(format->encoding));
|
||||
SDL_SetError("MPEG Layer 3 data not supported");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
default:
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#define WAVE 0x45564157 /* "WAVE" */
|
||||
#define FACT 0x74636166 /* "fact" */
|
||||
#define LIST 0x5453494c /* "LIST" */
|
||||
#define BEXT 0x74786562 /* "bext" */
|
||||
#define JUNK 0x4B4E554A /* "JUNK" */
|
||||
#define FMT 0x20746D66 /* "fmt " */
|
||||
#define DATA 0x61746164 /* "data" */
|
||||
#define PCM_CODE 0x0001
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
static void * audioDevice;
|
||||
static SDL_AudioDevice* audioDevice = NULL;
|
||||
|
||||
static int
|
||||
AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
@@ -49,6 +49,11 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
}
|
||||
|
||||
audioDevice = this;
|
||||
|
||||
this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
while (test_format != 0) { /* no "UNKNOWN" constant */
|
||||
@@ -110,6 +115,10 @@ AndroidAUD_CloseDevice(_THIS)
|
||||
Android_JNI_CloseAudioDevice();
|
||||
|
||||
if (audioDevice == this) {
|
||||
if (audioDevice->hidden != NULL) {
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
audioDevice = NULL;
|
||||
}
|
||||
}
|
||||
@@ -135,6 +144,41 @@ AudioBootStrap ANDROIDAUD_bootstrap = {
|
||||
"android", "SDL Android audio driver", AndroidAUD_Init, 0
|
||||
};
|
||||
|
||||
/* Pause (block) all non already paused audio devices by taking their mixer lock */
|
||||
void AndroidAUD_PauseDevices(void)
|
||||
{
|
||||
/* TODO: Handle multiple devices? */
|
||||
struct SDL_PrivateAudioData *private;
|
||||
if(audioDevice != NULL && audioDevice->hidden != NULL) {
|
||||
private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
|
||||
if (audioDevice->paused) {
|
||||
/* The device is already paused, leave it alone */
|
||||
private->resume = SDL_FALSE;
|
||||
}
|
||||
else {
|
||||
SDL_LockMutex(audioDevice->mixer_lock);
|
||||
audioDevice->paused = SDL_TRUE;
|
||||
private->resume = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
|
||||
void AndroidAUD_ResumeDevices(void)
|
||||
{
|
||||
/* TODO: Handle multiple devices? */
|
||||
struct SDL_PrivateAudioData *private;
|
||||
if(audioDevice != NULL && audioDevice->hidden != NULL) {
|
||||
private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
|
||||
if (private->resume) {
|
||||
audioDevice->paused = SDL_FALSE;
|
||||
private->resume = SDL_FALSE;
|
||||
SDL_UnlockMutex(audioDevice->mixer_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_ANDROID */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* Resume device if it was paused automatically */
|
||||
int resume;
|
||||
};
|
||||
|
||||
static void AndroidAUD_CloseDevice(_THIS);
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_AUDIO_DRIVER_COREAUDIO
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
@@ -319,7 +322,6 @@ COREAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->audioUnitOpened) {
|
||||
OSStatus result = noErr;
|
||||
AURenderCallbackStruct callback;
|
||||
const AudioUnitElement output_bus = 0;
|
||||
const AudioUnitElement input_bus = 1;
|
||||
@@ -331,14 +333,13 @@ COREAUDIO_CloseDevice(_THIS)
|
||||
kAudioUnitScope_Input);
|
||||
|
||||
/* stop processing the audio unit */
|
||||
result = AudioOutputUnitStop(this->hidden->audioUnit);
|
||||
AudioOutputUnitStop(this->hidden->audioUnit);
|
||||
|
||||
/* Remove the input callback */
|
||||
SDL_memset(&callback, 0, sizeof(AURenderCallbackStruct));
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
scope, bus, &callback,
|
||||
sizeof(callback));
|
||||
AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
scope, bus, &callback, sizeof(callback));
|
||||
|
||||
#if MACOSX_COREAUDIO
|
||||
CloseComponent(this->hidden->audioUnit);
|
||||
@@ -556,4 +557,6 @@ AudioBootStrap COREAUDIO_bootstrap = {
|
||||
"coreaudio", "CoreAudio", COREAUDIO_Init, 0
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_COREAUDIO */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#ifndef _SDL_directsound_h
|
||||
#define _SDL_directsound_h
|
||||
|
||||
#include "directx.h"
|
||||
#include "../../core/windows/SDL_directx.h"
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_EMSCRIPTEN
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_log.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_emscriptenaudio.h"
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
static int
|
||||
copyData(_THIS)
|
||||
{
|
||||
int byte_len;
|
||||
|
||||
if (this->hidden->write_off + this->convert.len_cvt > this->hidden->mixlen) {
|
||||
if (this->hidden->write_off > this->hidden->read_off) {
|
||||
SDL_memmove(this->hidden->mixbuf,
|
||||
this->hidden->mixbuf + this->hidden->read_off,
|
||||
this->hidden->mixlen - this->hidden->read_off);
|
||||
this->hidden->write_off = this->hidden->write_off - this->hidden->read_off;
|
||||
} else {
|
||||
this->hidden->write_off = 0;
|
||||
}
|
||||
this->hidden->read_off = 0;
|
||||
}
|
||||
|
||||
SDL_memcpy(this->hidden->mixbuf + this->hidden->write_off,
|
||||
this->convert.buf,
|
||||
this->convert.len_cvt);
|
||||
this->hidden->write_off += this->convert.len_cvt;
|
||||
byte_len = this->hidden->write_off - this->hidden->read_off;
|
||||
|
||||
return byte_len;
|
||||
}
|
||||
|
||||
static void
|
||||
HandleAudioProcess(_THIS)
|
||||
{
|
||||
Uint8 *buf = NULL;
|
||||
int byte_len = 0;
|
||||
int bytes = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
|
||||
int bytes_in = SDL_AUDIO_BITSIZE(this->convert.src_format) / 8;
|
||||
|
||||
/* Only do soemthing if audio is enabled */
|
||||
if (!this->enabled)
|
||||
return;
|
||||
|
||||
if (this->paused)
|
||||
return;
|
||||
|
||||
if (this->convert.needed) {
|
||||
if (this->hidden->conv_in_len != 0) {
|
||||
this->convert.len = this->hidden->conv_in_len * bytes_in * this->spec.channels;
|
||||
}
|
||||
|
||||
(*this->spec.callback) (this->spec.userdata,
|
||||
this->convert.buf,
|
||||
this->convert.len);
|
||||
SDL_ConvertAudio(&this->convert);
|
||||
buf = this->convert.buf;
|
||||
byte_len = this->convert.len_cvt;
|
||||
|
||||
/* size mismatch*/
|
||||
if (byte_len != this->spec.size) {
|
||||
if (!this->hidden->mixbuf) {
|
||||
this->hidden->mixlen = this->spec.size > byte_len ? this->spec.size * 2 : byte_len * 2;
|
||||
this->hidden->mixbuf = SDL_malloc(this->hidden->mixlen);
|
||||
}
|
||||
|
||||
/* copy existing data */
|
||||
byte_len = copyData(this);
|
||||
|
||||
/* read more data*/
|
||||
while (byte_len < this->spec.size) {
|
||||
(*this->spec.callback) (this->spec.userdata,
|
||||
this->convert.buf,
|
||||
this->convert.len);
|
||||
SDL_ConvertAudio(&this->convert);
|
||||
byte_len = copyData(this);
|
||||
}
|
||||
|
||||
byte_len = this->spec.size;
|
||||
buf = this->hidden->mixbuf + this->hidden->read_off;
|
||||
this->hidden->read_off += byte_len;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!this->hidden->mixbuf) {
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = SDL_malloc(this->hidden->mixlen);
|
||||
}
|
||||
(*this->spec.callback) (this->spec.userdata,
|
||||
this->hidden->mixbuf,
|
||||
this->hidden->mixlen);
|
||||
buf = this->hidden->mixbuf;
|
||||
byte_len = this->hidden->mixlen;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
EM_ASM_ARGS({
|
||||
var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels'];
|
||||
for (var c = 0; c < numChannels; ++c) {
|
||||
var channelData = SDL2.audio.currentOutputBuffer['getChannelData'](c);
|
||||
if (channelData.length != $1) {
|
||||
throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
|
||||
}
|
||||
|
||||
for (var j = 0; j < $1; ++j) {
|
||||
channelData[j] = getValue($0 + (j*numChannels + c)*4, 'float');
|
||||
}
|
||||
}
|
||||
}, buf, byte_len / bytes / this->spec.channels);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Emscripten_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
/* Clean up the audio buffer */
|
||||
SDL_free(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Emscripten_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
SDL_bool valid_format = SDL_FALSE;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
int i;
|
||||
float f;
|
||||
int result;
|
||||
|
||||
while ((!valid_format) && (test_format)) {
|
||||
switch (test_format) {
|
||||
case AUDIO_F32: /* web audio only supports floats */
|
||||
this->spec.format = test_format;
|
||||
|
||||
valid_format = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
|
||||
if (!valid_format) {
|
||||
/* Didn't find a compatible format :( */
|
||||
return SDL_SetError("No compatible audio format!");
|
||||
}
|
||||
|
||||
/* 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_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* based on parts of library_sdl.js */
|
||||
|
||||
/* create context (TODO: this puts stuff in the global namespace...)*/
|
||||
result = EM_ASM_INT_V({
|
||||
if(typeof(SDL2) === 'undefined')
|
||||
SDL2 = {};
|
||||
|
||||
if(typeof(SDL2.audio) === 'undefined')
|
||||
SDL2.audio = {};
|
||||
|
||||
if (!SDL2.audioContext) {
|
||||
if (typeof(AudioContext) !== 'undefined') {
|
||||
SDL2.audioContext = new AudioContext();
|
||||
} else if (typeof(webkitAudioContext) !== 'undefined') {
|
||||
SDL2.audioContext = new webkitAudioContext();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
if (result < 0) {
|
||||
return SDL_SetError("Web Audio API is not available!");
|
||||
}
|
||||
|
||||
/* limit to native freq */
|
||||
int sampleRate = EM_ASM_INT_V({
|
||||
return SDL2.audioContext['sampleRate'];
|
||||
});
|
||||
|
||||
if(this->spec.freq != sampleRate) {
|
||||
for (i = this->spec.samples; i > 0; i--) {
|
||||
f = (float)i / (float)sampleRate * (float)this->spec.freq;
|
||||
if (SDL_floor(f) == f) {
|
||||
this->hidden->conv_in_len = SDL_floor(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->spec.freq = sampleRate;
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* setup a ScriptProcessorNode */
|
||||
EM_ASM_ARGS({
|
||||
SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
|
||||
SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
|
||||
SDL2.audio.currentOutputBuffer = e['outputBuffer'];
|
||||
Runtime.dynCall('vi', $2, [$3]);
|
||||
};
|
||||
SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
|
||||
}, this->spec.channels, this->spec.samples, HandleAudioProcess, this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
Emscripten_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = Emscripten_OpenDevice;
|
||||
impl->CloseDevice = Emscripten_CloseDevice;
|
||||
|
||||
/* only one output */
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
|
||||
/* no threads here */
|
||||
impl->SkipMixerLock = 1;
|
||||
impl->ProvidesOwnCallbackThread = 1;
|
||||
|
||||
/* check availability */
|
||||
int available = EM_ASM_INT_V({
|
||||
if (typeof(AudioContext) !== 'undefined') {
|
||||
return 1;
|
||||
} else if (typeof(webkitAudioContext) !== 'undefined') {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
AudioBootStrap EmscriptenAudio_bootstrap = {
|
||||
"emscripten", "SDL emscripten audio driver", Emscripten_Init, 0
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_EMSCRIPTEN */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_emscriptenaudio_h
|
||||
#define _SDL_emscriptenaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
Uint8 *mixbuf;
|
||||
Uint32 mixlen;
|
||||
|
||||
Uint32 conv_in_len;
|
||||
|
||||
Uint32 write_off, read_off;
|
||||
};
|
||||
|
||||
#endif /* _SDL_emscriptenaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_audiomem.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 NACLAUD_DRIVER_NAME "nacl"
|
||||
|
||||
#define SAMPLE_FRAME_COUNT 4096
|
||||
|
||||
/* Audio driver functions */
|
||||
static int NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture);
|
||||
static void NACLAUD_CloseDevice(_THIS);
|
||||
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* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data) {
|
||||
SDL_AudioDevice* _this = (SDL_AudioDevice*) data;
|
||||
|
||||
SDL_LockMutex(private->mutex);
|
||||
|
||||
if (_this->enabled && !_this->paused) {
|
||||
if (_this->convert.needed) {
|
||||
SDL_LockMutex(_this->mixer_lock);
|
||||
(*_this->spec.callback) (_this->spec.userdata,
|
||||
(Uint8 *) _this->convert.buf,
|
||||
_this->convert.len);
|
||||
SDL_UnlockMutex(_this->mixer_lock);
|
||||
SDL_ConvertAudio(&_this->convert);
|
||||
SDL_memcpy(samples, _this->convert.buf, _this->convert.len_cvt);
|
||||
} else {
|
||||
SDL_LockMutex(_this->mixer_lock);
|
||||
(*_this->spec.callback) (_this->spec.userdata, (Uint8 *) samples, buffer_size);
|
||||
SDL_UnlockMutex(_this->mixer_lock);
|
||||
}
|
||||
} else {
|
||||
SDL_memset(samples, 0, buffer_size);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NACLAUD_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);
|
||||
SDL_DestroyMutex(hidden->mutex);
|
||||
core->ReleaseResource(hidden->audio);
|
||||
}
|
||||
|
||||
static int
|
||||
NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture) {
|
||||
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) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private->mutex = SDL_CreateMutex();
|
||||
_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 1;
|
||||
}
|
||||
|
||||
static int
|
||||
NACLAUD_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
if (PSGetInstanceId() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = NACLAUD_OpenDevice;
|
||||
impl->CloseDevice = NACLAUD_CloseDevice;
|
||||
impl->HasCaptureSupport = 0;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
impl->OnlyHasDefaultInputDevice = 1;
|
||||
impl->ProvidesOwnCallbackThread = 1;
|
||||
/*
|
||||
* impl->WaitDevice = NACLAUD_WaitDevice;
|
||||
* impl->GetDeviceBuf = NACLAUD_GetDeviceBuf;
|
||||
* impl->PlayDevice = NACLAUD_PlayDevice;
|
||||
* impl->Deinitialize = NACLAUD_Deinitialize;
|
||||
*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
AudioBootStrap NACLAUD_bootstrap = {
|
||||
NACLAUD_DRIVER_NAME, "SDL NaCl Audio Driver",
|
||||
NACLAUD_Init, 0
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_NACL */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_naclaudio_h
|
||||
#define _SDL_naclaudio_h
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_mutex.h"
|
||||
|
||||
#include "ppapi/c/ppb_audio.h"
|
||||
|
||||
#define _THIS SDL_AudioDevice *_this
|
||||
#define private _this->hidden
|
||||
|
||||
typedef struct SDL_PrivateAudioData {
|
||||
SDL_mutex* mutex;
|
||||
PP_Resource audio;
|
||||
} SDL_PrivateAudioData;
|
||||
|
||||
#endif /* _SDL_naclaudio_h */
|
||||
@@ -18,6 +18,9 @@
|
||||
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_PSP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -191,5 +194,6 @@ AudioBootStrap PSPAUD_bootstrap = {
|
||||
|
||||
/* SDL_AUDI */
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_PSP */
|
||||
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the video functions */
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
#define NUM_BUFFERS 2
|
||||
|
||||
@@ -383,6 +383,7 @@ sub buildArbitraryResampleFunc {
|
||||
my $eps_adjust = ($upsample) ? 'dstsize' : 'srcsize';
|
||||
my $incr = '';
|
||||
my $incr2 = '';
|
||||
my $block_align = $channels * $fsize/8;
|
||||
|
||||
|
||||
# !!! FIXME: DEBUG_CONVERT should report frequencies.
|
||||
@@ -395,7 +396,7 @@ ${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - $fudge;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
const int dstsize = (int) (((double)(cvt->len_cvt/${block_align})) * cvt->rate_incr) * ${block_align};
|
||||
register int eps = 0;
|
||||
EOF
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
|
||||
/* !!! FIXME: SIO_DEVANY can be a specific device... */
|
||||
if ((this->hidden->dev = SNDIO_sio_open(NULL, SIO_PLAY, 0)) == NULL) {
|
||||
if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) {
|
||||
SNDIO_CloseDevice(this);
|
||||
return SDL_SetError("sio_open() failed");
|
||||
}
|
||||
@@ -229,7 +229,17 @@ SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
par.sig = SDL_AUDIO_ISSIGNED(test_format) ? 1 : 0;
|
||||
par.bits = SDL_AUDIO_BITSIZE(test_format);
|
||||
|
||||
if (SNDIO_sio_setpar(this->hidden->dev, &par) == 1) {
|
||||
if (SNDIO_sio_setpar(this->hidden->dev, &par) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
|
||||
SNDIO_CloseDevice(this);
|
||||
return SDL_SetError("sio_getpar() failed");
|
||||
}
|
||||
if (par.bps != SIO_BPS(par.bits)) {
|
||||
continue;
|
||||
}
|
||||
if ((par.bits == 8 * par.bps) || (par.msb)) {
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
@@ -242,26 +252,21 @@ SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
return SDL_SetError("sndio: Couldn't find any hardware audio formats");
|
||||
}
|
||||
|
||||
if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
|
||||
SNDIO_CloseDevice(this);
|
||||
return SDL_SetError("sio_getpar() failed");
|
||||
}
|
||||
|
||||
if ((par.bits == 32) && (par.sig) && (par.le))
|
||||
if ((par.bps == 4) && (par.sig) && (par.le))
|
||||
this->spec.format = AUDIO_S32LSB;
|
||||
else if ((par.bits == 32) && (par.sig) && (!par.le))
|
||||
else if ((par.bps == 4) && (par.sig) && (!par.le))
|
||||
this->spec.format = AUDIO_S32MSB;
|
||||
else if ((par.bits == 16) && (par.sig) && (par.le))
|
||||
else if ((par.bps == 2) && (par.sig) && (par.le))
|
||||
this->spec.format = AUDIO_S16LSB;
|
||||
else if ((par.bits == 16) && (par.sig) && (!par.le))
|
||||
else if ((par.bps == 2) && (par.sig) && (!par.le))
|
||||
this->spec.format = AUDIO_S16MSB;
|
||||
else if ((par.bits == 16) && (!par.sig) && (par.le))
|
||||
else if ((par.bps == 2) && (!par.sig) && (par.le))
|
||||
this->spec.format = AUDIO_U16LSB;
|
||||
else if ((par.bits == 16) && (!par.sig) && (!par.le))
|
||||
else if ((par.bps == 2) && (!par.sig) && (!par.le))
|
||||
this->spec.format = AUDIO_U16MSB;
|
||||
else if ((par.bits == 8) && (par.sig))
|
||||
else if ((par.bps == 1) && (par.sig))
|
||||
this->spec.format = AUDIO_S8;
|
||||
else if ((par.bits == 8) && (!par.sig))
|
||||
else if ((par.bps == 1) && (!par.sig))
|
||||
this->spec.format = AUDIO_U8;
|
||||
else {
|
||||
SNDIO_CloseDevice(this);
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
/* The configure script already did any necessary checking */
|
||||
# define SDL_XAUDIO2_HAS_SDK 1
|
||||
#elif defined(__WINRT__)
|
||||
/* WinRT always has access to the .the XAudio 2 SDK */
|
||||
/* WinRT always has access to the XAudio 2 SDK */
|
||||
# define SDL_XAUDIO2_HAS_SDK
|
||||
#else
|
||||
/* XAudio2 exists as of the March 2008 DirectX SDK
|
||||
@@ -241,14 +241,14 @@ XAUDIO2_WaitDone(_THIS)
|
||||
SDL_assert(!this->enabled); /* flag that stops playing. */
|
||||
IXAudio2SourceVoice_Discontinuity(source);
|
||||
#if SDL_XAUDIO2_WIN8
|
||||
IXAudio2SourceVoice_GetState(source, &state, 0);
|
||||
IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
|
||||
#else
|
||||
IXAudio2SourceVoice_GetState(source, &state);
|
||||
#endif
|
||||
while (state.BuffersQueued > 0) {
|
||||
SDL_SemWait(this->hidden->semaphore);
|
||||
#if SDL_XAUDIO2_WIN8
|
||||
IXAudio2SourceVoice_GetState(source, &state, 0);
|
||||
IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
|
||||
#else
|
||||
IXAudio2SourceVoice_GetState(source, &state);
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_log.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
@@ -43,8 +44,8 @@
|
||||
#define LOG_TAG "SDL_android"
|
||||
/* #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) */
|
||||
/* #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) */
|
||||
#define LOGI(...) do {} while (false)
|
||||
#define LOGE(...) do {} while (false)
|
||||
#define LOGI(...) do {} while (0)
|
||||
#define LOGE(...) do {} while (0)
|
||||
|
||||
/* Uncomment this to log messages entering and exiting methods in this file */
|
||||
/* #define DEBUG_JNI */
|
||||
@@ -56,7 +57,6 @@ static void Android_JNI_ThreadDestroyed(void*);
|
||||
*******************************************************************************/
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -79,14 +79,14 @@ static jmethodID midPollInputDevices;
|
||||
|
||||
/* Accelerometer data storage */
|
||||
static float fLastAccelerometer[3];
|
||||
static bool bHasNewData;
|
||||
static SDL_bool bHasNewData;
|
||||
|
||||
/*******************************************************************************
|
||||
Functions called by JNI
|
||||
*******************************************************************************/
|
||||
|
||||
/* Library init */
|
||||
jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
mJavaVM = vm;
|
||||
@@ -108,7 +108,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
}
|
||||
|
||||
/* Called before SDL_main() to initialize JNI bindings */
|
||||
void SDL_Android_Init(JNIEnv* mEnv, jclass cls)
|
||||
JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()");
|
||||
|
||||
@@ -131,7 +131,7 @@ void SDL_Android_Init(JNIEnv* mEnv, jclass cls)
|
||||
midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
|
||||
"pollInputDevices", "()V");
|
||||
|
||||
bHasNewData = false;
|
||||
bHasNewData = SDL_FALSE;
|
||||
|
||||
if(!midGetNativeSurface || !midFlipBuffers || !midAudioInit ||
|
||||
!midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit || !midPollInputDevices) {
|
||||
@@ -141,23 +141,23 @@ void SDL_Android_Init(JNIEnv* mEnv, jclass cls)
|
||||
}
|
||||
|
||||
/* Resize */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeResize(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeResize(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint width, jint height, jint format)
|
||||
jint width, jint height, jint format, jfloat rate)
|
||||
{
|
||||
Android_SetScreenResolution(width, height, format);
|
||||
Android_SetScreenResolution(width, height, format, rate);
|
||||
}
|
||||
|
||||
// Paddown
|
||||
int Java_org_libsdl_app_SDLActivity_onNativePadDown(
|
||||
/* Paddown */
|
||||
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_onNativePadDown(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
{
|
||||
return Android_OnPadDown(device_id, keycode);
|
||||
}
|
||||
|
||||
// Padup
|
||||
int Java_org_libsdl_app_SDLActivity_onNativePadUp(
|
||||
/* Padup */
|
||||
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_onNativePadUp(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
{
|
||||
@@ -165,7 +165,7 @@ int Java_org_libsdl_app_SDLActivity_onNativePadUp(
|
||||
}
|
||||
|
||||
/* Joy */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeJoy(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeJoy(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint axis, jfloat value)
|
||||
{
|
||||
@@ -173,7 +173,7 @@ void Java_org_libsdl_app_SDLActivity_onNativeJoy(
|
||||
}
|
||||
|
||||
/* POV Hat */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeHat(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeHat(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jint hat_id, jint x, jint y)
|
||||
{
|
||||
@@ -181,7 +181,7 @@ void Java_org_libsdl_app_SDLActivity_onNativeHat(
|
||||
}
|
||||
|
||||
|
||||
int Java_org_libsdl_app_SDLActivity_nativeAddJoystick(
|
||||
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeAddJoystick(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint device_id, jstring device_name, jint is_accelerometer,
|
||||
jint nbuttons, jint naxes, jint nhats, jint nballs)
|
||||
@@ -196,7 +196,7 @@ int Java_org_libsdl_app_SDLActivity_nativeAddJoystick(
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Java_org_libsdl_app_SDLActivity_nativeRemoveJoystick(
|
||||
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeRemoveJoystick(
|
||||
JNIEnv* env, jclass jcls, jint device_id)
|
||||
{
|
||||
return Android_RemoveJoystick(device_id);
|
||||
@@ -204,7 +204,7 @@ int Java_org_libsdl_app_SDLActivity_nativeRemoveJoystick(
|
||||
|
||||
|
||||
/* Surface Created */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass jcls)
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass jcls)
|
||||
{
|
||||
SDL_WindowData *data;
|
||||
SDL_VideoDevice *_this;
|
||||
@@ -230,7 +230,7 @@ void Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass
|
||||
}
|
||||
|
||||
/* Surface Destroyed */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(JNIEnv* env, jclass jcls)
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(JNIEnv* env, jclass jcls)
|
||||
{
|
||||
/* We have to clear the current context and destroy the egl surface here
|
||||
* Otherwise there's BAD_NATIVE_WINDOW errors coming from eglCreateWindowSurface on resume
|
||||
@@ -256,27 +256,27 @@ void Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(JNIEnv* env, jclas
|
||||
|
||||
}
|
||||
|
||||
void Java_org_libsdl_app_SDLActivity_nativeFlipBuffers(JNIEnv* env, jclass jcls)
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_nativeFlipBuffers(JNIEnv* env, jclass jcls)
|
||||
{
|
||||
SDL_GL_SwapWindow(Android_Window);
|
||||
}
|
||||
|
||||
/* Keydown */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
|
||||
JNIEnv* env, jclass jcls, jint keycode)
|
||||
{
|
||||
Android_OnKeyDown(keycode);
|
||||
}
|
||||
|
||||
/* Keyup */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
|
||||
JNIEnv* env, jclass jcls, jint keycode)
|
||||
{
|
||||
Android_OnKeyUp(keycode);
|
||||
}
|
||||
|
||||
/* Keyboard Focus Lost */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
|
||||
JNIEnv* env, jclass jcls)
|
||||
{
|
||||
/* Calling SDL_StopTextInput will take care of hiding the keyboard and cleaning up the DummyText widget */
|
||||
@@ -285,7 +285,7 @@ void Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
|
||||
|
||||
|
||||
/* Touch */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeTouch(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeTouch(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint touch_device_id_in, jint pointer_finger_id_in,
|
||||
jint action, jfloat x, jfloat y, jfloat p)
|
||||
@@ -294,25 +294,25 @@ void Java_org_libsdl_app_SDLActivity_onNativeTouch(
|
||||
}
|
||||
|
||||
/* Accelerometer */
|
||||
void Java_org_libsdl_app_SDLActivity_onNativeAccel(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jfloat x, jfloat y, jfloat z)
|
||||
{
|
||||
fLastAccelerometer[0] = x;
|
||||
fLastAccelerometer[1] = y;
|
||||
fLastAccelerometer[2] = z;
|
||||
bHasNewData = true;
|
||||
bHasNewData = SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Low memory */
|
||||
void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_nativeLowMemory(
|
||||
JNIEnv* env, jclass cls)
|
||||
{
|
||||
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
|
||||
}
|
||||
|
||||
/* Quit */
|
||||
void Java_org_libsdl_app_SDLActivity_nativeQuit(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_nativeQuit(
|
||||
JNIEnv* env, jclass cls)
|
||||
{
|
||||
/* Discard previous events. The user should have handled state storage
|
||||
@@ -328,7 +328,7 @@ void Java_org_libsdl_app_SDLActivity_nativeQuit(
|
||||
}
|
||||
|
||||
/* Pause */
|
||||
void Java_org_libsdl_app_SDLActivity_nativePause(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_nativePause(
|
||||
JNIEnv* env, jclass cls)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()");
|
||||
@@ -345,7 +345,7 @@ void Java_org_libsdl_app_SDLActivity_nativePause(
|
||||
}
|
||||
|
||||
/* Resume */
|
||||
void Java_org_libsdl_app_SDLActivity_nativeResume(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_nativeResume(
|
||||
JNIEnv* env, jclass cls)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeResume()");
|
||||
@@ -363,7 +363,7 @@ void Java_org_libsdl_app_SDLActivity_nativeResume(
|
||||
}
|
||||
}
|
||||
|
||||
void Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
|
||||
JNIEnv* env, jclass cls,
|
||||
jstring text, jint newCursorPosition)
|
||||
{
|
||||
@@ -374,7 +374,7 @@ void Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
|
||||
(*env)->ReleaseStringUTFChars(env, text, utftext);
|
||||
}
|
||||
|
||||
void Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
|
||||
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
|
||||
JNIEnv* env, jclass cls,
|
||||
jstring text, jint newCursorPosition)
|
||||
{
|
||||
@@ -385,7 +385,15 @@ void Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
|
||||
(*env)->ReleaseStringUTFChars(env, text, utftext);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_org_libsdl_app_SDLActivity_nativeGetHint(JNIEnv* env, jclass cls, jstring name) {
|
||||
const char *utfname = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
const char *hint = SDL_GetHint(utfname);
|
||||
|
||||
jstring result = (*env)->NewStringUTF(env, hint);
|
||||
(*env)->ReleaseStringUTFChars(env, name, utfname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Functions called by SDL into Java
|
||||
@@ -435,7 +443,7 @@ static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder)
|
||||
|
||||
static SDL_bool LocalReferenceHolder_IsActive()
|
||||
{
|
||||
return s_active > 0;
|
||||
return s_active > 0;
|
||||
}
|
||||
|
||||
ANativeWindow* Android_JNI_GetNativeWindow(void)
|
||||
@@ -478,7 +486,7 @@ SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
|
||||
for (i = 0; i < 3; ++i) {
|
||||
values[i] = fLastAccelerometer[i];
|
||||
}
|
||||
bHasNewData = false;
|
||||
bHasNewData = SDL_FALSE;
|
||||
retval = SDL_TRUE;
|
||||
}
|
||||
|
||||
@@ -540,12 +548,12 @@ int Android_JNI_SetupThread(void)
|
||||
* Audio support
|
||||
*/
|
||||
static jboolean audioBuffer16Bit = JNI_FALSE;
|
||||
static jboolean audioBufferStereo = JNI_FALSE;
|
||||
static jobject audioBuffer = NULL;
|
||||
static void* audioBufferPinned = NULL;
|
||||
|
||||
int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
|
||||
{
|
||||
jboolean audioBufferStereo;
|
||||
int audioBufferFrames;
|
||||
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
@@ -638,7 +646,7 @@ void Android_JNI_CloseAudioDevice()
|
||||
|
||||
/* Test for an exception and call SDL_SetError with its detail if one occurs */
|
||||
/* If the parameter silent is truthy then SDL_SetError() will not be called. */
|
||||
static bool Android_JNI_ExceptionOccurred(bool silent)
|
||||
static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent)
|
||||
{
|
||||
SDL_assert(LocalReferenceHolder_IsActive());
|
||||
JNIEnv *mEnv = Android_JNI_GetEnv();
|
||||
@@ -672,10 +680,10 @@ static bool Android_JNI_ExceptionOccurred(bool silent)
|
||||
(*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
|
||||
}
|
||||
|
||||
return true;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
return false;
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static int Internal_Android_JNI_FileOpen(SDL_RWops* ctx)
|
||||
@@ -719,19 +727,19 @@ static int Internal_Android_JNI_FileOpen(SDL_RWops* ctx)
|
||||
*/
|
||||
mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager), "openFd", "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
|
||||
inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
|
||||
if (Android_JNI_ExceptionOccurred(true)) {
|
||||
if (Android_JNI_ExceptionOccurred(SDL_TRUE)) {
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getStartOffset", "()J");
|
||||
ctx->hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
|
||||
if (Android_JNI_ExceptionOccurred(true)) {
|
||||
if (Android_JNI_ExceptionOccurred(SDL_TRUE)) {
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getDeclaredLength", "()J");
|
||||
ctx->hidden.androidio.size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
|
||||
if (Android_JNI_ExceptionOccurred(true)) {
|
||||
if (Android_JNI_ExceptionOccurred(SDL_TRUE)) {
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
@@ -745,7 +753,7 @@ static int Internal_Android_JNI_FileOpen(SDL_RWops* ctx)
|
||||
/* Seek to the correct offset in the file. */
|
||||
lseek(ctx->hidden.androidio.fd, (off_t)ctx->hidden.androidio.offset, SEEK_SET);
|
||||
|
||||
if (false) {
|
||||
if (0) {
|
||||
fallback:
|
||||
/* Disabled log message because of spam on the Nexus 7 */
|
||||
/* __android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file"); */
|
||||
@@ -757,8 +765,15 @@ fallback:
|
||||
mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
|
||||
"open", "(Ljava/lang/String;I)Ljava/io/InputStream;");
|
||||
inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /* ACCESS_RANDOM */);
|
||||
if (Android_JNI_ExceptionOccurred(false)) {
|
||||
goto failure;
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
// Try fallback to APK Extension files
|
||||
mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
|
||||
"openAPKExtensionInputStream", "(Ljava/lang/String;)Ljava/io/InputStream;");
|
||||
inputStream = (*mEnv)->CallObjectMethod(mEnv, context, mid, fileNameJString);
|
||||
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
|
||||
@@ -774,7 +789,7 @@ fallback:
|
||||
mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
|
||||
"available", "()I");
|
||||
ctx->hidden.androidio.size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
|
||||
if (Android_JNI_ExceptionOccurred(false)) {
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
@@ -785,7 +800,7 @@ fallback:
|
||||
"(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
|
||||
readableByteChannel = (*mEnv)->CallStaticObjectMethod(
|
||||
mEnv, channels, mid, inputStream);
|
||||
if (Android_JNI_ExceptionOccurred(false)) {
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
@@ -798,7 +813,7 @@ fallback:
|
||||
ctx->hidden.androidio.readMethod = mid;
|
||||
}
|
||||
|
||||
if (false) {
|
||||
if (0) {
|
||||
failure:
|
||||
result = -1;
|
||||
|
||||
@@ -891,7 +906,7 @@ size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
|
||||
/* result = readableByteChannel.read(...); */
|
||||
int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
|
||||
|
||||
if (Android_JNI_ExceptionOccurred(false)) {
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
LocalReferenceHolder_Cleanup(&refs);
|
||||
return 0;
|
||||
}
|
||||
@@ -916,7 +931,7 @@ size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Internal_Android_JNI_FileClose(SDL_RWops* ctx, bool release)
|
||||
static int Internal_Android_JNI_FileClose(SDL_RWops* ctx, SDL_bool release)
|
||||
{
|
||||
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
|
||||
|
||||
@@ -939,7 +954,7 @@ static int Internal_Android_JNI_FileClose(SDL_RWops* ctx, bool release)
|
||||
"close", "()V");
|
||||
(*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
|
||||
(*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.assetFileDescriptorRef);
|
||||
if (Android_JNI_ExceptionOccurred(false)) {
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
@@ -952,7 +967,7 @@ static int Internal_Android_JNI_FileClose(SDL_RWops* ctx, bool release)
|
||||
(*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
|
||||
(*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.inputStreamRef);
|
||||
(*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.readableByteChannelRef);
|
||||
if (Android_JNI_ExceptionOccurred(false)) {
|
||||
if (Android_JNI_ExceptionOccurred(SDL_FALSE)) {
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
@@ -1043,7 +1058,7 @@ Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
|
||||
} else if (movement < 0) {
|
||||
/* We can't seek backwards so we have to reopen the file and seek */
|
||||
/* forwards which obviously isn't very efficient */
|
||||
Internal_Android_JNI_FileClose(ctx, false);
|
||||
Internal_Android_JNI_FileClose(ctx, SDL_FALSE);
|
||||
Internal_Android_JNI_FileOpen(ctx);
|
||||
Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET);
|
||||
}
|
||||
@@ -1055,7 +1070,7 @@ Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
|
||||
|
||||
int Android_JNI_FileClose(SDL_RWops* ctx)
|
||||
{
|
||||
return Internal_Android_JNI_FileClose(ctx, true);
|
||||
return Internal_Android_JNI_FileClose(ctx, SDL_TRUE);
|
||||
}
|
||||
|
||||
/* returns a new global reference which needs to be released later */
|
||||
@@ -1286,6 +1301,9 @@ void Android_JNI_PollInputDevices()
|
||||
(*env)->CallStaticVoidMethod(env, mActivityClass, midPollInputDevices);
|
||||
}
|
||||
|
||||
/* See SDLActivity.java for constants. */
|
||||
#define COMMAND_SET_KEEP_SCREEN_ON 5
|
||||
|
||||
/* sends message to be handled on the UI event dispatch thread */
|
||||
int Android_JNI_SendMessage(int command, int param)
|
||||
{
|
||||
@@ -1301,6 +1319,11 @@ int Android_JNI_SendMessage(int command, int param)
|
||||
return success ? 0 : -1;
|
||||
}
|
||||
|
||||
void Android_JNI_SuspendScreenSaver(SDL_bool suspend)
|
||||
{
|
||||
Android_JNI_SendMessage(COMMAND_SET_KEEP_SCREEN_ON, (suspend == SDL_FALSE) ? 0 : 1);
|
||||
}
|
||||
|
||||
void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
@@ -1326,6 +1349,94 @@ void Android_JNI_HideTextInput()
|
||||
Android_JNI_SendMessage(COMMAND_TEXTEDIT_HIDE, 0);
|
||||
}
|
||||
|
||||
int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jclass clazz;
|
||||
jmethodID mid;
|
||||
jobject context;
|
||||
jstring title;
|
||||
jstring message;
|
||||
jintArray button_flags;
|
||||
jintArray button_ids;
|
||||
jobjectArray button_texts;
|
||||
jintArray colors;
|
||||
jobject text;
|
||||
jint temp;
|
||||
int i;
|
||||
|
||||
env = Android_JNI_GetEnv();
|
||||
|
||||
/* convert parameters */
|
||||
|
||||
clazz = (*env)->FindClass(env, "java/lang/String");
|
||||
|
||||
title = (*env)->NewStringUTF(env, messageboxdata->title);
|
||||
message = (*env)->NewStringUTF(env, messageboxdata->message);
|
||||
|
||||
button_flags = (*env)->NewIntArray(env, messageboxdata->numbuttons);
|
||||
button_ids = (*env)->NewIntArray(env, messageboxdata->numbuttons);
|
||||
button_texts = (*env)->NewObjectArray(env, messageboxdata->numbuttons,
|
||||
clazz, NULL);
|
||||
for (i = 0; i < messageboxdata->numbuttons; ++i) {
|
||||
temp = messageboxdata->buttons[i].flags;
|
||||
(*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp);
|
||||
temp = messageboxdata->buttons[i].buttonid;
|
||||
(*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp);
|
||||
text = (*env)->NewStringUTF(env, messageboxdata->buttons[i].text);
|
||||
(*env)->SetObjectArrayElement(env, button_texts, i, text);
|
||||
(*env)->DeleteLocalRef(env, text);
|
||||
}
|
||||
|
||||
if (messageboxdata->colorScheme) {
|
||||
colors = (*env)->NewIntArray(env, SDL_MESSAGEBOX_COLOR_MAX);
|
||||
for (i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; ++i) {
|
||||
temp = (0xFF << 24) |
|
||||
(messageboxdata->colorScheme->colors[i].r << 16) |
|
||||
(messageboxdata->colorScheme->colors[i].g << 8) |
|
||||
(messageboxdata->colorScheme->colors[i].b << 0);
|
||||
(*env)->SetIntArrayRegion(env, colors, i, 1, &temp);
|
||||
}
|
||||
} else {
|
||||
colors = NULL;
|
||||
}
|
||||
|
||||
(*env)->DeleteLocalRef(env, clazz);
|
||||
|
||||
/* call function */
|
||||
|
||||
mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext","()Landroid/content/Context;");
|
||||
|
||||
context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
|
||||
|
||||
clazz = (*env)->GetObjectClass(env, context);
|
||||
|
||||
mid = (*env)->GetMethodID(env, clazz,
|
||||
"messageboxShowMessageBox", "(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
|
||||
*buttonid = (*env)->CallIntMethod(env, context, mid,
|
||||
messageboxdata->flags,
|
||||
title,
|
||||
message,
|
||||
button_flags,
|
||||
button_ids,
|
||||
button_texts,
|
||||
colors);
|
||||
|
||||
(*env)->DeleteLocalRef(env, context);
|
||||
(*env)->DeleteLocalRef(env, clazz);
|
||||
|
||||
/* delete parameters */
|
||||
|
||||
(*env)->DeleteLocalRef(env, title);
|
||||
(*env)->DeleteLocalRef(env, message);
|
||||
(*env)->DeleteLocalRef(env, button_flags);
|
||||
(*env)->DeleteLocalRef(env, button_ids);
|
||||
(*env)->DeleteLocalRef(env, button_texts);
|
||||
(*env)->DeleteLocalRef(env, colors);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
@@ -68,6 +68,8 @@ int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seco
|
||||
/* Joystick support */
|
||||
void Android_JNI_PollInputDevices();
|
||||
|
||||
/* Video */
|
||||
void Android_JNI_SuspendScreenSaver(SDL_bool suspend);
|
||||
|
||||
/* Touch support */
|
||||
int Android_JNI_GetTouchDeviceIds(int **ids);
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_dbus.h"
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
/* we never link directly to libdbus. */
|
||||
#include "SDL_loadso.h"
|
||||
static const char *dbus_library = "libdbus-1.so.3";
|
||||
static void *dbus_handle = NULL;
|
||||
static unsigned int screensaver_cookie = 0;
|
||||
static SDL_DBusContext dbus = {0};
|
||||
|
||||
static int
|
||||
load_dbus_syms(void)
|
||||
{
|
||||
#define SDL_DBUS_SYM2(x, y) \
|
||||
if (!(dbus.x = SDL_LoadFunction(dbus_handle, #y))) return -1
|
||||
|
||||
#define SDL_DBUS_SYM(x) \
|
||||
SDL_DBUS_SYM2(x, dbus_##x)
|
||||
|
||||
SDL_DBUS_SYM(bus_get_private);
|
||||
SDL_DBUS_SYM(bus_register);
|
||||
SDL_DBUS_SYM(bus_add_match);
|
||||
SDL_DBUS_SYM(connection_open_private);
|
||||
SDL_DBUS_SYM(connection_set_exit_on_disconnect);
|
||||
SDL_DBUS_SYM(connection_get_is_connected);
|
||||
SDL_DBUS_SYM(connection_add_filter);
|
||||
SDL_DBUS_SYM(connection_send);
|
||||
SDL_DBUS_SYM(connection_send_with_reply_and_block);
|
||||
SDL_DBUS_SYM(connection_close);
|
||||
SDL_DBUS_SYM(connection_unref);
|
||||
SDL_DBUS_SYM(connection_flush);
|
||||
SDL_DBUS_SYM(connection_read_write);
|
||||
SDL_DBUS_SYM(connection_dispatch);
|
||||
SDL_DBUS_SYM(message_is_signal);
|
||||
SDL_DBUS_SYM(message_new_method_call);
|
||||
SDL_DBUS_SYM(message_append_args);
|
||||
SDL_DBUS_SYM(message_get_args);
|
||||
SDL_DBUS_SYM(message_iter_init);
|
||||
SDL_DBUS_SYM(message_iter_next);
|
||||
SDL_DBUS_SYM(message_iter_get_basic);
|
||||
SDL_DBUS_SYM(message_iter_get_arg_type);
|
||||
SDL_DBUS_SYM(message_iter_recurse);
|
||||
SDL_DBUS_SYM(message_unref);
|
||||
SDL_DBUS_SYM(error_init);
|
||||
SDL_DBUS_SYM(error_is_set);
|
||||
SDL_DBUS_SYM(error_free);
|
||||
SDL_DBUS_SYM(get_local_machine_id);
|
||||
SDL_DBUS_SYM(free);
|
||||
SDL_DBUS_SYM(shutdown);
|
||||
|
||||
#undef SDL_DBUS_SYM
|
||||
#undef SDL_DBUS_SYM2
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
UnloadDBUSLibrary(void)
|
||||
{
|
||||
if (dbus_handle != NULL) {
|
||||
SDL_UnloadObject(dbus_handle);
|
||||
dbus_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
LoadDBUSLibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (dbus_handle == NULL) {
|
||||
dbus_handle = SDL_LoadObject(dbus_library);
|
||||
if (dbus_handle == NULL) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
} else {
|
||||
retval = load_dbus_syms();
|
||||
if (retval < 0) {
|
||||
UnloadDBUSLibrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DBus_Init(void)
|
||||
{
|
||||
if (!dbus.session_conn && LoadDBUSLibrary() != -1) {
|
||||
DBusError err;
|
||||
dbus.error_init(&err);
|
||||
dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err);
|
||||
if (dbus.error_is_set(&err)) {
|
||||
dbus.error_free(&err);
|
||||
if (dbus.session_conn) {
|
||||
dbus.connection_unref(dbus.session_conn);
|
||||
dbus.session_conn = NULL;
|
||||
}
|
||||
return; /* oh well */
|
||||
}
|
||||
dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DBus_Quit(void)
|
||||
{
|
||||
if (dbus.session_conn) {
|
||||
dbus.connection_close(dbus.session_conn);
|
||||
dbus.connection_unref(dbus.session_conn);
|
||||
dbus.shutdown();
|
||||
SDL_memset(&dbus, 0, sizeof(dbus));
|
||||
}
|
||||
UnloadDBUSLibrary();
|
||||
}
|
||||
|
||||
SDL_DBusContext *
|
||||
SDL_DBus_GetContext(void)
|
||||
{
|
||||
if(!dbus_handle || !dbus.session_conn){
|
||||
SDL_DBus_Init();
|
||||
}
|
||||
|
||||
if(dbus_handle && dbus.session_conn){
|
||||
return &dbus;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DBus_ScreensaverTickle(void)
|
||||
{
|
||||
DBusConnection *conn = dbus.session_conn;
|
||||
if (conn != NULL) {
|
||||
DBusMessage *msg = dbus.message_new_method_call("org.gnome.ScreenSaver",
|
||||
"/org/gnome/ScreenSaver",
|
||||
"org.gnome.ScreenSaver",
|
||||
"SimulateUserActivity");
|
||||
if (msg != NULL) {
|
||||
if (dbus.connection_send(conn, msg, NULL)) {
|
||||
dbus.connection_flush(conn);
|
||||
}
|
||||
dbus.message_unref(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
|
||||
{
|
||||
DBusConnection *conn = dbus.session_conn;
|
||||
|
||||
if (conn == NULL)
|
||||
return SDL_FALSE;
|
||||
|
||||
if (inhibit &&
|
||||
screensaver_cookie != 0)
|
||||
return SDL_TRUE;
|
||||
if (!inhibit &&
|
||||
screensaver_cookie == 0)
|
||||
return SDL_TRUE;
|
||||
|
||||
if (inhibit) {
|
||||
const char *app = "My SDL application";
|
||||
const char *reason = "Playing a game";
|
||||
|
||||
DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
|
||||
"/org/freedesktop/ScreenSaver",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"Inhibit");
|
||||
if (msg != NULL) {
|
||||
dbus.message_append_args (msg,
|
||||
DBUS_TYPE_STRING, &app,
|
||||
DBUS_TYPE_STRING, &reason,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
if (msg != NULL) {
|
||||
DBusMessage *reply;
|
||||
|
||||
reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
|
||||
if (reply) {
|
||||
if (!dbus.message_get_args(reply, NULL,
|
||||
DBUS_TYPE_UINT32, &screensaver_cookie,
|
||||
DBUS_TYPE_INVALID))
|
||||
screensaver_cookie = 0;
|
||||
dbus.message_unref(reply);
|
||||
}
|
||||
|
||||
dbus.message_unref(msg);
|
||||
}
|
||||
|
||||
if (screensaver_cookie == 0) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
|
||||
"/org/freedesktop/ScreenSaver",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"UnInhibit");
|
||||
dbus.message_append_args (msg,
|
||||
DBUS_TYPE_UINT32, &screensaver_cookie,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (msg != NULL) {
|
||||
if (dbus.connection_send(conn, msg, NULL)) {
|
||||
dbus.connection_flush(conn);
|
||||
}
|
||||
dbus.message_unref(msg);
|
||||
}
|
||||
|
||||
screensaver_cookie = 0;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_dbus_h
|
||||
#define _SDL_dbus_h
|
||||
|
||||
#ifdef HAVE_DBUS_DBUS_H
|
||||
#define SDL_USE_LIBDBUS 1
|
||||
#include "SDL_stdinc.h"
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
|
||||
typedef struct SDL_DBusContext {
|
||||
DBusConnection *session_conn;
|
||||
|
||||
DBusConnection *(*bus_get_private)(DBusBusType, DBusError *);
|
||||
dbus_bool_t (*bus_register)(DBusConnection *, DBusError *);
|
||||
void (*bus_add_match)(DBusConnection *, const char *, DBusError *);
|
||||
DBusConnection * (*connection_open_private)(const char *, DBusError *);
|
||||
void (*connection_set_exit_on_disconnect)(DBusConnection *, dbus_bool_t);
|
||||
dbus_bool_t (*connection_get_is_connected)(DBusConnection *);
|
||||
dbus_bool_t (*connection_add_filter)(DBusConnection *, DBusHandleMessageFunction,
|
||||
void *, DBusFreeFunction);
|
||||
dbus_bool_t (*connection_send)(DBusConnection *, DBusMessage *, dbus_uint32_t *);
|
||||
DBusMessage *(*connection_send_with_reply_and_block)(DBusConnection *, DBusMessage *, int, DBusError *);
|
||||
void (*connection_close)(DBusConnection *);
|
||||
void (*connection_unref)(DBusConnection *);
|
||||
void (*connection_flush)(DBusConnection *);
|
||||
dbus_bool_t (*connection_read_write)(DBusConnection *, int);
|
||||
DBusDispatchStatus (*connection_dispatch)(DBusConnection *);
|
||||
dbus_bool_t (*message_is_signal)(DBusMessage *, const char *, const char *);
|
||||
DBusMessage *(*message_new_method_call)(const char *, const char *, const char *, const char *);
|
||||
dbus_bool_t (*message_append_args)(DBusMessage *, int, ...);
|
||||
dbus_bool_t (*message_get_args)(DBusMessage *, DBusError *, int, ...);
|
||||
dbus_bool_t (*message_iter_init)(DBusMessage *, DBusMessageIter *);
|
||||
dbus_bool_t (*message_iter_next)(DBusMessageIter *);
|
||||
void (*message_iter_get_basic)(DBusMessageIter *, void *);
|
||||
int (*message_iter_get_arg_type)(DBusMessageIter *);
|
||||
void (*message_iter_recurse)(DBusMessageIter *, DBusMessageIter *);
|
||||
void (*message_unref)(DBusMessage *);
|
||||
void (*error_init)(DBusError *);
|
||||
dbus_bool_t (*error_is_set)(const DBusError *);
|
||||
void (*error_free)(DBusError *);
|
||||
char *(*get_local_machine_id)(void);
|
||||
void (*free)(void *);
|
||||
void (*shutdown)(void);
|
||||
|
||||
} SDL_DBusContext;
|
||||
|
||||
extern void SDL_DBus_Init(void);
|
||||
extern void SDL_DBus_Quit(void);
|
||||
extern SDL_DBusContext * SDL_DBus_GetContext(void);
|
||||
extern void SDL_DBus_ScreensaverTickle(void);
|
||||
extern SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit);
|
||||
|
||||
#endif /* HAVE_DBUS_DBUS_H */
|
||||
|
||||
#endif /* _SDL_dbus_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -584,6 +584,10 @@ SDL_EVDEV_Poll(void)
|
||||
Uint32 kval;
|
||||
#endif
|
||||
|
||||
if (!_this) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBUDEV
|
||||
SDL_UDEV_Poll();
|
||||
#endif
|
||||
@@ -677,10 +681,10 @@ SDL_EVDEV_Poll(void)
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
|
||||
break;
|
||||
case REL_WHEEL:
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value);
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
case REL_HWHEEL:
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0);
|
||||
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,671 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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 HAVE_IBUS_IBUS_H
|
||||
#include "SDL.h"
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_ibus.h"
|
||||
#include "SDL_dbus.h"
|
||||
#include "../../video/SDL_sysvideo.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
#include "../../video/x11/SDL_x11video.h"
|
||||
#endif
|
||||
|
||||
#include <sys/inotify.h>
|
||||
#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_INTERFACE[] = "org.freedesktop.IBus";
|
||||
static const char IBUS_INPUT_INTERFACE[] = "org.freedesktop.IBus.InputContext";
|
||||
|
||||
static char *input_ctx_path = NULL;
|
||||
static SDL_Rect ibus_cursor_rect = {0};
|
||||
static DBusConnection *ibus_conn = NULL;
|
||||
static char *ibus_addr_file = NULL;
|
||||
int inotify_fd = -1, inotify_wd = -1;
|
||||
|
||||
static Uint32
|
||||
IBus_ModState(void)
|
||||
{
|
||||
Uint32 ibus_mods = 0;
|
||||
SDL_Keymod sdl_mods = SDL_GetModState();
|
||||
|
||||
/* Not sure about MOD3, MOD4 and HYPER mappings */
|
||||
if (sdl_mods & KMOD_LSHIFT) ibus_mods |= IBUS_SHIFT_MASK;
|
||||
if (sdl_mods & KMOD_CAPS) ibus_mods |= IBUS_LOCK_MASK;
|
||||
if (sdl_mods & KMOD_LCTRL) ibus_mods |= IBUS_CONTROL_MASK;
|
||||
if (sdl_mods & KMOD_LALT) ibus_mods |= IBUS_MOD1_MASK;
|
||||
if (sdl_mods & KMOD_NUM) ibus_mods |= IBUS_MOD2_MASK;
|
||||
if (sdl_mods & KMOD_MODE) ibus_mods |= IBUS_MOD5_MASK;
|
||||
if (sdl_mods & KMOD_LGUI) ibus_mods |= IBUS_SUPER_MASK;
|
||||
if (sdl_mods & KMOD_RGUI) ibus_mods |= IBUS_META_MASK;
|
||||
|
||||
return ibus_mods;
|
||||
}
|
||||
|
||||
static const char *
|
||||
IBus_GetVariantText(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus)
|
||||
{
|
||||
/* The text we need is nested weirdly, use dbus-monitor to see the structure better */
|
||||
const char *text = NULL;
|
||||
const char *struct_id = NULL;
|
||||
DBusMessageIter sub1, sub2;
|
||||
|
||||
if (dbus->message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_recurse(iter, &sub1);
|
||||
|
||||
if (dbus->message_iter_get_arg_type(&sub1) != DBUS_TYPE_STRUCT) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_recurse(&sub1, &sub2);
|
||||
|
||||
if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_get_basic(&sub2, &struct_id);
|
||||
if (!struct_id || SDL_strncmp(struct_id, "IBusText", sizeof("IBusText")) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_next(&sub2);
|
||||
dbus->message_iter_next(&sub2);
|
||||
|
||||
if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus->message_iter_get_basic(&sub2, &text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
static size_t
|
||||
IBus_utf8_strlen(const char *str)
|
||||
{
|
||||
size_t utf8_len = 0;
|
||||
const char *p;
|
||||
|
||||
for (p = str; *p; ++p) {
|
||||
if (!((*p & 0x80) && !(*p & 0x40))) {
|
||||
++utf8_len;
|
||||
}
|
||||
}
|
||||
|
||||
return utf8_len;
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
IBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *user_data)
|
||||
{
|
||||
SDL_DBusContext *dbus = (SDL_DBusContext *)user_data;
|
||||
|
||||
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "CommitText")) {
|
||||
DBusMessageIter iter;
|
||||
const char *text;
|
||||
|
||||
dbus->message_iter_init(msg, &iter);
|
||||
|
||||
text = IBus_GetVariantText(conn, &iter, dbus);
|
||||
if (text && *text) {
|
||||
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
|
||||
size_t text_bytes = SDL_strlen(text), i = 0;
|
||||
|
||||
while (i < text_bytes) {
|
||||
size_t sz = SDL_utf8strlcpy(buf, text+i, sizeof(buf));
|
||||
SDL_SendKeyboardText(buf);
|
||||
|
||||
i += sz;
|
||||
}
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "UpdatePreeditText")) {
|
||||
DBusMessageIter iter;
|
||||
const char *text;
|
||||
|
||||
dbus->message_iter_init(msg, &iter);
|
||||
text = IBus_GetVariantText(conn, &iter, dbus);
|
||||
|
||||
if (text && *text) {
|
||||
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
|
||||
size_t text_bytes = SDL_strlen(text), i = 0;
|
||||
size_t cursor = 0;
|
||||
|
||||
while (i < text_bytes) {
|
||||
size_t sz = SDL_utf8strlcpy(buf, text+i, sizeof(buf));
|
||||
size_t chars = IBus_utf8_strlen(buf);
|
||||
|
||||
SDL_SendEditingText(buf, cursor, chars);
|
||||
|
||||
i += sz;
|
||||
cursor += chars;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
if (dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "HidePreeditText")) {
|
||||
SDL_SendEditingText("", 0, 0);
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static char *
|
||||
IBus_ReadAddressFromFile(const char *file_path)
|
||||
{
|
||||
char addr_buf[1024];
|
||||
SDL_bool success = SDL_FALSE;
|
||||
FILE *addr_file;
|
||||
|
||||
addr_file = fopen(file_path, "r");
|
||||
if (!addr_file) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (fgets(addr_buf, sizeof(addr_buf), addr_file)) {
|
||||
if (SDL_strncmp(addr_buf, "IBUS_ADDRESS=", sizeof("IBUS_ADDRESS=")-1) == 0) {
|
||||
size_t sz = SDL_strlen(addr_buf);
|
||||
if (addr_buf[sz-1] == '\n') addr_buf[sz-1] = 0;
|
||||
if (addr_buf[sz-2] == '\r') addr_buf[sz-2] = 0;
|
||||
success = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(addr_file);
|
||||
|
||||
if (success) {
|
||||
return SDL_strdup(addr_buf + (sizeof("IBUS_ADDRESS=") - 1));
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
IBus_GetDBusAddressFilename(void)
|
||||
{
|
||||
SDL_DBusContext *dbus;
|
||||
const char *disp_env;
|
||||
char config_dir[PATH_MAX];
|
||||
char *display = NULL;
|
||||
const char *addr;
|
||||
const char *conf_env;
|
||||
char *key;
|
||||
char file_path[PATH_MAX];
|
||||
const char *host;
|
||||
char *disp_num, *screen_num;
|
||||
|
||||
if (ibus_addr_file) {
|
||||
return SDL_strdup(ibus_addr_file);
|
||||
}
|
||||
|
||||
dbus = SDL_DBus_GetContext();
|
||||
if (!dbus) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Use this environment variable if it exists. */
|
||||
addr = SDL_getenv("IBUS_ADDRESS");
|
||||
if (addr && *addr) {
|
||||
return SDL_strdup(addr);
|
||||
}
|
||||
|
||||
/* Otherwise, we have to get the hostname, display, machine id, config dir
|
||||
and look up the address from a filepath using all those bits, eek. */
|
||||
disp_env = SDL_getenv("DISPLAY");
|
||||
|
||||
if (!disp_env || !*disp_env) {
|
||||
display = SDL_strdup(":0.0");
|
||||
} else {
|
||||
display = SDL_strdup(disp_env);
|
||||
}
|
||||
|
||||
host = display;
|
||||
disp_num = SDL_strrchr(display, ':');
|
||||
screen_num = SDL_strrchr(display, '.');
|
||||
|
||||
if (!disp_num) {
|
||||
SDL_free(display);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*disp_num = 0;
|
||||
disp_num++;
|
||||
|
||||
if (screen_num) {
|
||||
*screen_num = 0;
|
||||
}
|
||||
|
||||
if (!*host) {
|
||||
host = "unix";
|
||||
}
|
||||
|
||||
SDL_memset(config_dir, 0, sizeof(config_dir));
|
||||
|
||||
conf_env = SDL_getenv("XDG_CONFIG_HOME");
|
||||
if (conf_env && *conf_env) {
|
||||
SDL_strlcpy(config_dir, conf_env, sizeof(config_dir));
|
||||
} else {
|
||||
const char *home_env = SDL_getenv("HOME");
|
||||
if (!home_env || !*home_env) {
|
||||
SDL_free(display);
|
||||
return NULL;
|
||||
}
|
||||
SDL_snprintf(config_dir, sizeof(config_dir), "%s/.config", home_env);
|
||||
}
|
||||
|
||||
key = dbus->get_local_machine_id();
|
||||
|
||||
SDL_memset(file_path, 0, sizeof(file_path));
|
||||
SDL_snprintf(file_path, sizeof(file_path), "%s/ibus/bus/%s-%s-%s",
|
||||
config_dir, key, host, disp_num);
|
||||
dbus->free(key);
|
||||
SDL_free(display);
|
||||
|
||||
return SDL_strdup(file_path);
|
||||
}
|
||||
|
||||
static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus);
|
||||
|
||||
static void
|
||||
IBus_SetCapabilities(void *data, const char *name, const char *old_val,
|
||||
const char *internal_editing)
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
|
||||
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
|
||||
input_ctx_path,
|
||||
IBUS_INPUT_INTERFACE,
|
||||
"SetCapabilities");
|
||||
if (msg) {
|
||||
Uint32 caps = IBUS_CAP_FOCUS;
|
||||
if (!(internal_editing && *internal_editing == '1')) {
|
||||
caps |= IBUS_CAP_PREEDIT_TEXT;
|
||||
}
|
||||
|
||||
dbus->message_append_args(msg,
|
||||
DBUS_TYPE_UINT32, &caps,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
if (dbus->connection_send(ibus_conn, msg, NULL)) {
|
||||
dbus->connection_flush(ibus_conn);
|
||||
}
|
||||
dbus->message_unref(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static SDL_bool
|
||||
IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
|
||||
{
|
||||
const char *path = NULL;
|
||||
SDL_bool result = SDL_FALSE;
|
||||
DBusMessage *msg;
|
||||
|
||||
ibus_conn = dbus->connection_open_private(addr, NULL);
|
||||
|
||||
if (!ibus_conn) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
dbus->connection_flush(ibus_conn);
|
||||
|
||||
if (!dbus->bus_register(ibus_conn, NULL)) {
|
||||
ibus_conn = NULL;
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
dbus->connection_flush(ibus_conn);
|
||||
|
||||
msg = dbus->message_new_method_call(IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext");
|
||||
if (msg) {
|
||||
const char *client_name = "SDL2_Application";
|
||||
dbus->message_append_args(msg,
|
||||
DBUS_TYPE_STRING, &client_name,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
DBusMessage *reply;
|
||||
|
||||
reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 1000, NULL);
|
||||
if (reply) {
|
||||
if (dbus->message_get_args(reply, NULL,
|
||||
DBUS_TYPE_OBJECT_PATH, &path,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
if (input_ctx_path) {
|
||||
SDL_free(input_ctx_path);
|
||||
}
|
||||
input_ctx_path = SDL_strdup(path);
|
||||
result = SDL_TRUE;
|
||||
}
|
||||
dbus->message_unref(reply);
|
||||
}
|
||||
dbus->message_unref(msg);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
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->connection_add_filter(ibus_conn, &IBus_MessageFilter, dbus, NULL);
|
||||
dbus->connection_flush(ibus_conn);
|
||||
}
|
||||
|
||||
SDL_IBus_SetFocus(SDL_GetKeyboardFocus() != NULL);
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
IBus_CheckConnection(SDL_DBusContext *dbus)
|
||||
{
|
||||
if (!dbus) return SDL_FALSE;
|
||||
|
||||
if (ibus_conn && dbus->connection_get_is_connected(ibus_conn)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
if (inotify_fd > 0 && inotify_wd > 0) {
|
||||
char buf[1024];
|
||||
ssize_t readsize = read(inotify_fd, buf, sizeof(buf));
|
||||
if (readsize > 0) {
|
||||
|
||||
char *p;
|
||||
SDL_bool file_updated = SDL_FALSE;
|
||||
|
||||
for (p = buf; p < buf + readsize; /**/) {
|
||||
struct inotify_event *event = (struct inotify_event*) p;
|
||||
if (event->len > 0) {
|
||||
char *addr_file_no_path = SDL_strrchr(ibus_addr_file, '/');
|
||||
if (!addr_file_no_path) return SDL_FALSE;
|
||||
|
||||
if (SDL_strcmp(addr_file_no_path + 1, event->name) == 0) {
|
||||
file_updated = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p += sizeof(struct inotify_event) + event->len;
|
||||
}
|
||||
|
||||
if (file_updated) {
|
||||
char *addr = IBus_ReadAddressFromFile(ibus_addr_file);
|
||||
if (addr) {
|
||||
SDL_bool result = IBus_SetupConnection(dbus, addr);
|
||||
SDL_free(addr);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IBus_Init(void)
|
||||
{
|
||||
SDL_bool result = SDL_FALSE;
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (dbus) {
|
||||
char *addr_file = IBus_GetDBusAddressFilename();
|
||||
char *addr;
|
||||
char *addr_file_dir;
|
||||
|
||||
if (!addr_file) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
ibus_addr_file = SDL_strdup(addr_file);
|
||||
|
||||
addr = IBus_ReadAddressFromFile(addr_file);
|
||||
|
||||
if (inotify_fd < 0) {
|
||||
inotify_fd = inotify_init();
|
||||
fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
|
||||
addr_file_dir = SDL_strrchr(addr_file, '/');
|
||||
if (addr_file_dir) {
|
||||
*addr_file_dir = 0;
|
||||
}
|
||||
|
||||
inotify_wd = inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY);
|
||||
SDL_free(addr_file);
|
||||
|
||||
result = IBus_SetupConnection(dbus, addr);
|
||||
SDL_free(addr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_Quit(void)
|
||||
{
|
||||
SDL_DBusContext *dbus;
|
||||
|
||||
if (input_ctx_path) {
|
||||
SDL_free(input_ctx_path);
|
||||
input_ctx_path = NULL;
|
||||
}
|
||||
|
||||
if (ibus_addr_file) {
|
||||
SDL_free(ibus_addr_file);
|
||||
ibus_addr_file = NULL;
|
||||
}
|
||||
|
||||
dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (dbus && ibus_conn) {
|
||||
dbus->connection_close(ibus_conn);
|
||||
dbus->connection_unref(ibus_conn);
|
||||
}
|
||||
|
||||
if (inotify_fd > 0 && inotify_wd > 0) {
|
||||
inotify_rm_watch(inotify_fd, inotify_wd);
|
||||
inotify_wd = -1;
|
||||
}
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
|
||||
|
||||
SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect));
|
||||
}
|
||||
|
||||
static void
|
||||
IBus_SimpleMessage(const char *method)
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
|
||||
input_ctx_path,
|
||||
IBUS_INPUT_INTERFACE,
|
||||
method);
|
||||
if (msg) {
|
||||
if (dbus->connection_send(ibus_conn, msg, NULL)) {
|
||||
dbus->connection_flush(ibus_conn);
|
||||
}
|
||||
dbus->message_unref(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_SetFocus(SDL_bool focused)
|
||||
{
|
||||
const char *method = focused ? "FocusIn" : "FocusOut";
|
||||
IBus_SimpleMessage(method);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_Reset(void)
|
||||
{
|
||||
IBus_SimpleMessage("Reset");
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
|
||||
{
|
||||
SDL_bool result = SDL_FALSE;
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
|
||||
input_ctx_path,
|
||||
IBUS_INPUT_INTERFACE,
|
||||
"ProcessKeyEvent");
|
||||
if (msg) {
|
||||
Uint32 mods = IBus_ModState();
|
||||
dbus->message_append_args(msg,
|
||||
DBUS_TYPE_UINT32, &keysym,
|
||||
DBUS_TYPE_UINT32, &keycode,
|
||||
DBUS_TYPE_UINT32, &mods,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
DBusMessage *reply;
|
||||
|
||||
reply = dbus->connection_send_with_reply_and_block(ibus_conn, msg, 300, NULL);
|
||||
if (reply) {
|
||||
if (!dbus->message_get_args(reply, NULL,
|
||||
DBUS_TYPE_BOOLEAN, &result,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
result = SDL_FALSE;
|
||||
}
|
||||
dbus->message_unref(reply);
|
||||
}
|
||||
dbus->message_unref(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_UpdateTextRect(SDL_Rect *rect)
|
||||
{
|
||||
SDL_Window *focused_win;
|
||||
SDL_SysWMinfo info;
|
||||
int x = 0, y = 0;
|
||||
SDL_DBusContext *dbus;
|
||||
|
||||
if (rect) {
|
||||
SDL_memcpy(&ibus_cursor_rect, rect, sizeof(ibus_cursor_rect));
|
||||
}
|
||||
|
||||
focused_win = SDL_GetKeyboardFocus();
|
||||
if (!focused_win) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_VERSION(&info.version);
|
||||
if (!SDL_GetWindowWMInfo(focused_win, &info)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GetWindowPosition(focused_win, &x, &y);
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
if (info.subsystem == SDL_SYSWM_X11) {
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
|
||||
|
||||
Display *x_disp = info.info.x11.display;
|
||||
Window x_win = info.info.x11.window;
|
||||
int x_screen = displaydata->screen;
|
||||
Window unused;
|
||||
|
||||
X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
|
||||
}
|
||||
#endif
|
||||
|
||||
x += ibus_cursor_rect.x;
|
||||
y += ibus_cursor_rect.y;
|
||||
|
||||
dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
|
||||
input_ctx_path,
|
||||
IBUS_INPUT_INTERFACE,
|
||||
"SetCursorLocation");
|
||||
if (msg) {
|
||||
dbus->message_append_args(msg,
|
||||
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);
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
if (dbus->connection_send(ibus_conn, msg, NULL)) {
|
||||
dbus->connection_flush(ibus_conn);
|
||||
}
|
||||
dbus->message_unref(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_IBus_PumpEvents(void)
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if (IBus_CheckConnection(dbus)) {
|
||||
dbus->connection_read_write(ibus_conn, 0);
|
||||
|
||||
while (dbus->connection_dispatch(ibus_conn) == DBUS_DISPATCH_DATA_REMAINS) {
|
||||
/* Do nothing, actual work happens in IBus_MessageFilter */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_ibus_h
|
||||
#define _SDL_ibus_h
|
||||
|
||||
#ifdef HAVE_IBUS_IBUS_H
|
||||
#define SDL_USE_IBUS 1
|
||||
#include "SDL_stdinc.h"
|
||||
#include <ibus-1.0/ibus.h>
|
||||
|
||||
extern SDL_bool SDL_IBus_Init(void);
|
||||
extern void SDL_IBus_Quit(void);
|
||||
|
||||
/* Lets the IBus server know about changes in window focus */
|
||||
extern void SDL_IBus_SetFocus(SDL_bool focused);
|
||||
|
||||
/* Closes the candidate list and resets any text currently being edited */
|
||||
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. */
|
||||
extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
|
||||
|
||||
/* Update the position of IBus' candidate list. If rect is NULL then this will
|
||||
just reposition it relative to the focused window's new position. */
|
||||
extern void SDL_IBus_UpdateTextRect(SDL_Rect *window_relative_rect);
|
||||
|
||||
/* Checks DBus for new IBus events, and calls SDL_SendKeyboardText /
|
||||
SDL_SendEditingText for each event it finds */
|
||||
extern void SDL_IBus_PumpEvents();
|
||||
|
||||
#endif /* HAVE_IBUS_IBUS_H */
|
||||
|
||||
#endif /* _SDL_ibus_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -25,18 +25,19 @@
|
||||
* udevadm info --query=all -n input/event3 (for a keyboard, mouse, etc)
|
||||
* udevadm info --query=property -n input/event2
|
||||
*/
|
||||
|
||||
#include "SDL_udev.h"
|
||||
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
static char* SDL_UDEV_LIBS[] = { "libudev.so.1", "libudev.so.0" };
|
||||
|
||||
#define _THIS SDL_UDEV_PrivateData *_this
|
||||
static _THIS = NULL;
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr);
|
||||
static int SDL_UDEV_load_syms(void);
|
||||
static SDL_bool SDL_UDEV_hotplug_update_available(void);
|
||||
@@ -64,7 +65,9 @@ SDL_UDEV_load_syms(void)
|
||||
SDL_UDEV_SYM(udev_device_get_action);
|
||||
SDL_UDEV_SYM(udev_device_get_devnode);
|
||||
SDL_UDEV_SYM(udev_device_get_subsystem);
|
||||
SDL_UDEV_SYM(udev_device_get_parent_with_subsystem_devtype);
|
||||
SDL_UDEV_SYM(udev_device_get_property_value);
|
||||
SDL_UDEV_SYM(udev_device_get_sysattr_value);
|
||||
SDL_UDEV_SYM(udev_device_new_from_syspath);
|
||||
SDL_UDEV_SYM(udev_device_unref);
|
||||
SDL_UDEV_SYM(udev_enumerate_add_match_property);
|
||||
@@ -274,6 +277,109 @@ SDL_UDEV_LoadLibrary(void)
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
|
||||
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
|
||||
#define OFF(x) ((x)%BITS_PER_LONG)
|
||||
#define BIT(x) (1UL<<OFF(x))
|
||||
#define LONG(x) ((x)/BITS_PER_LONG)
|
||||
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
|
||||
|
||||
static void get_caps(struct udev_device *dev, struct udev_device *pdev, const char *attr, unsigned long *bitmask, size_t bitmask_len)
|
||||
{
|
||||
const char *value;
|
||||
char text[4096];
|
||||
char *word;
|
||||
int i;
|
||||
unsigned long v;
|
||||
|
||||
SDL_memset(bitmask, 0, bitmask_len*sizeof(*bitmask));
|
||||
value = _this->udev_device_get_sysattr_value(pdev, attr);
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_strlcpy(text, value, sizeof(text));
|
||||
i = 0;
|
||||
while ((word = SDL_strrchr(text, ' ')) != NULL) {
|
||||
v = SDL_strtoul(word+1, NULL, 16);
|
||||
if (i < bitmask_len) {
|
||||
bitmask[i] = v;
|
||||
}
|
||||
++i;
|
||||
*word = '\0';
|
||||
}
|
||||
v = SDL_strtoul(text, NULL, 16);
|
||||
if (i < bitmask_len) {
|
||||
bitmask[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
guess_device_class(struct udev_device *dev)
|
||||
{
|
||||
int devclass = 0;
|
||||
struct udev_device *pdev;
|
||||
unsigned long bitmask_ev[NBITS(EV_MAX)];
|
||||
unsigned long bitmask_abs[NBITS(ABS_MAX)];
|
||||
unsigned long bitmask_key[NBITS(KEY_MAX)];
|
||||
unsigned long bitmask_rel[NBITS(REL_MAX)];
|
||||
unsigned long keyboard_mask;
|
||||
|
||||
/* walk up the parental chain until we find the real input device; the
|
||||
* argument is very likely a subdevice of this, like eventN */
|
||||
pdev = dev;
|
||||
while (pdev && !_this->udev_device_get_sysattr_value(pdev, "capabilities/ev")) {
|
||||
pdev = _this->udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL);
|
||||
}
|
||||
if (!pdev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_caps(dev, pdev, "capabilities/ev", bitmask_ev, SDL_arraysize(bitmask_ev));
|
||||
get_caps(dev, pdev, "capabilities/abs", bitmask_abs, SDL_arraysize(bitmask_abs));
|
||||
get_caps(dev, pdev, "capabilities/rel", bitmask_rel, SDL_arraysize(bitmask_rel));
|
||||
get_caps(dev, pdev, "capabilities/key", bitmask_key, SDL_arraysize(bitmask_key));
|
||||
|
||||
if (test_bit(EV_ABS, bitmask_ev) &&
|
||||
test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs)) {
|
||||
if (test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key)) {
|
||||
; /* ID_INPUT_TABLET */
|
||||
} else if (test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key)) {
|
||||
; /* ID_INPUT_TOUCHPAD */
|
||||
} else if (test_bit(BTN_MOUSE, bitmask_key)) {
|
||||
devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */
|
||||
} else if (test_bit(BTN_TOUCH, bitmask_key)) {
|
||||
; /* ID_INPUT_TOUCHSCREEN */
|
||||
} else if (test_bit(BTN_TRIGGER, bitmask_key) ||
|
||||
test_bit(BTN_A, bitmask_key) ||
|
||||
test_bit(BTN_1, bitmask_key) ||
|
||||
test_bit(ABS_RX, bitmask_abs) ||
|
||||
test_bit(ABS_RY, bitmask_abs) ||
|
||||
test_bit(ABS_RZ, bitmask_abs) ||
|
||||
test_bit(ABS_THROTTLE, bitmask_abs) ||
|
||||
test_bit(ABS_RUDDER, bitmask_abs) ||
|
||||
test_bit(ABS_WHEEL, bitmask_abs) ||
|
||||
test_bit(ABS_GAS, bitmask_abs) ||
|
||||
test_bit(ABS_BRAKE, bitmask_abs)) {
|
||||
devclass |= SDL_UDEV_DEVICE_JOYSTICK; /* ID_INPUT_JOYSTICK */
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(EV_REL, bitmask_ev) &&
|
||||
test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel) &&
|
||||
test_bit(BTN_MOUSE, bitmask_key)) {
|
||||
devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */
|
||||
}
|
||||
|
||||
/* the first 32 bits are ESC, numbers, and Q to D; if we have any of
|
||||
* those, consider it a keyboard device; do not test KEY_RESERVED, though */
|
||||
keyboard_mask = 0xFFFFFFFE;
|
||||
if ((bitmask_key[0] & keyboard_mask) != 0)
|
||||
devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEYBOARD */
|
||||
|
||||
return devclass;
|
||||
}
|
||||
|
||||
static void
|
||||
device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
||||
{
|
||||
@@ -292,6 +398,8 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
||||
if (SDL_strcmp(subsystem, "sound") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_SOUND;
|
||||
} else if (SDL_strcmp(subsystem, "input") == 0) {
|
||||
/* udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c */
|
||||
|
||||
val = _this->udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_JOYSTICK;
|
||||
@@ -302,13 +410,34 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
||||
devclass |= SDL_UDEV_DEVICE_MOUSE;
|
||||
}
|
||||
|
||||
val = _this->udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
|
||||
/* The undocumented rule is:
|
||||
- All devices with keys get ID_INPUT_KEY
|
||||
- From this subset, if they have ESC, numbers, and Q to D, it also gets ID_INPUT_KEYBOARD
|
||||
|
||||
Ref: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c#n183
|
||||
*/
|
||||
val = _this->udev_device_get_property_value(dev, "ID_INPUT_KEY");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_KEYBOARD;
|
||||
}
|
||||
|
||||
if (devclass == 0) {
|
||||
return;
|
||||
/* Fall back to old style input classes */
|
||||
val = _this->udev_device_get_property_value(dev, "ID_CLASS");
|
||||
if (val != NULL) {
|
||||
if (SDL_strcmp(val, "joystick") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_JOYSTICK;
|
||||
} else if (SDL_strcmp(val, "mouse") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_MOUSE;
|
||||
} else if (SDL_strcmp(val, "kbd") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_KEYBOARD;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* We could be linked with libudev on a system that doesn't have udev running */
|
||||
devclass = guess_device_class(dev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
|
||||
@@ -75,7 +75,9 @@ typedef struct SDL_UDEV_PrivateData
|
||||
const char *(*udev_device_get_action)(struct udev_device *);
|
||||
const char *(*udev_device_get_devnode)(struct udev_device *);
|
||||
const char *(*udev_device_get_subsystem)(struct udev_device *);
|
||||
struct udev_device *(*udev_device_get_parent_with_subsystem_devtype)(struct udev_device *udev_device, const char *subsystem, const char *devtype);
|
||||
const char *(*udev_device_get_property_value)(struct udev_device *, const char *);
|
||||
const char *(*udev_device_get_sysattr_value)(struct udev_device *udev_device, const char *sysattr);
|
||||
struct udev_device *(*udev_device_new_from_syspath)(struct udev *, const char *);
|
||||
void (*udev_device_unref)(struct udev_device *);
|
||||
int (*udev_enumerate_add_match_property)(struct udev_enumerate *, const char *, const char *);
|
||||
|
||||
+14
-5
@@ -18,13 +18,14 @@
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _directx_h
|
||||
#define _directx_h
|
||||
#ifndef _SDL_directx_h
|
||||
#define _SDL_directx_h
|
||||
|
||||
/* Include all of the DirectX 8.0 headers and adds any necessary tweaks */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "SDL_windows.h"
|
||||
#include <mmsystem.h>
|
||||
#ifndef WIN32
|
||||
#define WIN32
|
||||
@@ -91,12 +92,20 @@
|
||||
/* We need these defines to mark what version of DirectX API we use */
|
||||
#define DIRECTDRAW_VERSION 0x0700
|
||||
#define DIRECTSOUND_VERSION 0x0800
|
||||
#define DIRECTINPUT_VERSION 0x0500
|
||||
#define DIRECTINPUT_VERSION 0x0800 /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
|
||||
|
||||
#ifdef HAVE_DDRAW_H
|
||||
#include <ddraw.h>
|
||||
#endif
|
||||
#ifdef HAVE_DSOUND_H
|
||||
#include <dsound.h>
|
||||
#endif
|
||||
#ifdef HAVE_DINPUT_H
|
||||
#include <dinput.h>
|
||||
#else
|
||||
typedef struct { int unused; } DIDEVICEINSTANCE;
|
||||
#endif
|
||||
|
||||
#endif /* _directx_h */
|
||||
#endif /* _SDL_directx_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -28,6 +28,11 @@
|
||||
|
||||
#include <objbase.h> /* for CoInitialize/CoUninitialize (Win32 only) */
|
||||
|
||||
#ifndef _WIN32_WINNT_VISTA
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
#endif
|
||||
|
||||
|
||||
/* Sets an error message based on GetLastError() */
|
||||
int
|
||||
WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
|
||||
@@ -88,6 +93,37 @@ WIN_CoUninitialize(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __WINRT__
|
||||
static BOOL
|
||||
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||
{
|
||||
OSVERSIONINFOEXW osvi;
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
0, VER_MAJORVERSION, VER_GREATER_EQUAL ),
|
||||
VER_MINORVERSION, VER_GREATER_EQUAL ),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
|
||||
|
||||
SDL_zero(osvi);
|
||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||
osvi.dwMajorVersion = wMajorVersion;
|
||||
osvi.dwMinorVersion = wMinorVersion;
|
||||
osvi.wServicePackMajor = wServicePackMajor;
|
||||
|
||||
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL WIN_IsWindowsVistaOrGreater()
|
||||
{
|
||||
#ifdef __WINRT__
|
||||
return TRUE;
|
||||
#else
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __WIN32__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -56,6 +56,9 @@ extern int WIN_SetError(const char *prefix);
|
||||
extern HRESULT WIN_CoInitialize(void);
|
||||
extern void WIN_CoUninitialize(void);
|
||||
|
||||
/* Returns SDL_TRUE if we're running on Windows Vista and newer */
|
||||
extern BOOL WIN_IsWindowsVistaOrGreater();
|
||||
|
||||
#endif /* _INCLUDED_WINDOWS_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_assert.h"
|
||||
#include "SDL_xinput.h"
|
||||
|
||||
|
||||
#ifdef HAVE_XINPUT_H
|
||||
|
||||
XInputGetState_t SDL_XInputGetState = NULL;
|
||||
XInputSetState_t SDL_XInputSetState = NULL;
|
||||
XInputGetCapabilities_t SDL_XInputGetCapabilities = NULL;
|
||||
DWORD SDL_XInputVersion = 0;
|
||||
|
||||
static HANDLE s_pXInputDLL = 0;
|
||||
static int s_XInputDLLRefCount = 0;
|
||||
|
||||
|
||||
#ifdef __WINRT__
|
||||
|
||||
int
|
||||
WIN_LoadXInputDLL(void)
|
||||
{
|
||||
/* Getting handles to system dlls (via LoadLibrary and its variants) is not
|
||||
* supported on WinRT, thus, pointers to XInput's functions can't be
|
||||
* retrieved via GetProcAddress.
|
||||
*
|
||||
* When on WinRT, assume that XInput is already loaded, and directly map
|
||||
* its XInput.h-declared functions to the SDL_XInput* set of function
|
||||
* pointers.
|
||||
*
|
||||
* Side-note: XInputGetStateEx is not available for use in WinRT.
|
||||
* This seems to mean that support for the guide button is not available
|
||||
* in WinRT, unfortunately.
|
||||
*/
|
||||
SDL_XInputGetState = (XInputGetState_t)XInputGetState;
|
||||
SDL_XInputSetState = (XInputSetState_t)XInputSetState;
|
||||
SDL_XInputGetCapabilities = (XInputGetCapabilities_t)XInputGetCapabilities;
|
||||
|
||||
/* XInput 1.4 ships with Windows 8 and 8.1: */
|
||||
SDL_XInputVersion = (1 << 16) | 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WIN_UnloadXInputDLL(void)
|
||||
{
|
||||
}
|
||||
|
||||
#else /* !__WINRT__ */
|
||||
|
||||
int
|
||||
WIN_LoadXInputDLL(void)
|
||||
{
|
||||
DWORD version = 0;
|
||||
|
||||
if (s_pXInputDLL) {
|
||||
SDL_assert(s_XInputDLLRefCount > 0);
|
||||
s_XInputDLLRefCount++;
|
||||
return 0; /* already loaded */
|
||||
}
|
||||
|
||||
version = (1 << 16) | 4;
|
||||
s_pXInputDLL = LoadLibrary(L"XInput1_4.dll"); /* 1.4 Ships with Windows 8. */
|
||||
if (!s_pXInputDLL) {
|
||||
version = (1 << 16) | 3;
|
||||
s_pXInputDLL = LoadLibrary(L"XInput1_3.dll"); /* 1.3 Ships with Vista and Win7, can be installed as a redistributable component. */
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
s_pXInputDLL = LoadLibrary(L"bin\\XInput1_3.dll");
|
||||
}
|
||||
if (!s_pXInputDLL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_assert(s_XInputDLLRefCount == 0);
|
||||
SDL_XInputVersion = version;
|
||||
s_XInputDLLRefCount = 1;
|
||||
|
||||
/* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */
|
||||
SDL_XInputGetState = (XInputGetState_t)GetProcAddress((HMODULE)s_pXInputDLL, (LPCSTR)100);
|
||||
SDL_XInputSetState = (XInputSetState_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputSetState");
|
||||
SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress((HMODULE)s_pXInputDLL, "XInputGetCapabilities");
|
||||
if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) {
|
||||
WIN_UnloadXInputDLL();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WIN_UnloadXInputDLL(void)
|
||||
{
|
||||
if (s_pXInputDLL) {
|
||||
SDL_assert(s_XInputDLLRefCount > 0);
|
||||
if (--s_XInputDLLRefCount == 0) {
|
||||
FreeLibrary(s_pXInputDLL);
|
||||
s_pXInputDLL = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_assert(s_XInputDLLRefCount == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __WINRT__ */
|
||||
#endif /* HAVE_XINPUT_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
+44
-60
@@ -20,29 +20,13 @@
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_JOYSTICK_DINPUT_H
|
||||
#ifndef _SDL_xinput_h
|
||||
#define _SDL_xinput_h
|
||||
|
||||
/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
|
||||
* A. Formiga's WINMM driver.
|
||||
*
|
||||
* Hats and sliders are completely untested; the app I'm writing this for mostly
|
||||
* doesn't use them and I don't own any joysticks with them.
|
||||
*
|
||||
* We don't bother to use event notification here. It doesn't seem to work
|
||||
* with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and
|
||||
* let it return 0 events. */
|
||||
#ifdef HAVE_XINPUT_H
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0800 /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */
|
||||
#include <dinput.h>
|
||||
#define COBJMACROS
|
||||
#include <wbemcli.h>
|
||||
#include <oleauto.h>
|
||||
#include "SDL_windows.h"
|
||||
#include <xinput.h>
|
||||
#include <devguid.h>
|
||||
#include <dbt.h>
|
||||
|
||||
|
||||
#ifndef XUSER_MAX_COUNT
|
||||
#define XUSER_MAX_COUNT 4
|
||||
@@ -54,6 +38,43 @@
|
||||
#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
|
||||
#endif
|
||||
|
||||
#ifndef XINPUT_DEVSUBTYPE_UNKNOWN
|
||||
#define XINPUT_DEVSUBTYPE_UNKNOWN 0x00
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_GAMEPAD
|
||||
#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_WHEEL
|
||||
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
|
||||
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
|
||||
#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
|
||||
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_GUITAR
|
||||
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE
|
||||
#define XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE 0x07
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
|
||||
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_GUITAR_BASS
|
||||
#define XINPUT_DEVSUBTYPE_GUITAR_BASS 0x0B
|
||||
#endif
|
||||
#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
|
||||
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
|
||||
#endif
|
||||
|
||||
#ifndef XINPUT_GAMEPAD_GUIDE
|
||||
#define XINPUT_GAMEPAD_GUIDE 0x0400
|
||||
#endif
|
||||
|
||||
/* typedef's for XInput structs we use */
|
||||
typedef struct
|
||||
@@ -105,46 +126,9 @@ extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
|
||||
#define XINPUTGETSTATE SDL_XInputGetState
|
||||
#define XINPUTSETSTATE SDL_XInputSetState
|
||||
#define XINPUTGETCAPABILITIES SDL_XInputGetCapabilities
|
||||
#define INVALID_XINPUT_USERID XUSER_INDEX_ANY
|
||||
#define SDL_XINPUT_MAX_DEVICES XUSER_MAX_COUNT
|
||||
|
||||
#define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */
|
||||
#endif /* HAVE_XINPUT_H */
|
||||
|
||||
#endif /* _SDL_xinput_h */
|
||||
|
||||
/* local types */
|
||||
typedef enum Type
|
||||
{ BUTTON, AXIS, HAT } Type;
|
||||
|
||||
typedef struct input_t
|
||||
{
|
||||
/* DirectInput offset for this input type: */
|
||||
DWORD ofs;
|
||||
|
||||
/* Button, axis or hat: */
|
||||
Type type;
|
||||
|
||||
/* SDL input offset: */
|
||||
Uint8 num;
|
||||
} input_t;
|
||||
|
||||
/* The private structure used to keep track of a joystick */
|
||||
struct joystick_hwdata
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 InputDevice;
|
||||
DIDEVCAPS Capabilities;
|
||||
int buffered;
|
||||
SDL_JoystickGUID guid;
|
||||
|
||||
input_t Inputs[MAX_INPUTS];
|
||||
int NumInputs;
|
||||
int NumSliders;
|
||||
Uint8 removed;
|
||||
Uint8 send_remove_event;
|
||||
Uint8 bXInputDevice; /* 1 if this device supports using the xinput API rather than DirectInput */
|
||||
Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
|
||||
Uint8 userid; /* XInput userid index for this joystick */
|
||||
Uint8 currentXInputSlot; /* the current position to write to in XInputState below, used so we can compare old and new values */
|
||||
XINPUT_STATE_EX XInputState[2];
|
||||
};
|
||||
|
||||
#endif /* SDL_JOYSTICK_DINPUT_H */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -70,6 +70,13 @@ extern "C" {
|
||||
#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.
|
||||
@@ -119,6 +126,16 @@ static void WINRT_SetDisplayOrientationsPreference(void *userdata, const char *n
|
||||
{
|
||||
SDL_assert(SDL_strcmp(name, SDL_HINT_ORIENTATIONS) == 0);
|
||||
|
||||
/* HACK: prevent SDL from altering an app's .appxmanifest-set orientation
|
||||
* from being changed on startup, by detecting when SDL_HINT_ORIENTATIONS
|
||||
* is getting registered.
|
||||
*
|
||||
* TODO, WinRT: consider reading in an app's .appxmanifest file, and apply its orientation when 'newValue == NULL'.
|
||||
*/
|
||||
if ((oldValue == NULL) && (newValue == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start with no orientation flags, then add each in as they're parsed
|
||||
// from newValue.
|
||||
unsigned int orientationFlags = 0;
|
||||
@@ -163,16 +180,14 @@ static void WINRT_SetDisplayOrientationsPreference(void *userdata, const char *n
|
||||
// for details. Microsoft's "Display orientation sample" also gives an
|
||||
// outline of how Windows treats device rotation
|
||||
// (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
|
||||
#if NTDDI_VERSION > NTDDI_WIN8
|
||||
DisplayInformation::AutoRotationPreferences = (DisplayOrientations) orientationFlags;
|
||||
#else
|
||||
DisplayProperties::AutoRotationPreferences = (DisplayOrientations) orientationFlags;
|
||||
#endif
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences) = (DisplayOrientations) orientationFlags;
|
||||
}
|
||||
|
||||
static void
|
||||
WINRT_ProcessWindowSizeChange()
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
// Make the new window size be the one true fullscreen mode.
|
||||
// This change was initially done, in part, to allow the Direct3D 11.1
|
||||
// renderer to receive window-resize events as a device rotates.
|
||||
@@ -192,64 +207,58 @@ WINRT_ProcessWindowSizeChange()
|
||||
// Make note of the old display mode, and it's old driverdata.
|
||||
SDL_DisplayMode oldDisplayMode;
|
||||
SDL_zero(oldDisplayMode);
|
||||
if (WINRT_GlobalSDLVideoDevice) {
|
||||
oldDisplayMode = WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode;
|
||||
if (_this) {
|
||||
oldDisplayMode = _this->displays[0].desktop_mode;
|
||||
}
|
||||
|
||||
// Setup the new display mode in the appropriate spots.
|
||||
if (WINRT_GlobalSDLVideoDevice) {
|
||||
if (_this) {
|
||||
// Make a full copy of the display mode for display_modes[0],
|
||||
// one with with a separately malloced 'driverdata' field.
|
||||
// SDL_VideoQuit(), if called, will attempt to free the driverdata
|
||||
// fields in 'desktop_mode' and each entry in the 'display_modes'
|
||||
// array.
|
||||
if (WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0].driverdata) {
|
||||
if (_this->displays[0].display_modes[0].driverdata) {
|
||||
// Free the previous mode's memory
|
||||
SDL_free(WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0].driverdata);
|
||||
WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0].driverdata = NULL;
|
||||
SDL_free(_this->displays[0].display_modes[0].driverdata);
|
||||
_this->displays[0].display_modes[0].driverdata = NULL;
|
||||
}
|
||||
if (WINRT_DuplicateDisplayMode(&(WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0]), &newDisplayMode) != 0) {
|
||||
if (WINRT_DuplicateDisplayMode(&(_this->displays[0].display_modes[0]), &newDisplayMode) != 0) {
|
||||
// Uh oh, something went wrong. A malloc call probably failed.
|
||||
SDL_free(newDisplayMode.driverdata);
|
||||
return;
|
||||
}
|
||||
|
||||
// Install 'newDisplayMode' into 'current_mode' and 'desktop_mode'.
|
||||
WINRT_GlobalSDLVideoDevice->displays[0].current_mode = newDisplayMode;
|
||||
WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode = newDisplayMode;
|
||||
_this->displays[0].current_mode = newDisplayMode;
|
||||
_this->displays[0].desktop_mode = newDisplayMode;
|
||||
}
|
||||
|
||||
if (WINRT_GlobalSDLWindow) {
|
||||
// Send a window-resize event to the rest of SDL, and to apps:
|
||||
SDL_SendWindowEvent(
|
||||
WINRT_GlobalSDLWindow,
|
||||
SDL_WINDOWEVENT_RESIZED,
|
||||
newDisplayMode.w,
|
||||
newDisplayMode.h);
|
||||
|
||||
// If the window size changed, send a resize event to SDL and its host app:
|
||||
int window_w = 0;
|
||||
int window_h = 0;
|
||||
SDL_GetWindowSize(WINRT_GlobalSDLWindow, &window_w, &window_h);
|
||||
if ((window_w != newDisplayMode.w) || (window_h != newDisplayMode.h)) {
|
||||
SDL_SendWindowEvent(
|
||||
WINRT_GlobalSDLWindow,
|
||||
SDL_WINDOWEVENT_RESIZED,
|
||||
newDisplayMode.w,
|
||||
newDisplayMode.h);
|
||||
} else {
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
// HACK: On Windows Phone, make sure that orientation changes from
|
||||
// Landscape to LandscapeFlipped, Portrait to PortraitFlipped,
|
||||
// or vice-versa on either of those two, lead to the Direct3D renderer
|
||||
// getting updated.
|
||||
const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
|
||||
const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)newDisplayMode.driverdata)->currentOrientation;
|
||||
|
||||
if ((oldOrientation == DisplayOrientations::Landscape && newOrientation == DisplayOrientations::LandscapeFlipped) ||
|
||||
(oldOrientation == DisplayOrientations::LandscapeFlipped && newOrientation == DisplayOrientations::Landscape) ||
|
||||
(oldOrientation == DisplayOrientations::Portrait && newOrientation == DisplayOrientations::PortraitFlipped) ||
|
||||
(oldOrientation == DisplayOrientations::PortraitFlipped && newOrientation == DisplayOrientations::Portrait))
|
||||
{
|
||||
// One of the reasons this event is getting sent out is because SDL
|
||||
// will ignore requests to send out SDL_WINDOWEVENT_RESIZED events
|
||||
// if and when the event size doesn't change (and the Direct3D 11.1
|
||||
// renderer doesn't get the memo).
|
||||
// HACK: Make sure that orientation changes
|
||||
// lead to the Direct3D renderer's viewport getting updated:
|
||||
//
|
||||
// Make sure that the display/window size really didn't change. If
|
||||
// it did, then a SDL_WINDOWEVENT_SIZE_CHANGED event got sent, and
|
||||
// the Direct3D 11.1 renderer picked it up, presumably.
|
||||
if (oldDisplayMode.w == newDisplayMode.w &&
|
||||
oldDisplayMode.h == newDisplayMode.h)
|
||||
// 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
|
||||
const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
|
||||
const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)newDisplayMode.driverdata)->currentOrientation;
|
||||
if (oldOrientation != newOrientation)
|
||||
{
|
||||
SDL_SendWindowEvent(
|
||||
WINRT_GlobalSDLWindow,
|
||||
@@ -257,8 +266,8 @@ WINRT_ProcessWindowSizeChange()
|
||||
newDisplayMode.w,
|
||||
newDisplayMode.h);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, free the 'driverdata' field of the old 'desktop_mode'.
|
||||
@@ -300,26 +309,21 @@ void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
|
||||
if (window) {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Size={%f,%f}\n",
|
||||
__FUNCTION__,
|
||||
(int)DisplayProperties::CurrentOrientation,
|
||||
(int)DisplayProperties::NativeOrientation,
|
||||
(int)DisplayProperties::AutoRotationPreferences,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
} else {
|
||||
SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
|
||||
__FUNCTION__,
|
||||
(int)DisplayProperties::CurrentOrientation,
|
||||
(int)DisplayProperties::NativeOrientation,
|
||||
(int)DisplayProperties::AutoRotationPreferences);
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
// On Windows Phone, treat an orientation change as a change in window size.
|
||||
// The native window's size doesn't seem to change, however SDL will simulate
|
||||
// a window size change.
|
||||
WINRT_ProcessWindowSizeChange();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
@@ -327,9 +331,9 @@ 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 Size={%f,%f}\n",
|
||||
__FUNCTION__,
|
||||
(int)DisplayProperties::CurrentOrientation,
|
||||
(int)DisplayProperties::NativeOrientation,
|
||||
(int)DisplayProperties::AutoRotationPreferences,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
window->Bounds.Width,
|
||||
window->Bounds.Height);
|
||||
#endif
|
||||
@@ -371,6 +375,9 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
|
||||
window->KeyUp +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyUp);
|
||||
|
||||
window->CharacterReceived +=
|
||||
ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &SDL_WinRTApp::OnCharacterReceived);
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
HardwareButtons::BackPressed +=
|
||||
ref new EventHandler<BackPressedEventArgs^>(this, &SDL_WinRTApp::OnBackButtonPressed);
|
||||
@@ -416,16 +423,62 @@ void SDL_WinRTApp::Run()
|
||||
}
|
||||
}
|
||||
|
||||
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 (m_windowVisible)
|
||||
{
|
||||
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
|
||||
{
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@@ -485,9 +538,9 @@ void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEven
|
||||
SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
|
||||
__FUNCTION__,
|
||||
args->Size.Width, args->Size.Height,
|
||||
(int)DisplayProperties::CurrentOrientation,
|
||||
(int)DisplayProperties::NativeOrientation,
|
||||
(int)DisplayProperties::AutoRotationPreferences,
|
||||
WINRT_DISPLAY_PROPERTY(CurrentOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(NativeOrientation),
|
||||
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
|
||||
(WINRT_GlobalSDLWindow ? "yes" : "no"));
|
||||
#endif
|
||||
|
||||
@@ -509,8 +562,12 @@ void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEven
|
||||
|
||||
if (args->Visible) {
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_SHOWN, 0, 0);
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
|
||||
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
|
||||
@@ -536,80 +593,57 @@ void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedE
|
||||
CoreWindow::GetForCurrentThread()->Activate();
|
||||
}
|
||||
|
||||
static int SDLCALL RemoveAppSuspendAndResumeEvents(void * userdata, SDL_Event * event)
|
||||
{
|
||||
if (event->type == SDL_WINDOWEVENT)
|
||||
{
|
||||
switch (event->window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
// Return 0 to indicate that the event should be removed from the
|
||||
// event queue:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return 1 to indicate that the event should stay in the event queue:
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 a window-minimized event immediately to observers.
|
||||
// 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.
|
||||
//
|
||||
// In order to prevent app-suspend events from being received twice:
|
||||
// first via a callback passed to SDL_AddEventWatch, and second via
|
||||
// SDL's event queue, the event will be sent to SDL, then immediately
|
||||
// removed from the queue.
|
||||
if (WINRT_GlobalSDLWindow)
|
||||
{
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_MINIMIZED, 0, 0); // TODO: see if SDL_WINDOWEVENT_SIZE_CHANGED should be getting triggered here (it is, currently)
|
||||
SDL_FilterEvents(RemoveAppSuspendAndResumeEvents, 0);
|
||||
}
|
||||
|
||||
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
|
||||
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);
|
||||
|
||||
// Restore any data or state that was unloaded on suspend. By default, data
|
||||
// and state are persisted when resuming from suspend. Note that this event
|
||||
// does not occur if the app was previously terminated.
|
||||
if (WINRT_GlobalSDLWindow)
|
||||
{
|
||||
SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_WINDOWEVENT_RESTORED, 0, 0); // TODO: see if SDL_WINDOWEVENT_SIZE_CHANGED should be getting triggered here (it is, currently)
|
||||
|
||||
// Remove the app-resume event from the queue, as is done with the
|
||||
// app-suspend event.
|
||||
//
|
||||
// TODO, WinRT: consider posting this event to the queue even though
|
||||
// its counterpart, the app-suspend event, effectively has to be
|
||||
// processed immediately.
|
||||
SDL_FilterEvents(RemoveAppSuspendAndResumeEvents, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnExiting(Platform::Object^ sender, Platform::Object^ args)
|
||||
@@ -682,6 +716,11 @@ void SDL_WinRTApp::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::C
|
||||
WINRT_ProcessKeyUpEvent(args);
|
||||
}
|
||||
|
||||
void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args)
|
||||
{
|
||||
WINRT_ProcessCharacterReceivedEvent(args);
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
void SDL_WinRTApp::OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args)
|
||||
{
|
||||
|
||||
@@ -39,6 +39,8 @@ internal:
|
||||
void PumpEvents();
|
||||
|
||||
protected:
|
||||
bool ShouldWaitForAppResumeEvents();
|
||||
|
||||
// Event Handlers.
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_APP // for Windows 8/8.1/RT apps... (and not Phone apps)
|
||||
@@ -67,6 +69,7 @@ protected:
|
||||
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 WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
void OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#ifndef _SDL_winrtapp_xaml_h
|
||||
#define _SDL_winrtapp_xaml_h
|
||||
|
||||
#include "SDL_types.h"
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern SDL_bool WINRT_XAMLWasEnabled;
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#define CPU_HAS_SSE41 0x00000100
|
||||
#define CPU_HAS_SSE42 0x00000200
|
||||
#define CPU_HAS_AVX 0x00000400
|
||||
#define CPU_HAS_AVX2 0x00000800
|
||||
|
||||
#if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__
|
||||
/* This is the brute force way of detecting instruction sets...
|
||||
@@ -73,11 +74,12 @@ illegal_instruction(int sig)
|
||||
}
|
||||
#endif /* HAVE_SETJMP */
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveCPUID(void)
|
||||
{
|
||||
int has_CPUID = 0;
|
||||
/* *INDENT-OFF* */
|
||||
#ifndef SDL_CPUINFO_DISABLED
|
||||
#if defined(__GNUC__) && defined(i386)
|
||||
__asm__ (
|
||||
" pushfl # Get original EFLAGS \n"
|
||||
@@ -164,6 +166,7 @@ done:
|
||||
"1: \n"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
return has_CPUID;
|
||||
}
|
||||
@@ -172,6 +175,7 @@ done:
|
||||
#define cpuid(func, a, b, c, d) \
|
||||
__asm__ __volatile__ ( \
|
||||
" pushl %%ebx \n" \
|
||||
" xorl %%ecx,%%ecx \n" \
|
||||
" cpuid \n" \
|
||||
" movl %%ebx, %%esi \n" \
|
||||
" popl %%ebx \n" : \
|
||||
@@ -180,6 +184,7 @@ done:
|
||||
#define cpuid(func, a, b, c, d) \
|
||||
__asm__ __volatile__ ( \
|
||||
" pushq %%rbx \n" \
|
||||
" xorq %%rcx,%%rcx \n" \
|
||||
" cpuid \n" \
|
||||
" movq %%rbx, %%rsi \n" \
|
||||
" popq %%rbx \n" : \
|
||||
@@ -188,6 +193,7 @@ done:
|
||||
#define cpuid(func, a, b, c, d) \
|
||||
__asm { \
|
||||
__asm mov eax, func \
|
||||
__asm xor ecx, ecx \
|
||||
__asm cpuid \
|
||||
__asm mov a, eax \
|
||||
__asm mov b, ebx \
|
||||
@@ -209,7 +215,7 @@ done:
|
||||
a = b = c = d = 0
|
||||
#endif
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_getCPUIDFeatures(void)
|
||||
{
|
||||
int features = 0;
|
||||
@@ -223,7 +229,39 @@ CPU_getCPUIDFeatures(void)
|
||||
return features;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static SDL_bool
|
||||
CPU_OSSavesYMM(void)
|
||||
{
|
||||
int a, b, c, d;
|
||||
|
||||
/* Check to make sure we can call xgetbv */
|
||||
cpuid(0, a, b, c, d);
|
||||
if (a < 1) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
cpuid(1, a, b, c, d);
|
||||
if (!(c & 0x08000000)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Call xgetbv to see if YMM register state is saved */
|
||||
a = 0;
|
||||
#if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))
|
||||
asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx");
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */
|
||||
a = (int)_xgetbv(0);
|
||||
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
|
||||
__asm
|
||||
{
|
||||
xor ecx, ecx
|
||||
_asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
|
||||
mov a, eax
|
||||
}
|
||||
#endif
|
||||
return ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
CPU_haveRDTSC(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
@@ -232,10 +270,11 @@ CPU_haveRDTSC(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveAltiVec(void)
|
||||
{
|
||||
volatile int altivec = 0;
|
||||
#ifndef SDL_CPUINFO_DISABLED
|
||||
#if (defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__))
|
||||
#ifdef __OpenBSD__
|
||||
int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC };
|
||||
@@ -255,11 +294,12 @@ CPU_haveAltiVec(void)
|
||||
altivec = 1;
|
||||
}
|
||||
signal(SIGILL, handler);
|
||||
#endif
|
||||
#endif
|
||||
return altivec;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveMMX(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
@@ -268,7 +308,7 @@ CPU_haveMMX(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_have3DNow(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
@@ -283,7 +323,7 @@ CPU_have3DNow(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveSSE(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
@@ -292,7 +332,7 @@ CPU_haveSSE(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveSSE2(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
@@ -301,7 +341,7 @@ CPU_haveSSE2(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveSSE3(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
@@ -316,13 +356,13 @@ CPU_haveSSE3(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveSSE41(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(1, a, b, c, d);
|
||||
cpuid(0, a, b, c, d);
|
||||
if (a >= 1) {
|
||||
cpuid(1, a, b, c, d);
|
||||
return (c & 0x00080000);
|
||||
@@ -331,13 +371,13 @@ CPU_haveSSE41(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveSSE42(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(1, a, b, c, d);
|
||||
cpuid(0, a, b, c, d);
|
||||
if (a >= 1) {
|
||||
cpuid(1, a, b, c, d);
|
||||
return (c & 0x00100000);
|
||||
@@ -346,13 +386,13 @@ CPU_haveSSE42(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_INLINE int
|
||||
static int
|
||||
CPU_haveAVX(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(1, a, b, c, d);
|
||||
cpuid(0, a, b, c, d);
|
||||
if (a >= 1) {
|
||||
cpuid(1, a, b, c, d);
|
||||
return (c & 0x10000000);
|
||||
@@ -361,12 +401,28 @@ CPU_haveAVX(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
CPU_haveAVX2(void)
|
||||
{
|
||||
if (CPU_haveCPUID() && CPU_OSSavesYMM()) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(0, a, b, c, d);
|
||||
if (a >= 7) {
|
||||
cpuid(7, a, b, c, d);
|
||||
return (b & 0x00000020);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SDL_CPUCount = 0;
|
||||
|
||||
int
|
||||
SDL_GetCPUCount(void)
|
||||
{
|
||||
if (!SDL_CPUCount) {
|
||||
#ifndef SDL_CPUINFO_DISABLED
|
||||
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
|
||||
if (SDL_CPUCount <= 0) {
|
||||
SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||
@@ -384,6 +440,7 @@ SDL_GetCPUCount(void)
|
||||
GetSystemInfo(&info);
|
||||
SDL_CPUCount = info.dwNumberOfProcessors;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* There has to be at least 1, right? :) */
|
||||
if (SDL_CPUCount <= 0) {
|
||||
@@ -401,22 +458,25 @@ SDL_GetCPUType(void)
|
||||
|
||||
if (!SDL_CPUType[0]) {
|
||||
int i = 0;
|
||||
int a, b, c, d;
|
||||
|
||||
if (CPU_haveCPUID()) {
|
||||
int a, b, c, d;
|
||||
cpuid(0x00000000, a, b, c, d);
|
||||
(void) a;
|
||||
SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUType[i++] = (char)(b & 0xff);
|
||||
|
||||
SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUType[i++] = (char)(d & 0xff);
|
||||
|
||||
SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUType[i++] = (char)(c & 0xff);
|
||||
}
|
||||
if (!SDL_CPUType[0]) {
|
||||
SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
|
||||
@@ -504,15 +564,12 @@ int
|
||||
SDL_GetCPUCacheLineSize(void)
|
||||
{
|
||||
const char *cpuType = SDL_GetCPUType();
|
||||
|
||||
int a, b, c, d;
|
||||
(void) a; (void) b; (void) c; (void) d;
|
||||
if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(0x00000001, a, b, c, d);
|
||||
return (((b >> 8) & 0xff) * 8);
|
||||
} else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(0x80000005, a, b, c, d);
|
||||
return (c & 0xff);
|
||||
} else {
|
||||
@@ -558,6 +615,9 @@ SDL_GetCPUFeatures(void)
|
||||
if (CPU_haveAVX()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_AVX;
|
||||
}
|
||||
if (CPU_haveAVX2()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_AVX2;
|
||||
}
|
||||
}
|
||||
return SDL_CPUFeatures;
|
||||
}
|
||||
@@ -652,12 +712,22 @@ SDL_HasAVX(void)
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasAVX2(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_AVX2) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static int SDL_SystemRAM = 0;
|
||||
|
||||
int
|
||||
SDL_GetSystemRAM(void)
|
||||
{
|
||||
if (!SDL_SystemRAM) {
|
||||
#ifndef SDL_CPUINFO_DISABLED
|
||||
#if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
|
||||
if (SDL_SystemRAM <= 0) {
|
||||
SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
|
||||
@@ -691,6 +761,7 @@ SDL_GetSystemRAM(void)
|
||||
SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return SDL_SystemRAM;
|
||||
@@ -718,6 +789,7 @@ main()
|
||||
printf("SSE4.1: %d\n", SDL_HasSSE41());
|
||||
printf("SSE4.2: %d\n", SDL_HasSSE42());
|
||||
printf("AVX: %d\n", SDL_HasAVX());
|
||||
printf("AVX2: %d\n", SDL_HasAVX2());
|
||||
printf("RAM: %d MB\n", SDL_GetSystemRAM());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -56,38 +56,38 @@ static void SDL_InitDynamicAPI(void);
|
||||
#if DISABLE_JUMP_MAGIC
|
||||
/* Can't use the macro for varargs nonsense. This is atrocious. */
|
||||
#define SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, logname, prio) \
|
||||
_static void SDL_Log##logname##name(int category, const char *fmt, ...) { \
|
||||
_static void SDL_Log##logname##name(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { \
|
||||
va_list ap; initcall; va_start(ap, fmt); \
|
||||
jump_table.SDL_LogMessageV(category, SDL_LOG_PRIORITY_##prio, fmt, ap); \
|
||||
va_end(ap); \
|
||||
}
|
||||
|
||||
#define SDL_DYNAPI_VARARGS(_static, name, initcall) \
|
||||
_static int SDL_SetError##name(const char *fmt, ...) { \
|
||||
_static int SDL_SetError##name(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { \
|
||||
char buf[512]; /* !!! FIXME: dynamic allocation */ \
|
||||
va_list ap; initcall; va_start(ap, fmt); \
|
||||
jump_table.SDL_vsnprintf(buf, sizeof (buf), fmt, ap); \
|
||||
va_end(ap); \
|
||||
return jump_table.SDL_SetError("%s", buf); \
|
||||
} \
|
||||
_static int SDL_sscanf##name(const char *buf, const char *fmt, ...) { \
|
||||
_static int SDL_sscanf##name(const char *buf, SDL_SCANF_FORMAT_STRING const char *fmt, ...) { \
|
||||
int retval; va_list ap; initcall; va_start(ap, fmt); \
|
||||
retval = jump_table.SDL_vsscanf(buf, fmt, ap); \
|
||||
va_end(ap); \
|
||||
return retval; \
|
||||
} \
|
||||
_static int SDL_snprintf##name(char *buf, size_t buflen, const char *fmt, ...) { \
|
||||
_static int SDL_snprintf##name(SDL_OUT_Z_CAP(maxlen) char *buf, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { \
|
||||
int retval; va_list ap; initcall; va_start(ap, fmt); \
|
||||
retval = jump_table.SDL_vsnprintf(buf, buflen, fmt, ap); \
|
||||
retval = jump_table.SDL_vsnprintf(buf, maxlen, fmt, ap); \
|
||||
va_end(ap); \
|
||||
return retval; \
|
||||
} \
|
||||
_static void SDL_Log##name(const char *fmt, ...) { \
|
||||
_static void SDL_Log##name(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { \
|
||||
va_list ap; initcall; va_start(ap, fmt); \
|
||||
jump_table.SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap); \
|
||||
va_end(ap); \
|
||||
} \
|
||||
_static void SDL_LogMessage##name(int category, SDL_LogPriority priority, const char *fmt, ...) { \
|
||||
_static void SDL_LogMessage##name(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { \
|
||||
va_list ap; initcall; va_start(ap, fmt); \
|
||||
jump_table.SDL_LogMessageV(category, priority, fmt, ap); \
|
||||
va_end(ap); \
|
||||
@@ -206,7 +206,14 @@ SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize)
|
||||
static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
|
||||
{
|
||||
HANDLE lib = LoadLibraryA(fname);
|
||||
return lib ? GetProcAddress(lib, sym) : NULL;
|
||||
void *retval = NULL;
|
||||
if (lib) {
|
||||
retval = GetProcAddress(lib, sym);
|
||||
if (retval == NULL) {
|
||||
FreeLibrary(lib);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
@@ -215,8 +222,11 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
|
||||
{
|
||||
image_id lib = load_add_on(fname);
|
||||
void *retval = NULL;
|
||||
if ((lib < 0) || (get_image_symbol(lib, sym, B_SYMBOL_TYPE_TEXT, &retval) != B_NO_ERROR)) {
|
||||
retval = NULL;
|
||||
if (lib >= 0) {
|
||||
if (get_image_symbol(lib, sym, B_SYMBOL_TYPE_TEXT, &retval) != B_NO_ERROR) {
|
||||
unload_add_on(lib);
|
||||
retval = NULL;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@@ -225,7 +235,14 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
|
||||
static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
|
||||
{
|
||||
void *lib = dlopen(fname, RTLD_NOW | RTLD_LOCAL);
|
||||
return lib ? dlsym(lib, sym) : NULL;
|
||||
void *retval = NULL;
|
||||
if (lib != NULL) {
|
||||
retval = dlsym(lib, sym);
|
||||
if (retval == NULL) {
|
||||
dlclose(lib);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
#else
|
||||
#error Please define your platform.
|
||||
|
||||
@@ -43,10 +43,12 @@
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_IPHONE /* probably not useful on iOS. */
|
||||
#if TARGET_OS_IPHONE || __native_client__ || __EMSCRIPTEN__ /* probably not useful on iOS, NACL or Emscripten. */
|
||||
#define SDL_DYNAMIC_API 0
|
||||
#elif SDL_BUILDING_WINRT /* probaly not useful on WinRT, given current .dll loading restrictions */
|
||||
#define SDL_DYNAMIC_API 0
|
||||
#elif defined(__clang_analyzer__)
|
||||
#define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */
|
||||
#else /* everyone else. */
|
||||
#define SDL_DYNAMIC_API 1
|
||||
#endif
|
||||
|
||||
@@ -575,3 +575,19 @@
|
||||
#define SDL_GetDefaultAssertionHandler SDL_GetDefaultAssertionHandler_REAL
|
||||
#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_WinRTRunApp SDL_WinRTRunApp_REAL
|
||||
#define SDL_sqrtf SDL_sqrtf_REAL
|
||||
#define SDL_tan SDL_tan_REAL
|
||||
#define SDL_tanf SDL_tanf_REAL
|
||||
#define SDL_CaptureMouse SDL_CaptureMouse_REAL
|
||||
#define SDL_SetWindowHitTest SDL_SetWindowHitTest_REAL
|
||||
#define SDL_GetGlobalMouseState SDL_GetGlobalMouseState_REAL
|
||||
#define SDL_HasAVX2 SDL_HasAVX2_REAL
|
||||
#define SDL_QueueAudio SDL_QueueAudio_REAL
|
||||
#define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL
|
||||
#define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL
|
||||
|
||||
@@ -31,17 +31,17 @@
|
||||
|
||||
/* direct jump magic can use these, the rest needs special code. */
|
||||
#if !SDL_DYNAPI_PROC_NO_VARARGS
|
||||
SDL_DYNAPI_PROC(int,SDL_SetError,(const char *a, ...),(a),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_Log,(const char *a, ...),(a),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogVerbose,(int a, const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogDebug,(int a, const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogInfo,(int a, const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogWarn,(int a, const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogError,(int a, const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogCritical,(int a, const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogMessage,(int a, SDL_LogPriority b, const char *c, ...),(a,b,c),)
|
||||
SDL_DYNAPI_PROC(int,SDL_sscanf,(const char *a, const char *b, ...),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_snprintf,(char *a, size_t b, const char *c, ...),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetError,(SDL_PRINTF_FORMAT_STRING const char *a, ...),(a),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_Log,(SDL_PRINTF_FORMAT_STRING const char *a, ...),(a),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogVerbose,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogDebug,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogInfo,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogWarn,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogError,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogCritical,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
|
||||
SDL_DYNAPI_PROC(void,SDL_LogMessage,(int a, SDL_LogPriority b, SDL_PRINTF_FORMAT_STRING const char *c, ...),(a,b,c),)
|
||||
SDL_DYNAPI_PROC(int,SDL_sscanf,(const char *a, SDL_SCANF_FORMAT_STRING const char *b, ...),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_snprintf,(SDL_OUT_Z_CAP(b) char *a, size_t b, SDL_PRINTF_FORMAT_STRING const char *c, ...),(a,b,c),return)
|
||||
#endif
|
||||
|
||||
#ifdef SDL_CreateThread
|
||||
@@ -418,17 +418,17 @@ SDL_DYNAPI_PROC(int,SDL_isdigit,(int a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_isspace,(int a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_toupper,(int a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_tolower,(int a),(a),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_memset,(void *a, int b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_memcpy,(void *a, const void *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_memmove,(void *a, const void *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_memset,(SDL_OUT_BYTECAP(c) void *a, int b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_memcpy,(SDL_OUT_BYTECAP(c) void *a, SDL_IN_BYTECAP(c) const void *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_memmove,(SDL_OUT_BYTECAP(c) void *a, SDL_IN_BYTECAP(c) const void *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_memcmp,(const void *a, const void *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_wcslen,(const wchar_t *a),(a),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_wcslcpy,(wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_wcslcat,(wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_wcslcpy,(SDL_OUT_Z_CAP(c) wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_wcslcat,(SDL_INOUT_Z_CAP(c) wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_strlen,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_strlcpy,(char *a, const char *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_utf8strlcpy,(char *a, const char *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_strlcat,(char *a, const char *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_strlcpy,(SDL_OUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_utf8strlcpy,(SDL_OUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(size_t,SDL_strlcat,(SDL_INOUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(char*,SDL_strdup,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(char*,SDL_strrev,(char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(char*,SDL_strupr,(char *a),(a),return)
|
||||
@@ -453,7 +453,7 @@ SDL_DYNAPI_PROC(int,SDL_strcmp,(const char *a, const char *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_strncmp,(const char *a, const char *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_strcasecmp,(const char *a, const char *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_strncasecmp,(const char *a, const char *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_vsnprintf,(char *a, size_t b, const char *c, va_list d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_vsnprintf,(SDL_OUT_Z_CAP(b) char *a, size_t b, const char *c, va_list d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(double,SDL_acos,(double a),(a),return)
|
||||
SDL_DYNAPI_PROC(double,SDL_asin,(double a),(a),return)
|
||||
SDL_DYNAPI_PROC(double,SDL_atan,(double a),(a),return)
|
||||
@@ -604,5 +604,22 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX,(void),(),return)
|
||||
SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetDefaultAssertionHandler,(void),(),return)
|
||||
SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),return)
|
||||
#ifdef __WIN32__
|
||||
SDL_DYNAPI_PROC(void,SDL_DXGIGetOutputInfo,(int a,int *b, int *c),(a,b,c),)
|
||||
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(void,SDL_WarpMouseGlobal,(int a, int b),(a,b),)
|
||||
SDL_DYNAPI_PROC(float,SDL_sqrtf,(float a),(a),return)
|
||||
SDL_DYNAPI_PROC(double,SDL_tan,(double a),(a),return)
|
||||
SDL_DYNAPI_PROC(float,SDL_tanf,(float a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetWindowHitTest,(SDL_Window *a, SDL_HitTest b, void *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(Uint32,SDL_GetGlobalMouseState,(int *a, int *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX2,(void),(),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),)
|
||||
|
||||
@@ -83,19 +83,6 @@ static struct
|
||||
} SDL_EventQ = { NULL, SDL_TRUE };
|
||||
|
||||
|
||||
static SDL_INLINE SDL_bool
|
||||
SDL_ShouldPollJoystick()
|
||||
{
|
||||
#if !SDL_JOYSTICK_DISABLED
|
||||
if ((!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] ||
|
||||
SDL_JoystickEventState(SDL_QUERY)) &&
|
||||
SDL_PrivateJoystickNeedsPolling()) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Public functions */
|
||||
|
||||
void
|
||||
@@ -315,7 +302,6 @@ SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
|
||||
For now we'll guarantee it's valid at least until
|
||||
the next call to SDL_PeepEvents()
|
||||
*/
|
||||
SDL_SysWMEntry *wmmsg;
|
||||
if (SDL_EventQ.wmmsg_free) {
|
||||
wmmsg = SDL_EventQ.wmmsg_free;
|
||||
SDL_EventQ.wmmsg_free = wmmsg->next;
|
||||
@@ -403,7 +389,7 @@ SDL_PumpEvents(void)
|
||||
}
|
||||
#if !SDL_JOYSTICK_DISABLED
|
||||
/* Check for joystick state change */
|
||||
if (SDL_ShouldPollJoystick()) {
|
||||
if ((!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY))) {
|
||||
SDL_JoystickUpdate();
|
||||
}
|
||||
#endif
|
||||
@@ -550,7 +536,7 @@ SDL_DelEventWatch(SDL_EventFilter filter, void *userdata)
|
||||
void
|
||||
SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
if (SDL_LockMutex(SDL_EventQ.lock) == 0) {
|
||||
if (SDL_EventQ.lock && SDL_LockMutex(SDL_EventQ.lock) == 0) {
|
||||
SDL_EventEntry *entry, *next;
|
||||
for (entry = SDL_EventQ.head; entry; entry = next) {
|
||||
next = entry->next;
|
||||
|
||||
@@ -27,13 +27,9 @@
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_gesture_c.h"
|
||||
|
||||
#if !defined(__PSP__)
|
||||
#include <memory.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
/*
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
*/
|
||||
|
||||
/* TODO: Replace with malloc */
|
||||
|
||||
@@ -137,7 +133,7 @@ int SDL_SaveAllDollarTemplates(SDL_RWops *dst)
|
||||
for (i = 0; i < SDL_numGestureTouches; i++) {
|
||||
SDL_GestureTouch* touch = &SDL_gestureTouch[i];
|
||||
for (j = 0; j < touch->numDollarTemplates; j++) {
|
||||
rtrn += SaveTemplate(&touch->dollarTemplate[i], dst);
|
||||
rtrn += SaveTemplate(&touch->dollarTemplate[j], dst);
|
||||
}
|
||||
}
|
||||
return rtrn;
|
||||
@@ -149,8 +145,8 @@ int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *dst)
|
||||
for (i = 0; i < SDL_numGestureTouches; i++) {
|
||||
SDL_GestureTouch* touch = &SDL_gestureTouch[i];
|
||||
for (j = 0; j < touch->numDollarTemplates; j++) {
|
||||
if (touch->dollarTemplate[i].hash == gestureId) {
|
||||
return SaveTemplate(&touch->dollarTemplate[i], dst);
|
||||
if (touch->dollarTemplate[j].hash == gestureId) {
|
||||
return SaveTemplate(&touch->dollarTemplate[j], dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,8 +450,8 @@ static int SDL_SendGestureDollar(SDL_GestureTouch* touch,
|
||||
SDL_Event event;
|
||||
event.dgesture.type = SDL_DOLLARGESTURE;
|
||||
event.dgesture.touchId = touch->id;
|
||||
event.mgesture.x = touch->centroid.x;
|
||||
event.mgesture.y = touch->centroid.y;
|
||||
event.dgesture.x = touch->centroid.x;
|
||||
event.dgesture.y = touch->centroid.y;
|
||||
event.dgesture.gestureId = gestureId;
|
||||
event.dgesture.error = error;
|
||||
/* A finger came up to trigger this event. */
|
||||
@@ -477,7 +473,6 @@ static int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId)
|
||||
void SDL_GestureProcessEvent(SDL_Event* event)
|
||||
{
|
||||
float x,y;
|
||||
SDL_FloatPoint path[DOLLARNPOINTS];
|
||||
int index;
|
||||
int i;
|
||||
float pathDx, pathDy;
|
||||
@@ -501,6 +496,8 @@ void SDL_GestureProcessEvent(SDL_Event* event)
|
||||
|
||||
/* Finger Up */
|
||||
if (event->type == SDL_FINGERUP) {
|
||||
SDL_FloatPoint path[DOLLARNPOINTS];
|
||||
|
||||
inTouch->numDownFingers--;
|
||||
|
||||
#ifdef ENABLE_DOLLAR
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
|
||||
@@ -619,6 +620,16 @@ SDL_SetKeyboardFocus(SDL_Window * window)
|
||||
|
||||
/* See if the current window has lost focus */
|
||||
if (keyboard->focus && keyboard->focus != window) {
|
||||
|
||||
/* new window shouldn't think it has mouse captured. */
|
||||
SDL_assert(!window || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE));
|
||||
|
||||
/* old window must lose an existing mouse capture. */
|
||||
if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) {
|
||||
SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */
|
||||
SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE));
|
||||
}
|
||||
|
||||
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
|
||||
0, 0);
|
||||
|
||||
|
||||
@@ -140,14 +140,14 @@ static SDL_bool
|
||||
SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int w, h;
|
||||
SDL_bool inWindow;
|
||||
SDL_bool inWindow = SDL_TRUE;
|
||||
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
if (x < 0 || y < 0 || x >= w || y >= h) {
|
||||
inWindow = SDL_FALSE;
|
||||
} else {
|
||||
inWindow = SDL_TRUE;
|
||||
if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
if (x < 0 || y < 0 || x >= w || y >= h) {
|
||||
inWindow = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Linux doesn't give you mouse events outside your window unless you grab
|
||||
@@ -204,7 +204,6 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
|
||||
int posted;
|
||||
int xrel;
|
||||
int yrel;
|
||||
int x_max = 0, y_max = 0;
|
||||
|
||||
if (mouse->relative_mode_warp) {
|
||||
int center_x = 0, center_y = 0;
|
||||
@@ -246,23 +245,29 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
|
||||
mouse->y += yrel;
|
||||
}
|
||||
|
||||
SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
|
||||
--x_max;
|
||||
--y_max;
|
||||
/* make sure that the pointers find themselves inside the windows,
|
||||
unless we have the mouse captured. */
|
||||
if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
|
||||
int x_max = 0, y_max = 0;
|
||||
|
||||
/* make sure that the pointers find themselves inside the windows */
|
||||
if (mouse->x > x_max) {
|
||||
mouse->x = x_max;
|
||||
}
|
||||
if (mouse->x < 0) {
|
||||
mouse->x = 0;
|
||||
}
|
||||
// !!! FIXME: shouldn't this be (window) instead of (mouse->focus)?
|
||||
SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
|
||||
--x_max;
|
||||
--y_max;
|
||||
|
||||
if (mouse->y > y_max) {
|
||||
mouse->y = y_max;
|
||||
}
|
||||
if (mouse->y < 0) {
|
||||
mouse->y = 0;
|
||||
if (mouse->x > x_max) {
|
||||
mouse->x = x_max;
|
||||
}
|
||||
if (mouse->x < 0) {
|
||||
mouse->x = 0;
|
||||
}
|
||||
|
||||
if (mouse->y > y_max) {
|
||||
mouse->y = y_max;
|
||||
}
|
||||
if (mouse->y < 0) {
|
||||
mouse->y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mouse->xdelta += xrel;
|
||||
@@ -298,10 +303,11 @@ static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
|
||||
{
|
||||
if (button >= mouse->num_clickstates) {
|
||||
int i, count = button + 1;
|
||||
mouse->clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
|
||||
if (!mouse->clickstate) {
|
||||
SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
|
||||
if (!clickstate) {
|
||||
return NULL;
|
||||
}
|
||||
mouse->clickstate = clickstate;
|
||||
|
||||
for (i = mouse->num_clickstates; i < count; ++i) {
|
||||
SDL_zero(mouse->clickstate[i]);
|
||||
@@ -392,7 +398,7 @@ SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y)
|
||||
SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y, SDL_MouseWheelDirection direction)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int posted;
|
||||
@@ -414,6 +420,7 @@ SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y)
|
||||
event.wheel.which = mouseID;
|
||||
event.wheel.x = x;
|
||||
event.wheel.y = y;
|
||||
event.wheel.direction = (Uint32)direction;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return posted;
|
||||
@@ -425,6 +432,9 @@ SDL_MouseQuit(void)
|
||||
SDL_Cursor *cursor, *next;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (mouse->CaptureMouse) {
|
||||
SDL_CaptureMouse(SDL_FALSE);
|
||||
}
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
SDL_ShowCursor(1);
|
||||
|
||||
@@ -476,16 +486,42 @@ SDL_GetRelativeMouseState(int *x, int *y)
|
||||
return mouse->buttonstate;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_GetGlobalMouseState(int *x, int *y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int tmpx, tmpy;
|
||||
|
||||
/* make sure these are never NULL for the backend implementations... */
|
||||
if (!x) {
|
||||
x = &tmpx;
|
||||
}
|
||||
if (!y) {
|
||||
y = &tmpy;
|
||||
}
|
||||
|
||||
*x = *y = 0;
|
||||
|
||||
if (!mouse->GetGlobalMouseState) {
|
||||
SDL_assert(0 && "This should really be implemented for every target.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mouse->GetGlobalMouseState(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if ( window == NULL )
|
||||
if (window == NULL) {
|
||||
window = mouse->focus;
|
||||
}
|
||||
|
||||
if ( window == NULL )
|
||||
if (window == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mouse->WarpMouse) {
|
||||
mouse->WarpMouse(window, x, y);
|
||||
@@ -494,6 +530,16 @@ SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_WarpMouseGlobal(int x, int y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (mouse->WarpMouseGlobal) {
|
||||
mouse->WarpMouseGlobal(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
|
||||
{
|
||||
@@ -539,7 +585,7 @@ SDL_SetRelativeMouseMode(SDL_bool enabled)
|
||||
mouse->relative_mode_warp = SDL_TRUE;
|
||||
} else if (mouse->SetRelativeMouseMode(enabled) < 0) {
|
||||
if (enabled) {
|
||||
// Fall back to warp mode if native relative mode failed
|
||||
/* Fall back to warp mode if native relative mode failed */
|
||||
mouse->relative_mode_warp = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
@@ -571,6 +617,41 @@ SDL_GetRelativeMouseMode()
|
||||
return mouse->relative_mode;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_CaptureMouse(SDL_bool enabled)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Window *focusWindow;
|
||||
SDL_bool isCaptured;
|
||||
|
||||
if (!mouse->CaptureMouse) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
focusWindow = SDL_GetKeyboardFocus();
|
||||
|
||||
isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE);
|
||||
if (isCaptured == enabled) {
|
||||
return 0; /* already done! */
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
if (!focusWindow) {
|
||||
return SDL_SetError("No window has focus");
|
||||
} else if (mouse->CaptureMouse(focusWindow) == -1) {
|
||||
return -1; /* CaptureMouse() should call SetError */
|
||||
}
|
||||
focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
|
||||
} else {
|
||||
if (mouse->CaptureMouse(NULL) == -1) {
|
||||
return -1; /* CaptureMouse() should call SetError */
|
||||
}
|
||||
focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_Cursor *
|
||||
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
|
||||
int w, int h, int hot_x, int hot_y)
|
||||
|
||||
@@ -57,12 +57,21 @@ typedef struct
|
||||
/* Free a window manager cursor */
|
||||
void (*FreeCursor) (SDL_Cursor * cursor);
|
||||
|
||||
/* Warp the mouse to (x,y) */
|
||||
/* Warp the mouse to (x,y) within a window */
|
||||
void (*WarpMouse) (SDL_Window * window, int x, int y);
|
||||
|
||||
/* Warp the mouse to (x,y) in screen space */
|
||||
void (*WarpMouseGlobal) (int x, int y);
|
||||
|
||||
/* Set relative mode */
|
||||
int (*SetRelativeMouseMode) (SDL_bool enabled);
|
||||
|
||||
/* Set mouse capture */
|
||||
int (*CaptureMouse) (SDL_Window * window);
|
||||
|
||||
/* Get absolute mouse coordinates. (x) and (y) are never NULL and set to zero before call. */
|
||||
Uint32 (*GetGlobalMouseState) (int *x, int *y);
|
||||
|
||||
/* Data common to all mice */
|
||||
SDL_MouseID mouseID;
|
||||
SDL_Window *focus;
|
||||
@@ -111,7 +120,7 @@ extern int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int rel
|
||||
extern int SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button);
|
||||
|
||||
/* Send a mouse wheel event */
|
||||
extern int SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y);
|
||||
extern int SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y, SDL_MouseWheelDirection direction);
|
||||
|
||||
/* Shutdown the mouse subsystem */
|
||||
extern void SDL_MouseQuit(void);
|
||||
|
||||
@@ -38,11 +38,15 @@
|
||||
#include "cocoa/SDL_rwopsbundlesupport.h"
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#ifdef ANDROID
|
||||
#ifdef __ANDROID__
|
||||
#include "../core/android/SDL_android.h"
|
||||
#include "SDL_system.h"
|
||||
#endif
|
||||
|
||||
#if __NACL__
|
||||
#include "nacl_io/nacl_io.h"
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
|
||||
/* Functions to read/write Win32 API file pointers */
|
||||
@@ -466,7 +470,7 @@ SDL_RWFromFile(const char *file, const char *mode)
|
||||
SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
|
||||
return NULL;
|
||||
}
|
||||
#if defined(ANDROID)
|
||||
#if defined(__ANDROID__)
|
||||
#ifdef HAVE_STDIO_H
|
||||
/* Try to open the file on the filesystem first */
|
||||
if (*file == '/') {
|
||||
|
||||
@@ -33,37 +33,30 @@
|
||||
Also, note the bundle layouts are different for iPhone and Mac.
|
||||
*/
|
||||
FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
FILE* fp = NULL;
|
||||
|
||||
/* If the file mode is writable, skip all the bundle stuff because generally the bundle is read-only. */
|
||||
if(strcmp("r", mode) && strcmp("rb", mode))
|
||||
{
|
||||
if(strcmp("r", mode) && strcmp("rb", mode)) {
|
||||
return fopen(file, mode);
|
||||
}
|
||||
|
||||
NSAutoreleasePool* autorelease_pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
NSFileManager* file_manager = [NSFileManager defaultManager];
|
||||
NSString* resource_path = [[NSBundle mainBundle] resourcePath];
|
||||
|
||||
NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
|
||||
|
||||
NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try])
|
||||
{
|
||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
||||
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
fp = fopen(file, mode);
|
||||
}
|
||||
|
||||
[autorelease_pool drain];
|
||||
|
||||
return fp;
|
||||
}
|
||||
}}
|
||||
|
||||
#endif /* __MACOSX__ */
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_ANDROID
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* System dependent filesystem routines */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_filesystem.h"
|
||||
#include "SDL_system.h"
|
||||
|
||||
|
||||
char *
|
||||
SDL_GetBasePath(void)
|
||||
{
|
||||
/* The current working directory is / on Android */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
const char *path = SDL_AndroidGetInternalStoragePath();
|
||||
if (path) {
|
||||
size_t pathlen = SDL_strlen(path)+2;
|
||||
char *fullpath = (char *)SDL_malloc(pathlen);
|
||||
if (!fullpath) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
SDL_snprintf(fullpath, pathlen, "%s/", path);
|
||||
return fullpath;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* SDL_FILESYSTEM_ANDROID */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -35,8 +35,8 @@
|
||||
|
||||
char *
|
||||
SDL_GetBasePath(void)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
const char* baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String];
|
||||
const char *base = NULL;
|
||||
@@ -62,14 +62,13 @@ SDL_GetBasePath(void)
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
return retval;
|
||||
}
|
||||
}}
|
||||
|
||||
char *
|
||||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
char *retval = NULL;
|
||||
|
||||
@@ -96,9 +95,8 @@ SDL_GetPrefPath(const char *org, const char *app)
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
return retval;
|
||||
}
|
||||
}}
|
||||
|
||||
#endif /* SDL_FILESYSTEM_COCOA */
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_EMSCRIPTEN
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* System dependent filesystem routines */
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_filesystem.h"
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
char *
|
||||
SDL_GetBasePath(void)
|
||||
{
|
||||
char *retval = "/";
|
||||
return SDL_strdup(retval);
|
||||
}
|
||||
|
||||
char *
|
||||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
const char *append = "/libsdl/";
|
||||
char *retval;
|
||||
size_t len = 0;
|
||||
|
||||
len = SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3;
|
||||
retval = (char *) SDL_malloc(len);
|
||||
if (!retval) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_snprintf(retval, len, "%s%s/%s/", append, org, app);
|
||||
|
||||
if (mkdir(retval, 0700) != 0 && errno != EEXIST) {
|
||||
SDL_SetError("Couldn't create directory '%s': '%s'", retval, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* SDL_FILESYSTEM_EMSCRIPTEN */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
+17
-19
@@ -18,27 +18,25 @@
|
||||
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"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <SDL_types.h>
|
||||
#ifdef SDL_FILESYSTEM_NACL
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
@interface SDLUIAccelerationDelegate: NSObject <UIAccelerometerDelegate> {
|
||||
|
||||
UIAccelerationValue x, y, z;
|
||||
BOOL isRunning;
|
||||
BOOL hasNewData;
|
||||
|
||||
char *
|
||||
SDL_GetBasePath(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+(SDLUIAccelerationDelegate *)sharedDelegate;
|
||||
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration;
|
||||
-(void)getLastOrientation:(Sint16 *)data;
|
||||
-(void)startup;
|
||||
-(void)shutdown;
|
||||
-(BOOL)isRunning;
|
||||
-(BOOL)hasNewData;
|
||||
-(void)setHasNewData:(BOOL)value;
|
||||
char *
|
||||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* SDL_FILESYSTEM_NACL */
|
||||
|
||||
@end
|
||||
/* *INDENT-ON* */
|
||||
@@ -197,7 +197,7 @@ SDL_GetPrefPath(const char *org, const char *app)
|
||||
}
|
||||
if (mkdir(retval, 0700) != 0 && errno != EEXIST) {
|
||||
error:
|
||||
SDL_SetError("Couldn't create directory '%s': ", retval, strerror(errno));
|
||||
SDL_SetError("Couldn't create directory '%s': '%s'", retval, strerror(errno));
|
||||
SDL_free(retval);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
/* TODO, WinRT: include copyright info in SDL_winrtpaths.cpp
|
||||
TODO, WinRT: remove the need to compile this with C++/CX (/ZW) extensions, and if possible, without C++ at all
|
||||
/* TODO, WinRT: remove the need to compile this with C++/CX (/ZW) extensions, and if possible, without C++ at all
|
||||
*/
|
||||
|
||||
#ifdef __WINRT__
|
||||
@@ -29,6 +28,7 @@
|
||||
extern "C" {
|
||||
#include "SDL_filesystem.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_system.h"
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
@@ -62,7 +62,7 @@ SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType)
|
||||
return path.c_str();
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
|
||||
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
|
||||
case SDL_WINRT_PATH_ROAMING_FOLDER:
|
||||
{
|
||||
static wstring path;
|
||||
@@ -144,31 +144,78 @@ SDL_GetPrefPath(const char *org, const char *app)
|
||||
* without violating Microsoft's app-store requirements.
|
||||
*/
|
||||
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
/* A 'Roaming' folder is not available in Windows Phone 8, however a 'Local' folder is. */
|
||||
const char * srcPath = SDL_WinRTGetFSPathUTF8(SDL_WINRT_PATH_LOCAL_FOLDER);
|
||||
#else
|
||||
/* A 'Roaming' folder is available on Windows 8 and 8.1. Use that. */
|
||||
const char * srcPath = SDL_WinRTGetFSPathUTF8(SDL_WINRT_PATH_ROAMING_FOLDER);
|
||||
#endif
|
||||
const WCHAR * srcPath = NULL;
|
||||
WCHAR path[MAX_PATH];
|
||||
char *retval = NULL;
|
||||
WCHAR* worg = NULL;
|
||||
WCHAR* wapp = NULL;
|
||||
size_t new_wpath_len = 0;
|
||||
BOOL api_result = FALSE;
|
||||
|
||||
size_t destPathLen;
|
||||
char * destPath = NULL;
|
||||
|
||||
if (!srcPath) {
|
||||
SDL_SetError("Couldn't locate our basepath: %s", SDL_GetError());
|
||||
srcPath = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_LOCAL_FOLDER);
|
||||
if ( ! srcPath) {
|
||||
SDL_SetError("Unable to find a source path");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
destPathLen = SDL_strlen(srcPath) + SDL_strlen(org) + SDL_strlen(app) + 4;
|
||||
destPath = (char *) SDL_malloc(destPathLen);
|
||||
if (!destPath) {
|
||||
if (SDL_wcslen(srcPath) >= MAX_PATH) {
|
||||
SDL_SetError("Path too long.");
|
||||
return NULL;
|
||||
}
|
||||
SDL_wcslcpy(path, srcPath, SDL_arraysize(path));
|
||||
|
||||
worg = WIN_UTF8ToString(org);
|
||||
if (worg == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_snprintf(destPath, destPathLen, "%s\\%s\\%s\\", srcPath, org, app);
|
||||
return destPath;
|
||||
wapp = WIN_UTF8ToString(app);
|
||||
if (wapp == NULL) {
|
||||
SDL_free(worg);
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_wpath_len = SDL_wcslen(worg) + SDL_wcslen(wapp) + SDL_wcslen(path) + 3;
|
||||
|
||||
if ((new_wpath_len + 1) > MAX_PATH) {
|
||||
SDL_free(worg);
|
||||
SDL_free(wapp);
|
||||
SDL_SetError("Path too long.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_wcslcat(path, L"\\", new_wpath_len + 1);
|
||||
SDL_wcslcat(path, worg, new_wpath_len + 1);
|
||||
SDL_free(worg);
|
||||
|
||||
api_result = CreateDirectoryW(path, NULL);
|
||||
if (api_result == FALSE) {
|
||||
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
||||
SDL_free(wapp);
|
||||
WIN_SetError("Couldn't create a prefpath.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_wcslcat(path, L"\\", new_wpath_len + 1);
|
||||
SDL_wcslcat(path, wapp, new_wpath_len + 1);
|
||||
SDL_free(wapp);
|
||||
|
||||
api_result = CreateDirectoryW(path, NULL);
|
||||
if (api_result == FALSE) {
|
||||
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
||||
WIN_SetError("Couldn't create a prefpath.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_wcslcat(path, L"\\", new_wpath_len + 1);
|
||||
|
||||
retval = WIN_StringToUTF8(path);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* __WINRT__ */
|
||||
|
||||
@@ -343,7 +343,7 @@ SDL_HapticClose(SDL_Haptic * haptic)
|
||||
}
|
||||
|
||||
/* Check if it's still in use */
|
||||
if (--haptic->ref_count < 0) {
|
||||
if (--haptic->ref_count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,12 @@
|
||||
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_syshaptic_h
|
||||
#define _SDL_syshaptic_h
|
||||
|
||||
#include "SDL_haptic.h"
|
||||
|
||||
|
||||
/*
|
||||
* Number of haptic devices on the system.
|
||||
*/
|
||||
extern Uint8 SDL_numhaptics;
|
||||
|
||||
|
||||
struct haptic_effect
|
||||
{
|
||||
SDL_HapticEffect effect; /* The current event */
|
||||
@@ -206,5 +203,7 @@ extern int SDL_SYS_HapticUnpause(SDL_Haptic * haptic);
|
||||
*/
|
||||
extern int SDL_SYS_HapticStopAll(SDL_Haptic * haptic);
|
||||
|
||||
#endif /* _SDL_syshaptic_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#ifdef SDL_HAPTIC_IOKIT
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_haptic.h"
|
||||
#include "../SDL_syshaptic.h"
|
||||
#include "SDL_joystick.h"
|
||||
@@ -91,14 +92,14 @@ static int numhaptics = -1;
|
||||
* Like strerror but for force feedback errors.
|
||||
*/
|
||||
static const char *
|
||||
FFStrError(HRESULT err)
|
||||
FFStrError(unsigned int err)
|
||||
{
|
||||
switch (err) {
|
||||
case FFERR_DEVICEFULL:
|
||||
return "device full";
|
||||
/* This should be valid, but for some reason isn't defined... */
|
||||
/* case FFERR_DEVICENOTREG:
|
||||
return "device not registered"; */
|
||||
/* This should be valid, but for some reason isn't defined... */
|
||||
/* case FFERR_DEVICENOTREG:
|
||||
return "device not registered"; */
|
||||
case FFERR_DEVICEPAUSED:
|
||||
return "device paused";
|
||||
case FFERR_DEVICERELEASED:
|
||||
@@ -257,21 +258,18 @@ MacHaptic_MaybeAddDevice( io_object_t device )
|
||||
kCFAllocatorDefault,
|
||||
kNilOptions);
|
||||
if ((result == KERN_SUCCESS) && hidProperties) {
|
||||
refCF =
|
||||
CFDictionaryGetValue(hidProperties,
|
||||
CFSTR(kIOHIDPrimaryUsagePageKey));
|
||||
refCF = CFDictionaryGetValue(hidProperties,
|
||||
CFSTR(kIOHIDPrimaryUsagePageKey));
|
||||
if (refCF) {
|
||||
if (!CFNumberGetValue(refCF, kCFNumberLongType,
|
||||
&item->usagePage))
|
||||
SDL_SetError
|
||||
("Haptic: Recieving device's usage page.");
|
||||
refCF =
|
||||
CFDictionaryGetValue(hidProperties,
|
||||
CFSTR(kIOHIDPrimaryUsageKey));
|
||||
if (!CFNumberGetValue(refCF, kCFNumberLongType, &item->usagePage)) {
|
||||
SDL_SetError("Haptic: Recieving device's usage page.");
|
||||
}
|
||||
refCF = CFDictionaryGetValue(hidProperties,
|
||||
CFSTR(kIOHIDPrimaryUsageKey));
|
||||
if (refCF) {
|
||||
if (!CFNumberGetValue(refCF, kCFNumberLongType,
|
||||
&item->usage))
|
||||
if (!CFNumberGetValue(refCF, kCFNumberLongType, &item->usage)) {
|
||||
SDL_SetError("Haptic: Recieving device's usage.");
|
||||
}
|
||||
}
|
||||
}
|
||||
CFRelease(hidProperties);
|
||||
@@ -377,24 +375,21 @@ HIDGetDeviceProduct(io_service_t dev, char *name)
|
||||
|
||||
|
||||
/* Get product name */
|
||||
refCF =
|
||||
CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey));
|
||||
if (!refCF)
|
||||
refCF =
|
||||
CFDictionaryGetValue(usbProperties,
|
||||
CFSTR("USB Product Name"));
|
||||
refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey));
|
||||
if (!refCF) {
|
||||
refCF = CFDictionaryGetValue(usbProperties,
|
||||
CFSTR("USB Product Name"));
|
||||
}
|
||||
if (refCF) {
|
||||
if (!CFStringGetCString(refCF, name, 256,
|
||||
CFStringGetSystemEncoding())) {
|
||||
return SDL_SetError
|
||||
("Haptic: CFStringGetCString error retrieving pDevice->product.");
|
||||
return SDL_SetError("Haptic: CFStringGetCString error retrieving pDevice->product.");
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(usbProperties);
|
||||
} else {
|
||||
return SDL_SetError
|
||||
("Haptic: IORegistryEntryCreateCFProperties failed to create usbProperties.");
|
||||
return SDL_SetError("Haptic: IORegistryEntryCreateCFProperties failed to create usbProperties.");
|
||||
}
|
||||
|
||||
/* Release stuff. */
|
||||
@@ -457,9 +452,9 @@ GetSupportedFeatures(SDL_Haptic * haptic)
|
||||
/* Check if supports gain. */
|
||||
ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_FFGAIN,
|
||||
&val, sizeof(val));
|
||||
if (ret == FF_OK)
|
||||
if (ret == FF_OK) {
|
||||
supported |= SDL_HAPTIC_GAIN;
|
||||
else if (ret != FFERR_UNSUPPORTED) {
|
||||
} else if (ret != FFERR_UNSUPPORTED) {
|
||||
return SDL_SetError("Haptic: Unable to get if device supports gain: %s.",
|
||||
FFStrError(ret));
|
||||
}
|
||||
@@ -467,9 +462,9 @@ GetSupportedFeatures(SDL_Haptic * haptic)
|
||||
/* Checks if supports autocenter. */
|
||||
ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_AUTOCENTER,
|
||||
&val, sizeof(val));
|
||||
if (ret == FF_OK)
|
||||
if (ret == FF_OK) {
|
||||
supported |= SDL_HAPTIC_AUTOCENTER;
|
||||
else if (ret != FFERR_UNSUPPORTED) {
|
||||
} else if (ret != FFERR_UNSUPPORTED) {
|
||||
return SDL_SetError
|
||||
("Haptic: Unable to get if device supports autocenter: %s.",
|
||||
FFStrError(ret));
|
||||
@@ -485,7 +480,7 @@ GetSupportedFeatures(SDL_Haptic * haptic)
|
||||
supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE;
|
||||
|
||||
haptic->supported = supported;
|
||||
return 0;;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -556,7 +551,7 @@ SDL_SYS_HapticOpenFromService(SDL_Haptic * haptic, io_service_t service)
|
||||
FFReleaseDevice(haptic->hwdata->device);
|
||||
creat_err:
|
||||
if (haptic->hwdata != NULL) {
|
||||
free(haptic->hwdata);
|
||||
SDL_free(haptic->hwdata);
|
||||
haptic->hwdata = NULL;
|
||||
}
|
||||
return -1;
|
||||
@@ -604,8 +599,9 @@ SDL_SYS_HapticMouse(void)
|
||||
int
|
||||
SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata->ffservice != 0)
|
||||
if (joystick->hwdata->ffservice != 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
@@ -617,8 +613,9 @@ int
|
||||
SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
{
|
||||
if (IOObjectIsEqualTo((io_object_t) ((size_t)haptic->hwdata->device),
|
||||
joystick->hwdata->ffservice))
|
||||
joystick->hwdata->ffservice)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -739,18 +736,22 @@ SDL_SYS_SetDirection(FFEFFECT * effect, SDL_HapticDirection * dir, int naxes)
|
||||
case SDL_HAPTIC_CARTESIAN:
|
||||
effect->dwFlags |= FFEFF_CARTESIAN;
|
||||
rglDir[0] = dir->dir[0];
|
||||
if (naxes > 1)
|
||||
if (naxes > 1) {
|
||||
rglDir[1] = dir->dir[1];
|
||||
if (naxes > 2)
|
||||
}
|
||||
if (naxes > 2) {
|
||||
rglDir[2] = dir->dir[2];
|
||||
}
|
||||
return 0;
|
||||
case SDL_HAPTIC_SPHERICAL:
|
||||
effect->dwFlags |= FFEFF_SPHERICAL;
|
||||
rglDir[0] = dir->dir[0];
|
||||
if (naxes > 1)
|
||||
if (naxes > 1) {
|
||||
rglDir[1] = dir->dir[1];
|
||||
if (naxes > 2)
|
||||
}
|
||||
if (naxes > 2) {
|
||||
rglDir[2] = dir->dir[2];
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
@@ -767,8 +768,7 @@ SDL_SYS_SetDirection(FFEFFECT * effect, SDL_HapticDirection * dir, int naxes)
|
||||
* Creates the FFEFFECT from a SDL_HapticEffect.
|
||||
*/
|
||||
static int
|
||||
SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest,
|
||||
SDL_HapticEffect * src)
|
||||
SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest, SDL_HapticEffect * src)
|
||||
{
|
||||
int i;
|
||||
FFCONSTANTFORCE *constant;
|
||||
@@ -873,9 +873,10 @@ SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest,
|
||||
SDL_memset(periodic, 0, sizeof(FFPERIODIC));
|
||||
|
||||
/* Specifics */
|
||||
periodic->dwMagnitude = CONVERT(hap_periodic->magnitude);
|
||||
periodic->dwMagnitude = CONVERT(SDL_abs(hap_periodic->magnitude));
|
||||
periodic->lOffset = CONVERT(hap_periodic->offset);
|
||||
periodic->dwPhase = hap_periodic->phase;
|
||||
periodic->dwPhase =
|
||||
(hap_periodic->phase + (hap_periodic->magnitude < 0 ? 18000 : 0)) % 36000;
|
||||
periodic->dwPeriod = hap_periodic->period * 1000;
|
||||
dest->cbTypeSpecificParams = sizeof(FFPERIODIC);
|
||||
dest->lpvTypeSpecificParams = periodic;
|
||||
@@ -925,10 +926,10 @@ SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest,
|
||||
condition[i].lNegativeCoefficient =
|
||||
CONVERT(hap_condition->left_coeff[i]);
|
||||
condition[i].dwPositiveSaturation =
|
||||
CCONVERT(hap_condition->right_sat[i]);
|
||||
CCONVERT(hap_condition->right_sat[i] / 2);
|
||||
condition[i].dwNegativeSaturation =
|
||||
CCONVERT(hap_condition->left_sat[i]);
|
||||
condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i]);
|
||||
CCONVERT(hap_condition->left_sat[i] / 2);
|
||||
condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i] / 2);
|
||||
}
|
||||
dest->cbTypeSpecificParams = sizeof(FFCONDITION) * dest->cAxes;
|
||||
dest->lpvTypeSpecificParams = condition;
|
||||
@@ -1269,8 +1270,7 @@ SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
HRESULT ret;
|
||||
|
||||
ret =
|
||||
FFDeviceReleaseEffect(haptic->hwdata->device, effect->hweffect->ref);
|
||||
ret = FFDeviceReleaseEffect(haptic->hwdata->device, effect->hweffect->ref);
|
||||
if (ret != FF_OK) {
|
||||
SDL_SetError("Haptic: Error removing the effect from the device: %s.",
|
||||
FFStrError(ret));
|
||||
@@ -1299,8 +1299,9 @@ SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
if (status == 0) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE; /* Assume it's playing or emulated. */
|
||||
}
|
||||
|
||||
@@ -1315,9 +1316,8 @@ SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
|
||||
Uint32 val;
|
||||
|
||||
val = gain * 100; /* Mac OS X uses 0 to 10,000 */
|
||||
ret =
|
||||
FFDeviceSetForceFeedbackProperty(haptic->hwdata->device,
|
||||
FFPROP_FFGAIN, &val);
|
||||
ret = FFDeviceSetForceFeedbackProperty(haptic->hwdata->device,
|
||||
FFPROP_FFGAIN, &val);
|
||||
if (ret != FF_OK) {
|
||||
return SDL_SetError("Haptic: Error setting gain: %s.", FFStrError(ret));
|
||||
}
|
||||
@@ -1336,10 +1336,11 @@ SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
|
||||
Uint32 val;
|
||||
|
||||
/* Mac OS X only has 0 (off) and 1 (on) */
|
||||
if (autocenter == 0)
|
||||
if (autocenter == 0) {
|
||||
val = 0;
|
||||
else
|
||||
} else {
|
||||
val = 1;
|
||||
}
|
||||
|
||||
ret = FFDeviceSetForceFeedbackProperty(haptic->hwdata->device,
|
||||
FFPROP_AUTOCENTER, &val);
|
||||
|
||||
@@ -288,8 +288,7 @@ MaybeAddDevice(const char *path)
|
||||
}
|
||||
|
||||
item->fname = SDL_strdup(path);
|
||||
if ( (item->fname == NULL) ) {
|
||||
SDL_free(item->fname);
|
||||
if (item->fname == NULL) {
|
||||
SDL_free(item);
|
||||
return -1;
|
||||
}
|
||||
@@ -441,7 +440,7 @@ SDL_SYS_HapticOpenFromFD(SDL_Haptic * haptic, int fd)
|
||||
open_err:
|
||||
close(fd);
|
||||
if (haptic->hwdata != NULL) {
|
||||
free(haptic->hwdata);
|
||||
SDL_free(haptic->hwdata);
|
||||
haptic->hwdata = NULL;
|
||||
}
|
||||
return -1;
|
||||
@@ -624,6 +623,8 @@ SDL_SYS_HapticQuit(void)
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
numhaptics = 0;
|
||||
SDL_hapticlist = NULL;
|
||||
SDL_hapticlist_tail = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -650,15 +651,14 @@ SDL_SYS_ToButton(Uint16 button)
|
||||
|
||||
|
||||
/*
|
||||
* Returns the ff_effect usable direction from a SDL_HapticDirection.
|
||||
* Initializes the ff_effect usable direction from a SDL_HapticDirection.
|
||||
*/
|
||||
static Uint16
|
||||
SDL_SYS_ToDirection(SDL_HapticDirection * dir)
|
||||
static int
|
||||
SDL_SYS_ToDirection(Uint16 *dest, SDL_HapticDirection * src)
|
||||
{
|
||||
Uint32 tmp;
|
||||
float f; /* Ideally we'd use fixed point math instead of floats... */
|
||||
|
||||
switch (dir->type) {
|
||||
switch (src->type) {
|
||||
case SDL_HAPTIC_POLAR:
|
||||
/* Linux directions start from south.
|
||||
(and range from 0 to 0xFFFF)
|
||||
@@ -668,25 +668,34 @@ SDL_SYS_ToDirection(SDL_HapticDirection * dir)
|
||||
90 deg -> 0x4000 (left)
|
||||
180 deg -> 0x8000 (up)
|
||||
270 deg -> 0xC000 (right)
|
||||
The force pulls into the direction specified by Linux directions,
|
||||
i.e. the opposite convention of SDL directions.
|
||||
*/
|
||||
tmp = (((18000 + dir->dir[0]) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
|
||||
return (Uint16) tmp;
|
||||
tmp = ((src->dir[0] % 36000) * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
|
||||
*dest = (Uint16) tmp;
|
||||
break;
|
||||
|
||||
case SDL_HAPTIC_SPHERICAL:
|
||||
case SDL_HAPTIC_SPHERICAL:
|
||||
/*
|
||||
We convert to polar, because that's the only supported direction on Linux.
|
||||
The first value of a spherical direction is practically the same as a
|
||||
Polar direction, except that we have to add 90 degrees. It is the angle
|
||||
from EAST {1,0} towards SOUTH {0,1}.
|
||||
--> add 9000
|
||||
--> finally add 18000 and convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
|
||||
--> finally convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
|
||||
*/
|
||||
tmp = ((dir->dir[0]) + 9000) % 36000; /* Convert to polars */
|
||||
tmp = (((18000 + tmp) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
|
||||
return (Uint16) tmp;
|
||||
tmp = ((src->dir[0]) + 9000) % 36000; /* Convert to polars */
|
||||
tmp = (tmp * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
|
||||
*dest = (Uint16) tmp;
|
||||
break;
|
||||
|
||||
case SDL_HAPTIC_CARTESIAN:
|
||||
f = atan2(dir->dir[1], dir->dir[0]);
|
||||
if (!src->dir[1])
|
||||
*dest = (src->dir[0] >= 0 ? 0x4000 : 0xC000);
|
||||
else if (!src->dir[0])
|
||||
*dest = (src->dir[1] >= 0 ? 0x8000 : 0);
|
||||
else {
|
||||
float f = atan2(src->dir[1], src->dir[0]); /* Ideally we'd use fixed point math instead of floats... */
|
||||
/*
|
||||
atan2 takes the parameters: Y-axis-value and X-axis-value (in that order)
|
||||
- Y-axis-value is the second coordinate (from center to SOUTH)
|
||||
@@ -695,14 +704,16 @@ SDL_SYS_ToDirection(SDL_HapticDirection * dir)
|
||||
have the first spherical value. Therefore we proceed as in case
|
||||
SDL_HAPTIC_SPHERICAL and add another 9000 to get the polar value.
|
||||
--> add 45000 in total
|
||||
--> finally add 18000 and convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
|
||||
--> finally convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
|
||||
*/
|
||||
tmp = (((int) (f * 18000. / M_PI)) + 45000) % 36000;
|
||||
tmp = (((18000 + tmp) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
|
||||
return (Uint16) tmp;
|
||||
tmp = (((Sint32) (f * 18000. / M_PI)) + 45000) % 36000;
|
||||
tmp = (tmp * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
|
||||
*dest = (Uint16) tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (Uint16) SDL_SetError("Haptic: Unsupported direction type.");
|
||||
return SDL_SetError("Haptic: Unsupported direction type.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -717,7 +728,6 @@ SDL_SYS_ToDirection(SDL_HapticDirection * dir)
|
||||
static int
|
||||
SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
||||
{
|
||||
Uint32 tmp;
|
||||
SDL_HapticConstant *constant;
|
||||
SDL_HapticPeriodic *periodic;
|
||||
SDL_HapticCondition *condition;
|
||||
@@ -733,8 +743,7 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
||||
|
||||
/* Header */
|
||||
dest->type = FF_CONSTANT;
|
||||
dest->direction = SDL_SYS_ToDirection(&constant->direction);
|
||||
if (dest->direction == (Uint16) - 1)
|
||||
if (SDL_SYS_ToDirection(&dest->direction, &constant->direction) == -1)
|
||||
return -1;
|
||||
|
||||
/* Replay */
|
||||
@@ -769,8 +778,7 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
||||
|
||||
/* Header */
|
||||
dest->type = FF_PERIODIC;
|
||||
dest->direction = SDL_SYS_ToDirection(&periodic->direction);
|
||||
if (dest->direction == (Uint16) - 1)
|
||||
if (SDL_SYS_ToDirection(&dest->direction, &periodic->direction) == -1)
|
||||
return -1;
|
||||
|
||||
/* Replay */
|
||||
@@ -797,9 +805,8 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
||||
dest->u.periodic.period = CLAMP(periodic->period);
|
||||
dest->u.periodic.magnitude = periodic->magnitude;
|
||||
dest->u.periodic.offset = periodic->offset;
|
||||
/* Phase is calculated based of offset from period and then clamped. */
|
||||
tmp = ((periodic->phase % 36000) * dest->u.periodic.period) / 36000;
|
||||
dest->u.periodic.phase = CLAMP(tmp);
|
||||
/* Linux phase is defined in interval "[0x0000, 0x10000[", corresponds with "[0deg, 360deg[" phase shift. */
|
||||
dest->u.periodic.phase = ((Uint32)periodic->phase * 0x10000U) / 36000;
|
||||
|
||||
/* Envelope */
|
||||
dest->u.periodic.envelope.attack_length =
|
||||
@@ -839,20 +846,18 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
||||
|
||||
/* Condition */
|
||||
/* X axis */
|
||||
dest->u.condition[0].right_saturation =
|
||||
CLAMP(condition->right_sat[0]);
|
||||
dest->u.condition[0].left_saturation = CLAMP(condition->left_sat[0]);
|
||||
dest->u.condition[0].right_saturation = condition->right_sat[0];
|
||||
dest->u.condition[0].left_saturation = condition->left_sat[0];
|
||||
dest->u.condition[0].right_coeff = condition->right_coeff[0];
|
||||
dest->u.condition[0].left_coeff = condition->left_coeff[0];
|
||||
dest->u.condition[0].deadband = CLAMP(condition->deadband[0]);
|
||||
dest->u.condition[0].deadband = condition->deadband[0];
|
||||
dest->u.condition[0].center = condition->center[0];
|
||||
/* Y axis */
|
||||
dest->u.condition[1].right_saturation =
|
||||
CLAMP(condition->right_sat[1]);
|
||||
dest->u.condition[1].left_saturation = CLAMP(condition->left_sat[1]);
|
||||
dest->u.condition[1].right_saturation = condition->right_sat[1];
|
||||
dest->u.condition[1].left_saturation = condition->left_sat[1];
|
||||
dest->u.condition[1].right_coeff = condition->right_coeff[1];
|
||||
dest->u.condition[1].left_coeff = condition->left_coeff[1];
|
||||
dest->u.condition[1].deadband = CLAMP(condition->deadband[1]);
|
||||
dest->u.condition[1].deadband = condition->deadband[1];
|
||||
dest->u.condition[1].center = condition->center[1];
|
||||
|
||||
/*
|
||||
@@ -866,8 +871,7 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
||||
|
||||
/* Header */
|
||||
dest->type = FF_RAMP;
|
||||
dest->direction = SDL_SYS_ToDirection(&ramp->direction);
|
||||
if (dest->direction == (Uint16) - 1)
|
||||
if (SDL_SYS_ToDirection(&dest->direction, &ramp->direction) == -1)
|
||||
return -1;
|
||||
|
||||
/* Replay */
|
||||
@@ -954,7 +958,7 @@ SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
|
||||
return 0;
|
||||
|
||||
new_effect_err:
|
||||
free(effect->hweffect);
|
||||
SDL_free(effect->hweffect);
|
||||
effect->hweffect = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
+340
-834
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_haptic.h"
|
||||
#include "SDL_windowshaptic_c.h"
|
||||
|
||||
|
||||
extern int SDL_DINPUT_HapticInit(void);
|
||||
extern int SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance);
|
||||
extern int SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance);
|
||||
extern int SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item);
|
||||
extern int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick);
|
||||
extern int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick);
|
||||
extern void SDL_DINPUT_HapticClose(SDL_Haptic * haptic);
|
||||
extern void SDL_DINPUT_HapticQuit(void);
|
||||
extern int SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base);
|
||||
extern int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data);
|
||||
extern int SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations);
|
||||
extern int SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
|
||||
extern void SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
|
||||
extern int SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect);
|
||||
extern int SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain);
|
||||
extern int SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter);
|
||||
extern int SDL_DINPUT_HapticPause(SDL_Haptic * haptic);
|
||||
extern int SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic);
|
||||
extern int SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
|
||||
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_haptic.h"
|
||||
#include "../SDL_syshaptic.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
|
||||
#include "../../joystick/windows/SDL_windowsjoystick_c.h" /* For joystick hwdata */
|
||||
#include "../../joystick/windows/SDL_xinputjoystick_c.h" /* For xinput rumble */
|
||||
|
||||
#include "SDL_windowshaptic_c.h"
|
||||
#include "SDL_dinputhaptic_c.h"
|
||||
#include "SDL_xinputhaptic_c.h"
|
||||
|
||||
|
||||
/*
|
||||
* Internal stuff.
|
||||
*/
|
||||
SDL_hapticlist_item *SDL_hapticlist = NULL;
|
||||
static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
|
||||
static int numhaptics = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Initializes the haptic subsystem.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticInit(void)
|
||||
{
|
||||
if (SDL_DINPUT_HapticInit() < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (SDL_XINPUT_HapticInit() < 0) {
|
||||
return -1;
|
||||
}
|
||||
return numhaptics;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
|
||||
{
|
||||
if (SDL_hapticlist_tail == NULL) {
|
||||
SDL_hapticlist = SDL_hapticlist_tail = item;
|
||||
} else {
|
||||
SDL_hapticlist_tail->next = item;
|
||||
SDL_hapticlist_tail = item;
|
||||
}
|
||||
|
||||
/* Device has been added. */
|
||||
++numhaptics;
|
||||
|
||||
return numhaptics;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
|
||||
{
|
||||
const int retval = item->haptic ? item->haptic->index : -1;
|
||||
if (prev != NULL) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
SDL_assert(SDL_hapticlist == item);
|
||||
SDL_hapticlist = item->next;
|
||||
}
|
||||
if (item == SDL_hapticlist_tail) {
|
||||
SDL_hapticlist_tail = prev;
|
||||
}
|
||||
--numhaptics;
|
||||
/* !!! TODO: Send a haptic remove event? */
|
||||
SDL_free(item);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_NumHaptics()
|
||||
{
|
||||
return numhaptics;
|
||||
}
|
||||
|
||||
static SDL_hapticlist_item *
|
||||
HapticByDevIndex(int device_index)
|
||||
{
|
||||
SDL_hapticlist_item *item = SDL_hapticlist;
|
||||
|
||||
if ((device_index < 0) || (device_index >= numhaptics)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (device_index > 0) {
|
||||
SDL_assert(item != NULL);
|
||||
--device_index;
|
||||
item = item->next;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the name of a haptic device, does not need to be opened.
|
||||
*/
|
||||
const char *
|
||||
SDL_SYS_HapticName(int index)
|
||||
{
|
||||
SDL_hapticlist_item *item = HapticByDevIndex(index);
|
||||
return item->name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a haptic device for usage.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticOpen(SDL_Haptic * haptic)
|
||||
{
|
||||
SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
|
||||
if (item->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticOpen(haptic, item);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticOpen(haptic, item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Opens a haptic device from first mouse it finds for usage.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticMouse(void)
|
||||
{
|
||||
#if SDL_HAPTIC_DINPUT
|
||||
SDL_hapticlist_item *item;
|
||||
int index = 0;
|
||||
|
||||
/* Grab the first mouse haptic device we find. */
|
||||
for (item = SDL_hapticlist; item != NULL; item = item->next) {
|
||||
if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
|
||||
return index;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
#endif /* SDL_HAPTIC_DINPUT */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Checks to see if a joystick has haptic features.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
|
||||
{
|
||||
const struct joystick_hwdata *hwdata = joystick->hwdata;
|
||||
#if SDL_HAPTIC_XINPUT
|
||||
if (hwdata->bXInputHaptic) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#if SDL_HAPTIC_DINPUT
|
||||
if (hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if the haptic device and joystick are in reality the same.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
|
||||
return 0; /* one is XInput, one is not; not the same device. */
|
||||
} else if (joystick->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
|
||||
} else {
|
||||
return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a SDL_Haptic from a SDL_Joystick.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata->bXInputDevice) {
|
||||
return SDL_XINPUT_HapticOpenFromJoystick(haptic, joystick);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the haptic device.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_HapticClose(SDL_Haptic * haptic)
|
||||
{
|
||||
if (haptic->hwdata) {
|
||||
|
||||
/* Free effects. */
|
||||
SDL_free(haptic->effects);
|
||||
haptic->effects = NULL;
|
||||
haptic->neffects = 0;
|
||||
|
||||
/* Clean up */
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
SDL_XINPUT_HapticClose(haptic);
|
||||
} else {
|
||||
SDL_DINPUT_HapticClose(haptic);
|
||||
}
|
||||
|
||||
/* Free */
|
||||
SDL_free(haptic->hwdata);
|
||||
haptic->hwdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up after system specific haptic stuff
|
||||
*/
|
||||
void
|
||||
SDL_SYS_HapticQuit(void)
|
||||
{
|
||||
SDL_hapticlist_item *item;
|
||||
SDL_hapticlist_item *next = NULL;
|
||||
SDL_Haptic *hapticitem = NULL;
|
||||
|
||||
extern SDL_Haptic *SDL_haptics;
|
||||
for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
|
||||
if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
|
||||
/* we _have_ to stop the thread before we free the XInput DLL! */
|
||||
hapticitem->hwdata->stopThread = 1;
|
||||
SDL_WaitThread(hapticitem->hwdata->thread, NULL);
|
||||
hapticitem->hwdata->thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (item = SDL_hapticlist; item; item = next) {
|
||||
/* Opened and not closed haptics are leaked, this is on purpose.
|
||||
* Close your haptic devices after usage. */
|
||||
/* !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. */
|
||||
next = item->next;
|
||||
SDL_free(item->name);
|
||||
SDL_free(item);
|
||||
}
|
||||
|
||||
SDL_XINPUT_HapticQuit();
|
||||
SDL_DINPUT_HapticQuit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new haptic effect.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
|
||||
SDL_HapticEffect * base)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Alloc the effect. */
|
||||
effect->hweffect = (struct haptic_hweffect *)
|
||||
SDL_malloc(sizeof(struct haptic_hweffect));
|
||||
if (effect->hweffect == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
SDL_zerop(effect->hweffect);
|
||||
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
result = SDL_XINPUT_HapticNewEffect(haptic, effect, base);
|
||||
} else {
|
||||
result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
|
||||
}
|
||||
if (result < 0) {
|
||||
SDL_free(effect->hweffect);
|
||||
effect->hweffect = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates an effect.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
|
||||
struct haptic_effect *effect,
|
||||
SDL_HapticEffect * data)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs an effect.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
|
||||
Uint32 iterations)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stops an effect.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticStopEffect(haptic, effect);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticStopEffect(haptic, effect);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees the effect.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
SDL_XINPUT_HapticDestroyEffect(haptic, effect);
|
||||
} else {
|
||||
SDL_DINPUT_HapticDestroyEffect(haptic, effect);
|
||||
}
|
||||
SDL_free(effect->hweffect);
|
||||
effect->hweffect = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the status of a haptic effect.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
|
||||
struct haptic_effect *effect)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticGetEffectStatus(haptic, effect);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the gain.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticSetGain(haptic, gain);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticSetGain(haptic, gain);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the autocentering.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pauses the device.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticPause(SDL_Haptic * haptic)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticPause(haptic);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticPause(haptic);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pauses the device.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticUnpause(haptic);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticUnpause(haptic);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stops all the playing effects on the device.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
|
||||
{
|
||||
if (haptic->hwdata->bXInputHaptic) {
|
||||
return SDL_XINPUT_HapticStopAll(haptic);
|
||||
} else {
|
||||
return SDL_DINPUT_HapticStopAll(haptic);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_windowshaptic_c_h
|
||||
#define _SDL_windowshaptic_c_h
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_syshaptic.h"
|
||||
#include "../../core/windows/SDL_directx.h"
|
||||
#include "../../core/windows/SDL_xinput.h"
|
||||
|
||||
/*
|
||||
* Haptic system hardware data.
|
||||
*/
|
||||
struct haptic_hwdata
|
||||
{
|
||||
#if SDL_HAPTIC_DINPUT
|
||||
LPDIRECTINPUTDEVICE8 device;
|
||||
#endif
|
||||
DWORD axes[3]; /* Axes to use. */
|
||||
SDL_bool is_joystick; /* Device is loaded as joystick. */
|
||||
Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
|
||||
Uint8 userid; /* XInput userid index for this joystick */
|
||||
SDL_Thread *thread;
|
||||
SDL_mutex *mutex;
|
||||
volatile Uint32 stopTicks;
|
||||
volatile int stopThread;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Haptic system effect data.
|
||||
*/
|
||||
struct haptic_hweffect
|
||||
{
|
||||
#if SDL_HAPTIC_DINPUT
|
||||
DIEFFECT effect;
|
||||
LPDIRECTINPUTEFFECT ref;
|
||||
#endif
|
||||
#if SDL_HAPTIC_XINPUT
|
||||
XINPUT_VIBRATION vibration;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* List of available haptic devices.
|
||||
*/
|
||||
typedef struct SDL_hapticlist_item
|
||||
{
|
||||
char *name;
|
||||
SDL_Haptic *haptic;
|
||||
#if SDL_HAPTIC_DINPUT
|
||||
DIDEVICEINSTANCE instance;
|
||||
DIDEVCAPS capabilities;
|
||||
#endif
|
||||
SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
|
||||
Uint8 userid; /* XInput userid index for this joystick */
|
||||
struct SDL_hapticlist_item *next;
|
||||
} SDL_hapticlist_item;
|
||||
|
||||
extern SDL_hapticlist_item *SDL_hapticlist;
|
||||
|
||||
extern int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item);
|
||||
extern int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item);
|
||||
|
||||
#endif /* _SDL_windowshaptic_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_assert.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_haptic.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_windowshaptic_c.h"
|
||||
#include "SDL_xinputhaptic_c.h"
|
||||
#include "../SDL_syshaptic.h"
|
||||
#include "../../core/windows/SDL_xinput.h"
|
||||
#include "../../joystick/windows/SDL_windowsjoystick_c.h"
|
||||
|
||||
|
||||
#if SDL_HAPTIC_XINPUT
|
||||
|
||||
/*
|
||||
* Internal stuff.
|
||||
*/
|
||||
static SDL_bool loaded_xinput = SDL_FALSE;
|
||||
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticInit(void)
|
||||
{
|
||||
const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
|
||||
if (!env || SDL_atoi(env)) {
|
||||
loaded_xinput = (WIN_LoadXInputDLL() == 0);
|
||||
}
|
||||
|
||||
if (loaded_xinput) {
|
||||
DWORD i;
|
||||
for (i = 0; i < XUSER_MAX_COUNT; i++) {
|
||||
SDL_XINPUT_MaybeAddDevice(i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
|
||||
{
|
||||
const Uint8 userid = (Uint8)dwUserid;
|
||||
SDL_hapticlist_item *item;
|
||||
XINPUT_VIBRATION state;
|
||||
|
||||
if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make sure we don't already have it */
|
||||
for (item = SDL_hapticlist; item; item = item->next) {
|
||||
if (item->bXInputHaptic && item->userid == userid) {
|
||||
return -1; /* Already added */
|
||||
}
|
||||
}
|
||||
|
||||
SDL_zero(state);
|
||||
if (XINPUTSETSTATE(dwUserid, &state) != ERROR_SUCCESS) {
|
||||
return -1; /* no force feedback on this device. */
|
||||
}
|
||||
|
||||
item = (SDL_hapticlist_item *)SDL_malloc(sizeof(SDL_hapticlist_item));
|
||||
if (item == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
SDL_zerop(item);
|
||||
|
||||
/* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */
|
||||
{
|
||||
char buf[64];
|
||||
SDL_snprintf(buf, sizeof(buf), "XInput Controller #%u", (unsigned int)(userid + 1));
|
||||
item->name = SDL_strdup(buf);
|
||||
}
|
||||
|
||||
if (!item->name) {
|
||||
SDL_free(item);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy the instance over, useful for creating devices. */
|
||||
item->bXInputHaptic = SDL_TRUE;
|
||||
item->userid = userid;
|
||||
|
||||
return SDL_SYS_AddHapticDevice(item);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
|
||||
{
|
||||
const Uint8 userid = (Uint8)dwUserid;
|
||||
SDL_hapticlist_item *item;
|
||||
SDL_hapticlist_item *prev = NULL;
|
||||
|
||||
if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (item = SDL_hapticlist; item != NULL; item = item->next) {
|
||||
if (item->bXInputHaptic && item->userid == userid) {
|
||||
/* found it, remove it. */
|
||||
return SDL_SYS_RemoveHapticDevice(prev, item);
|
||||
}
|
||||
prev = item;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* !!! FIXME: this is a hack, remove this later. */
|
||||
/* Since XInput doesn't offer a way to vibrate for X time, we hook into
|
||||
* SDL_PumpEvents() to check if it's time to stop vibrating with some
|
||||
* frequency.
|
||||
* In practice, this works for 99% of use cases. But in an ideal world,
|
||||
* we do this in a separate thread so that:
|
||||
* - we aren't bound to when the app chooses to pump the event queue.
|
||||
* - we aren't adding more polling to the event queue
|
||||
* - we can emulate all the haptic effects correctly (start on a delay,
|
||||
* mix multiple effects, etc).
|
||||
*
|
||||
* Mostly, this is here to get rumbling to work, and all the other features
|
||||
* are absent in the XInput path for now. :(
|
||||
*/
|
||||
static int SDLCALL
|
||||
SDL_RunXInputHaptic(void *arg)
|
||||
{
|
||||
struct haptic_hwdata *hwdata = (struct haptic_hwdata *) arg;
|
||||
|
||||
while (!hwdata->stopThread) {
|
||||
SDL_Delay(50);
|
||||
SDL_LockMutex(hwdata->mutex);
|
||||
/* If we're currently running and need to stop... */
|
||||
if (hwdata->stopTicks) {
|
||||
if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_TICKS_PASSED(SDL_GetTicks(), hwdata->stopTicks)) {
|
||||
XINPUT_VIBRATION vibration = { 0, 0 };
|
||||
hwdata->stopTicks = 0;
|
||||
XINPUTSETSTATE(hwdata->userid, &vibration);
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(hwdata->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 userid)
|
||||
{
|
||||
char threadName[32];
|
||||
XINPUT_VIBRATION vibration = { 0, 0 }; /* stop any current vibration */
|
||||
XINPUTSETSTATE(userid, &vibration);
|
||||
|
||||
haptic->supported = SDL_HAPTIC_LEFTRIGHT;
|
||||
|
||||
haptic->neffects = 1;
|
||||
haptic->nplaying = 1;
|
||||
|
||||
/* Prepare effects memory. */
|
||||
haptic->effects = (struct haptic_effect *)
|
||||
SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
|
||||
if (haptic->effects == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
/* Clear the memory */
|
||||
SDL_memset(haptic->effects, 0,
|
||||
sizeof(struct haptic_effect) * haptic->neffects);
|
||||
|
||||
haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata));
|
||||
if (haptic->hwdata == NULL) {
|
||||
SDL_free(haptic->effects);
|
||||
haptic->effects = NULL;
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
|
||||
|
||||
haptic->hwdata->bXInputHaptic = 1;
|
||||
haptic->hwdata->userid = userid;
|
||||
|
||||
haptic->hwdata->mutex = SDL_CreateMutex();
|
||||
if (haptic->hwdata->mutex == NULL) {
|
||||
SDL_free(haptic->effects);
|
||||
SDL_free(haptic->hwdata);
|
||||
haptic->effects = NULL;
|
||||
return SDL_SetError("Couldn't create XInput haptic mutex");
|
||||
}
|
||||
|
||||
SDL_snprintf(threadName, sizeof(threadName), "SDLXInputDev%d", (int)userid);
|
||||
|
||||
#if defined(__WIN32__) && !defined(HAVE_LIBC) /* !!! FIXME: this is nasty. */
|
||||
#undef SDL_CreateThread
|
||||
#if SDL_DYNAMIC_API
|
||||
haptic->hwdata->thread = SDL_CreateThread_REAL(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
|
||||
#else
|
||||
haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
|
||||
#endif
|
||||
#else
|
||||
haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata);
|
||||
#endif
|
||||
if (haptic->hwdata->thread == NULL) {
|
||||
SDL_DestroyMutex(haptic->hwdata->mutex);
|
||||
SDL_free(haptic->effects);
|
||||
SDL_free(haptic->hwdata);
|
||||
haptic->effects = NULL;
|
||||
return SDL_SetError("Couldn't create XInput haptic thread");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
|
||||
{
|
||||
return SDL_XINPUT_HapticOpenFromUserIndex(haptic, item->userid);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
{
|
||||
return (haptic->hwdata->userid == joystick->hwdata->userid);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_hapticlist_item *item;
|
||||
int index = 0;
|
||||
|
||||
/* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
|
||||
for (item = SDL_hapticlist; item != NULL; item = item->next) {
|
||||
if (item->bXInputHaptic && item->userid == joystick->hwdata->userid) {
|
||||
haptic->index = index;
|
||||
return SDL_XINPUT_HapticOpenFromUserIndex(haptic, joystick->hwdata->userid);
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
SDL_SetError("Couldn't find joystick in haptic device list");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_HapticClose(SDL_Haptic * haptic)
|
||||
{
|
||||
haptic->hwdata->stopThread = 1;
|
||||
SDL_WaitThread(haptic->hwdata->thread, NULL);
|
||||
SDL_DestroyMutex(haptic->hwdata->mutex);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_HapticQuit(void)
|
||||
{
|
||||
if (loaded_xinput) {
|
||||
WIN_UnloadXInputDLL();
|
||||
loaded_xinput = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
|
||||
{
|
||||
SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
|
||||
return SDL_XINPUT_HapticUpdateEffect(haptic, effect, base);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
|
||||
{
|
||||
XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
|
||||
SDL_assert(data->type == SDL_HAPTIC_LEFTRIGHT);
|
||||
vib->wLeftMotorSpeed = data->leftright.large_magnitude;
|
||||
vib->wRightMotorSpeed = data->leftright.small_magnitude;
|
||||
SDL_LockMutex(haptic->hwdata->mutex);
|
||||
if (haptic->hwdata->stopTicks) { /* running right now? Update it. */
|
||||
XINPUTSETSTATE(haptic->hwdata->userid, vib);
|
||||
}
|
||||
SDL_UnlockMutex(haptic->hwdata->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
|
||||
{
|
||||
XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
|
||||
SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
|
||||
SDL_LockMutex(haptic->hwdata->mutex);
|
||||
if (effect->effect.leftright.length == SDL_HAPTIC_INFINITY || iterations == SDL_HAPTIC_INFINITY) {
|
||||
haptic->hwdata->stopTicks = SDL_HAPTIC_INFINITY;
|
||||
} else if ((!effect->effect.leftright.length) || (!iterations)) {
|
||||
/* do nothing. Effect runs for zero milliseconds. */
|
||||
} else {
|
||||
haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
|
||||
if ((haptic->hwdata->stopTicks == SDL_HAPTIC_INFINITY) || (haptic->hwdata->stopTicks == 0)) {
|
||||
haptic->hwdata->stopTicks = 1; /* fix edge cases. */
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(haptic->hwdata->mutex);
|
||||
return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
XINPUT_VIBRATION vibration = { 0, 0 };
|
||||
SDL_LockMutex(haptic->hwdata->mutex);
|
||||
haptic->hwdata->stopTicks = 0;
|
||||
SDL_UnlockMutex(haptic->hwdata->mutex);
|
||||
return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
SDL_XINPUT_HapticStopEffect(haptic, effect);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticPause(SDL_Haptic * haptic)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic)
|
||||
{
|
||||
XINPUT_VIBRATION vibration = { 0, 0 };
|
||||
SDL_LockMutex(haptic->hwdata->mutex);
|
||||
haptic->hwdata->stopTicks = 0;
|
||||
SDL_UnlockMutex(haptic->hwdata->mutex);
|
||||
return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
|
||||
}
|
||||
|
||||
#else /* !SDL_HAPTIC_XINPUT */
|
||||
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticInit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_HapticClose(SDL_Haptic * haptic)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_HapticQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticPause(SDL_Haptic * haptic)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
#endif /* SDL_HAPTIC_XINPUT */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_haptic.h"
|
||||
#include "SDL_windowshaptic_c.h"
|
||||
|
||||
|
||||
extern int SDL_XINPUT_HapticInit(void);
|
||||
extern int SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid);
|
||||
extern int SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid);
|
||||
extern int SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item);
|
||||
extern int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick);
|
||||
extern int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick);
|
||||
extern void SDL_XINPUT_HapticClose(SDL_Haptic * haptic);
|
||||
extern void SDL_XINPUT_HapticQuit(void);
|
||||
extern int SDL_XINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base);
|
||||
extern int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data);
|
||||
extern int SDL_XINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations);
|
||||
extern int SDL_XINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
|
||||
extern void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect);
|
||||
extern int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect);
|
||||
extern int SDL_XINPUT_HapticSetGain(SDL_Haptic * haptic, int gain);
|
||||
extern int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter);
|
||||
extern int SDL_XINPUT_HapticPause(SDL_Haptic * haptic);
|
||||
extern int SDL_XINPUT_HapticUnpause(SDL_Haptic * haptic);
|
||||
extern int SDL_XINPUT_HapticStopAll(SDL_Haptic * haptic);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,10 @@
|
||||
*/
|
||||
static const char *s_ControllerMappings [] =
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_DINPUT
|
||||
#if SDL_JOYSTICK_XINPUT
|
||||
"xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
#endif
|
||||
#if SDL_JOYSTICK_DINPUT
|
||||
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
@@ -40,11 +43,9 @@ static const char *s_ControllerMappings [] =
|
||||
"88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,",
|
||||
"4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,",
|
||||
"4c05c405000000000000504944564944,PS4 Controller,a:a3,a:b1,b:b2,back:b8,dpdown:h0.0,dpdown:h0.4,dpleft:h0.8,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,guide:b12,leftshoulder:b4,leftshoulder:h0.0,leftstick:b10,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightshoulder:b6,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:a4,x:b0,y:b3,",
|
||||
"xinput,X360 Controller,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,",
|
||||
#elif defined(SDL_JOYSTICK_XINPUT)
|
||||
"xinput,X360 Controller,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,",
|
||||
#elif defined(__MACOSX__)
|
||||
"4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
#endif
|
||||
#if defined(__MACOSX__)
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
|
||||
"6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
@@ -53,7 +54,8 @@ static const char *s_ControllerMappings [] =
|
||||
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
|
||||
#elif defined(__LINUX__)
|
||||
#endif
|
||||
#if defined(__LINUX__)
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,",
|
||||
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
|
||||
@@ -61,14 +63,23 @@ static const char *s_ControllerMappings [] =
|
||||
"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
|
||||
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
|
||||
"050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
|
||||
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,",
|
||||
#endif
|
||||
#if defined(__ANDROID__)
|
||||
"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
|
||||
#endif
|
||||
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
|
||||
"emscripten,Standard Gamepad,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,back:b8,start:b9,leftstick:b10,rightstick:b11,dpup:b12,dpdown:b13,dpleft:b14,dpright:b15,guide:b16,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -113,9 +113,8 @@ SDL_JoystickOpen(int device_index)
|
||||
/* If the joystick is already open, return it
|
||||
* it is important that we have a single joystick * for each instance id
|
||||
*/
|
||||
while ( joysticklist )
|
||||
{
|
||||
if ( SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id ) {
|
||||
while (joysticklist) {
|
||||
if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id) {
|
||||
joystick = joysticklist;
|
||||
++joystick->ref_count;
|
||||
return (joystick);
|
||||
@@ -136,9 +135,9 @@ SDL_JoystickOpen(int device_index)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
joystickname = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
if ( joystickname )
|
||||
joystick->name = SDL_strdup( joystickname );
|
||||
joystickname = SDL_SYS_JoystickNameForDeviceIndex(device_index);
|
||||
if (joystickname)
|
||||
joystick->name = SDL_strdup(joystickname);
|
||||
else
|
||||
joystick->name = NULL;
|
||||
|
||||
@@ -186,7 +185,7 @@ SDL_JoystickOpen(int device_index)
|
||||
joystick->next = SDL_joysticks;
|
||||
SDL_joysticks = joystick;
|
||||
|
||||
SDL_SYS_JoystickUpdate( joystick );
|
||||
SDL_SYS_JoystickUpdate(joystick);
|
||||
|
||||
return (joystick);
|
||||
}
|
||||
@@ -200,15 +199,14 @@ SDL_PrivateJoystickValid(SDL_Joystick * joystick)
|
||||
{
|
||||
int valid;
|
||||
|
||||
if ( joystick == NULL ) {
|
||||
if (joystick == NULL) {
|
||||
SDL_SetError("Joystick hasn't been opened yet");
|
||||
valid = 0;
|
||||
} else {
|
||||
valid = 1;
|
||||
}
|
||||
|
||||
if ( joystick && joystick->closed )
|
||||
{
|
||||
if (joystick && joystick->closed) {
|
||||
valid = 0;
|
||||
}
|
||||
|
||||
@@ -417,20 +415,14 @@ SDL_JoystickClose(SDL_Joystick * joystick)
|
||||
|
||||
joysticklist = SDL_joysticks;
|
||||
joysticklistprev = NULL;
|
||||
while ( joysticklist )
|
||||
{
|
||||
if (joystick == joysticklist)
|
||||
{
|
||||
if ( joysticklistprev )
|
||||
{
|
||||
while (joysticklist) {
|
||||
if (joystick == joysticklist) {
|
||||
if (joysticklistprev) {
|
||||
/* unlink this entry */
|
||||
joysticklistprev->next = joysticklist->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
SDL_joysticks = joystick->next;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
joysticklistprev = joysticklist;
|
||||
@@ -454,8 +446,7 @@ SDL_JoystickQuit(void)
|
||||
SDL_assert(!SDL_updating_joystick);
|
||||
|
||||
/* Stop the event polling */
|
||||
while ( SDL_joysticks )
|
||||
{
|
||||
while (SDL_joysticks) {
|
||||
SDL_joysticks->ref_count = 1;
|
||||
SDL_JoystickClose(SDL_joysticks);
|
||||
}
|
||||
@@ -472,8 +463,7 @@ SDL_JoystickQuit(void)
|
||||
static SDL_bool
|
||||
SDL_PrivateJoystickShouldIgnoreEvent()
|
||||
{
|
||||
if (SDL_joystick_allows_background_events)
|
||||
{
|
||||
if (SDL_joystick_allows_background_events) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
@@ -497,26 +487,27 @@ SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
|
||||
{
|
||||
int posted;
|
||||
|
||||
/* Make sure we're not getting garbage events */
|
||||
/* Make sure we're not getting garbage or duplicate events */
|
||||
if (axis >= joystick->naxes) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update internal joystick state */
|
||||
if (value == joystick->axes[axis]) {
|
||||
return 0;
|
||||
}
|
||||
joystick->axes[axis] = value;
|
||||
|
||||
/* We ignore events if we don't have keyboard focus, except for centering
|
||||
* events.
|
||||
*/
|
||||
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
|
||||
if (!(joystick->closed && joystick->uncentered)) {
|
||||
if ((value > 0 && value >= joystick->axes[axis]) ||
|
||||
(value < 0 && value <= joystick->axes[axis])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update internal joystick state */
|
||||
joystick->axes[axis] = value;
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
@@ -537,23 +528,25 @@ SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
|
||||
{
|
||||
int posted;
|
||||
|
||||
/* Make sure we're not getting garbage events */
|
||||
/* Make sure we're not getting garbage or duplicate events */
|
||||
if (hat >= joystick->nhats) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update internal joystick state */
|
||||
joystick->hats[hat] = value;
|
||||
if (value == joystick->hats[hat]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We ignore events if we don't have keyboard focus, except for centering
|
||||
* events.
|
||||
*/
|
||||
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
|
||||
if (!(joystick->closed && joystick->uncentered)) {
|
||||
if (value != SDL_HAT_CENTERED) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update internal joystick state */
|
||||
joystick->hats[hat] = value;
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
@@ -626,15 +619,20 @@ SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
/* Make sure we're not getting garbage events */
|
||||
/* Make sure we're not getting garbage or duplicate events */
|
||||
if (button >= joystick->nbuttons) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (state == joystick->buttons[button]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We ignore events if we don't have keyboard focus, except for button
|
||||
* release. */
|
||||
if (state == SDL_PRESSED && SDL_PrivateJoystickShouldIgnoreEvent()) {
|
||||
return 0;
|
||||
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
|
||||
if (state == SDL_PRESSED) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update internal joystick state */
|
||||
@@ -659,8 +657,7 @@ SDL_JoystickUpdate(void)
|
||||
SDL_Joystick *joystick;
|
||||
|
||||
joystick = SDL_joysticks;
|
||||
while ( joystick )
|
||||
{
|
||||
while (joystick) {
|
||||
SDL_Joystick *joysticknext;
|
||||
/* save off the next pointer, the Update call may cause a joystick removed event
|
||||
* and cause our joystick pointer to be freed
|
||||
@@ -669,10 +666,9 @@ SDL_JoystickUpdate(void)
|
||||
|
||||
SDL_updating_joystick = joystick;
|
||||
|
||||
SDL_SYS_JoystickUpdate( joystick );
|
||||
SDL_SYS_JoystickUpdate(joystick);
|
||||
|
||||
if ( joystick->closed && joystick->uncentered )
|
||||
{
|
||||
if (joystick->closed && joystick->uncentered) {
|
||||
int i;
|
||||
|
||||
/* Tell the app that everything is centered/unpressed... */
|
||||
@@ -685,13 +681,13 @@ SDL_JoystickUpdate(void)
|
||||
for (i = 0; i < joystick->nhats; i++)
|
||||
SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
|
||||
|
||||
joystick->uncentered = 0;
|
||||
joystick->uncentered = SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_updating_joystick = NULL;
|
||||
|
||||
/* If the joystick was closed while updating, free it here */
|
||||
if ( joystick->ref_count <= 0 ) {
|
||||
if (joystick->ref_count <= 0) {
|
||||
SDL_JoystickClose(joystick);
|
||||
}
|
||||
|
||||
@@ -736,28 +732,16 @@ SDL_JoystickEventState(int state)
|
||||
#endif /* SDL_EVENTS_DISABLED */
|
||||
}
|
||||
|
||||
/* return 1 if you want to run the joystick update loop this frame, used by hotplug support */
|
||||
SDL_bool
|
||||
SDL_PrivateJoystickNeedsPolling()
|
||||
{
|
||||
if (SDL_joysticks != NULL) {
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
return SDL_SYS_JoystickNeedsPolling();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* return the guid for this index */
|
||||
SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
|
||||
{
|
||||
if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
|
||||
SDL_JoystickGUID emptyGUID;
|
||||
SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
|
||||
SDL_zero( emptyGUID );
|
||||
SDL_zero(emptyGUID);
|
||||
return emptyGUID;
|
||||
}
|
||||
return SDL_SYS_JoystickGetDeviceGUID( device_index );
|
||||
return SDL_SYS_JoystickGetDeviceGUID(device_index);
|
||||
}
|
||||
|
||||
/* return the guid for this opened device */
|
||||
@@ -765,14 +749,14 @@ SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
if (!SDL_PrivateJoystickValid(joystick)) {
|
||||
SDL_JoystickGUID emptyGUID;
|
||||
SDL_zero( emptyGUID );
|
||||
SDL_zero(emptyGUID);
|
||||
return emptyGUID;
|
||||
}
|
||||
return SDL_SYS_JoystickGetGUID( joystick );
|
||||
return SDL_SYS_JoystickGetGUID(joystick);
|
||||
}
|
||||
|
||||
/* convert the guid to a printable string */
|
||||
void SDL_JoystickGetGUIDString( SDL_JoystickGUID guid, char *pszGUID, int cbGUID )
|
||||
void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
|
||||
{
|
||||
static const char k_rgchHexToASCII[] = "0123456789abcdef";
|
||||
int i;
|
||||
@@ -781,14 +765,13 @@ void SDL_JoystickGetGUIDString( SDL_JoystickGUID guid, char *pszGUID, int cbGUID
|
||||
return;
|
||||
}
|
||||
|
||||
for ( i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++ )
|
||||
{
|
||||
for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
|
||||
/* each input byte writes 2 ascii chars, and might write a null byte. */
|
||||
/* If we don't have room for next input byte, stop */
|
||||
unsigned char c = guid.data[i];
|
||||
|
||||
*pszGUID++ = k_rgchHexToASCII[ c >> 4 ];
|
||||
*pszGUID++ = k_rgchHexToASCII[ c & 0x0F ];
|
||||
*pszGUID++ = k_rgchHexToASCII[c >> 4];
|
||||
*pszGUID++ = k_rgchHexToASCII[c & 0x0F];
|
||||
}
|
||||
*pszGUID = '\0';
|
||||
}
|
||||
@@ -799,28 +782,22 @@ void SDL_JoystickGetGUIDString( SDL_JoystickGUID guid, char *pszGUID, int cbGUID
|
||||
* Input : c -
|
||||
* Output : unsigned char
|
||||
*-----------------------------------------------------------------------------*/
|
||||
static unsigned char nibble( char c )
|
||||
static unsigned char nibble(char c)
|
||||
{
|
||||
if ( ( c >= '0' ) &&
|
||||
( c <= '9' ) )
|
||||
{
|
||||
if ((c >= '0') && (c <= '9')) {
|
||||
return (unsigned char)(c - '0');
|
||||
}
|
||||
|
||||
if ( ( c >= 'A' ) &&
|
||||
( c <= 'F' ) )
|
||||
{
|
||||
if ((c >= 'A') && (c <= 'F')) {
|
||||
return (unsigned char)(c - 'A' + 0x0a);
|
||||
}
|
||||
|
||||
if ( ( c >= 'a' ) &&
|
||||
( c <= 'f' ) )
|
||||
{
|
||||
if ((c >= 'a') && (c <= 'f')) {
|
||||
return (unsigned char)(c - 'a' + 0x0a);
|
||||
}
|
||||
|
||||
/* received an invalid character, and no real way to return an error */
|
||||
/* AssertMsg1( false, "Q_nibble invalid hex character '%c' ", c ); */
|
||||
/* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -830,21 +807,18 @@ SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
int maxoutputbytes= sizeof(guid);
|
||||
size_t len = SDL_strlen( pchGUID );
|
||||
size_t len = SDL_strlen(pchGUID);
|
||||
Uint8 *p;
|
||||
size_t i;
|
||||
|
||||
/* Make sure it's even */
|
||||
len = ( len ) & ~0x1;
|
||||
len = (len) & ~0x1;
|
||||
|
||||
SDL_memset( &guid, 0x00, sizeof(guid) );
|
||||
SDL_memset(&guid, 0x00, sizeof(guid));
|
||||
|
||||
p = (Uint8 *)&guid;
|
||||
for ( i = 0;
|
||||
( i < len ) && ( ( p - (Uint8 *)&guid ) < maxoutputbytes );
|
||||
i+=2, p++ )
|
||||
{
|
||||
*p = ( nibble( pchGUID[i] ) << 4 ) | nibble( pchGUID[i+1] );
|
||||
for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
|
||||
*p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]);
|
||||
}
|
||||
|
||||
return guid;
|
||||
|
||||
@@ -42,9 +42,6 @@ extern int SDL_PrivateJoystickHat(SDL_Joystick * joystick,
|
||||
extern int SDL_PrivateJoystickButton(SDL_Joystick * joystick,
|
||||
Uint8 button, Uint8 state);
|
||||
|
||||
/* Helper function to let lower sys layer tell the event system if the joystick code needs to think */
|
||||
extern SDL_bool SDL_PrivateJoystickNeedsPolling();
|
||||
|
||||
/* Internal sanity checking functions */
|
||||
extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick);
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_sysjoystick_h
|
||||
#define _SDL_sysjoystick_h
|
||||
|
||||
/* This is the system specific header for the SDL joystick API */
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
@@ -50,8 +53,8 @@ struct _SDL_Joystick
|
||||
|
||||
int ref_count; /* Reference count for multiple opens */
|
||||
|
||||
Uint8 closed; /* 1 if this device is no longer valid */
|
||||
Uint8 uncentered; /* 1 if this device needs to have its state reset to 0 */
|
||||
SDL_bool closed; /* SDL_TRUE if this device is no longer valid */
|
||||
SDL_bool uncentered; /* SDL_TRUE if this device needs to have its state reset to 0 */
|
||||
struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
|
||||
};
|
||||
|
||||
@@ -68,9 +71,6 @@ extern int SDL_SYS_NumJoysticks();
|
||||
/* Function to cause any queued joystick insertions to be processed */
|
||||
extern void SDL_SYS_JoystickDetect();
|
||||
|
||||
/* Function to determine if the joystick loop needs to run right now */
|
||||
extern SDL_bool SDL_SYS_JoystickNeedsPolling();
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
extern const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index);
|
||||
|
||||
@@ -78,14 +78,14 @@ extern const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index);
|
||||
extern SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index);
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
extern int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index);
|
||||
|
||||
/* Function to query if the joystick is currently attached
|
||||
* It returns 1 if attached, 0 otherwise.
|
||||
* It returns SDL_TRUE if attached, SDL_FALSE otherwise.
|
||||
*/
|
||||
extern SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick);
|
||||
|
||||
@@ -108,10 +108,11 @@ extern SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index);
|
||||
/* Function to return the stable GUID for a opened joystick */
|
||||
extern SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick);
|
||||
|
||||
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
|
||||
/* Function to get the current instance id of the joystick located at device_index */
|
||||
extern SDL_bool SDL_SYS_IsXInputDeviceIndex( int device_index );
|
||||
extern SDL_bool SDL_SYS_IsXInputJoystick(SDL_Joystick * joystick);
|
||||
#if SDL_JOYSTICK_XINPUT
|
||||
/* Function returns SDL_TRUE if this device is an XInput gamepad */
|
||||
extern SDL_bool SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index);
|
||||
#endif
|
||||
|
||||
#endif /* _SDL_sysjoystick_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -410,11 +410,6 @@ void SDL_SYS_JoystickDetect()
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_joylist_item *
|
||||
JoystickByDevIndex(int device_index)
|
||||
{
|
||||
@@ -472,7 +467,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
@@ -213,11 +213,6 @@ void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#endif
|
||||
|
||||
#define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick")
|
||||
|
||||
/* The base object of the HID Manager API */
|
||||
static IOHIDManagerRef hidman = NULL;
|
||||
|
||||
@@ -67,6 +69,11 @@ FreeDevice(recDevice *removeDevice)
|
||||
{
|
||||
recDevice *pDeviceNext = NULL;
|
||||
if (removeDevice) {
|
||||
if (removeDevice->deviceRef) {
|
||||
IOHIDDeviceUnscheduleFromRunLoop(removeDevice->deviceRef, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||
removeDevice->deviceRef = NULL;
|
||||
}
|
||||
|
||||
/* save next device prior to disposing of this device */
|
||||
pDeviceNext = removeDevice->pNext;
|
||||
|
||||
@@ -132,6 +139,7 @@ JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
|
||||
{
|
||||
recDevice *device = (recDevice *) ctx;
|
||||
device->removed = 1;
|
||||
device->deviceRef = NULL; // deviceRef was invalidated due to the remove
|
||||
#if SDL_HAPTIC_IOKIT
|
||||
MacHaptic_MaybeRemoveDevice(device->ffservice);
|
||||
#endif
|
||||
@@ -356,15 +364,33 @@ GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
JoystickAlreadyKnown(IOHIDDeviceRef ioHIDDeviceObject)
|
||||
{
|
||||
recDevice *i;
|
||||
for (i = gpDeviceList; i != NULL; i = i->pNext) {
|
||||
if (i->deviceRef == ioHIDDeviceObject) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef ioHIDDeviceObject)
|
||||
{
|
||||
recDevice *device;
|
||||
|
||||
if (res != kIOReturnSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
recDevice *device = (recDevice *) SDL_calloc(1, sizeof(recDevice));
|
||||
if (JoystickAlreadyKnown(ioHIDDeviceObject)) {
|
||||
return; /* IOKit sent us a duplicate. */
|
||||
}
|
||||
|
||||
device = (recDevice *) SDL_calloc(1, sizeof(recDevice));
|
||||
|
||||
if (!device) {
|
||||
SDL_OutOfMemory();
|
||||
@@ -378,7 +404,7 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
|
||||
|
||||
/* Get notified when this device is disconnected. */
|
||||
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
|
||||
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||
|
||||
/* Allocate an instance ID for this device */
|
||||
device->instance_id = ++s_joystick_instance_id;
|
||||
@@ -398,17 +424,13 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
|
||||
s_bDeviceAdded = SDL_TRUE;
|
||||
|
||||
/* Add device to the end of the list */
|
||||
if ( !gpDeviceList )
|
||||
{
|
||||
if ( !gpDeviceList ) {
|
||||
gpDeviceList = device;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
recDevice *curdevice;
|
||||
|
||||
curdevice = gpDeviceList;
|
||||
while ( curdevice->pNext )
|
||||
{
|
||||
while ( curdevice->pNext ) {
|
||||
curdevice = curdevice->pNext;
|
||||
}
|
||||
curdevice->pNext = device;
|
||||
@@ -420,25 +442,19 @@ ConfigHIDManager(CFArrayRef matchingArray)
|
||||
{
|
||||
CFRunLoopRef runloop = CFRunLoopGetCurrent();
|
||||
|
||||
/* Run in a custom RunLoop mode just while initializing,
|
||||
so we can detect sticks without messing with everything else. */
|
||||
CFStringRef tempRunLoopMode = CFSTR("SDLJoystickInit");
|
||||
|
||||
if (IOHIDManagerOpen(hidman, kIOHIDOptionsTypeNone) != kIOReturnSuccess) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
|
||||
IOHIDManagerScheduleWithRunLoop(hidman, runloop, tempRunLoopMode);
|
||||
IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
|
||||
IOHIDManagerScheduleWithRunLoop(hidman, runloop, SDL_JOYSTICK_RUNLOOP_MODE);
|
||||
|
||||
while (CFRunLoopRunInMode(tempRunLoopMode,0,TRUE)==kCFRunLoopRunHandledSource) {
|
||||
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
|
||||
/* no-op. Callback fires once per existing device. */
|
||||
}
|
||||
|
||||
/* Put this in the normal RunLoop mode now, for future hotplug events. */
|
||||
IOHIDManagerUnscheduleFromRunLoop(hidman, runloop, tempRunLoopMode);
|
||||
IOHIDManagerScheduleWithRunLoop(hidman, runloop, kCFRunLoopDefaultMode);
|
||||
/* future hotplug events will come through SDL_JOYSTICK_RUNLOOP_MODE now. */
|
||||
|
||||
return SDL_TRUE; /* good to go. */
|
||||
}
|
||||
@@ -593,12 +609,12 @@ SDL_SYS_JoystickDetect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return s_bDeviceAdded || s_bDeviceRemoved;
|
||||
// run this after the checks above so we don't set device->removed and delete the device before
|
||||
// SDL_SYS_JoystickUpdate can run to clean up the SDL_Joystick object that owns this device
|
||||
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
|
||||
/* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
@@ -630,7 +646,7 @@ SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
* The joystick to open is specified by the index field of the joystick.
|
||||
* The joystick to open is specified by the device index.
|
||||
* This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
* It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
@@ -656,7 +672,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
}
|
||||
|
||||
/* Function to query if the joystick is currently attached
|
||||
* It returns 1 if attached, 0 otherwise.
|
||||
* It returns SDL_TRUE if attached, SDL_FALSE otherwise.
|
||||
*/
|
||||
SDL_bool
|
||||
SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
|
||||
@@ -793,6 +809,7 @@ SDL_SYS_JoystickQuit(void)
|
||||
}
|
||||
|
||||
if (hidman) {
|
||||
IOHIDManagerUnscheduleFromRunLoop(hidman, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||
IOHIDManagerClose(hidman, kIOHIDOptionsTypeNone);
|
||||
CFRelease(hidman);
|
||||
hidman = NULL;
|
||||
|
||||
@@ -46,11 +46,6 @@ void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
@@ -66,7 +61,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_JOYSTICK_EMSCRIPTEN
|
||||
|
||||
#include <stdio.h> /* For the definition of NULL */
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_events.h"
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#endif
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_sysjoystick_c.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
static SDL_joylist_item * JoystickByIndex(int index);
|
||||
|
||||
static SDL_joylist_item *SDL_joylist = NULL;
|
||||
static SDL_joylist_item *SDL_joylist_tail = NULL;
|
||||
static int numjoysticks = 0;
|
||||
static int instance_counter = 0;
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_joylist_item *item;
|
||||
|
||||
if (JoystickByIndex(gamepadEvent->index) != NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
|
||||
if (item == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_zerop(item);
|
||||
item->index = gamepadEvent->index;
|
||||
|
||||
item->name = SDL_strdup(gamepadEvent->id);
|
||||
if ( item->name == NULL ) {
|
||||
SDL_free(item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
item->mapping = SDL_strdup(gamepadEvent->mapping);
|
||||
if ( item->mapping == NULL ) {
|
||||
SDL_free(item->name);
|
||||
SDL_free(item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
item->naxes = gamepadEvent->numAxes;
|
||||
item->nbuttons = gamepadEvent->numButtons;
|
||||
item->device_instance = instance_counter++;
|
||||
|
||||
item->timestamp = gamepadEvent->timestamp;
|
||||
|
||||
for( i = 0; i < item->naxes; i++) {
|
||||
item->axis[i] = gamepadEvent->axis[i];
|
||||
}
|
||||
|
||||
for( i = 0; i < item->nbuttons; i++) {
|
||||
item->analogButton[i] = gamepadEvent->analogButton[i];
|
||||
item->digitalButton[i] = gamepadEvent->digitalButton[i];
|
||||
}
|
||||
|
||||
if (SDL_joylist_tail == NULL) {
|
||||
SDL_joylist = SDL_joylist_tail = item;
|
||||
} else {
|
||||
SDL_joylist_tail->next = item;
|
||||
SDL_joylist_tail = item;
|
||||
}
|
||||
|
||||
++numjoysticks;
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Number of joysticks is %d", numjoysticks);
|
||||
#endif
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = numjoysticks - 1;
|
||||
if ( (SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Added joystick with index %d", item->index);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
|
||||
{
|
||||
SDL_joylist_item *item = SDL_joylist;
|
||||
SDL_joylist_item *prev = NULL;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
while (item != NULL) {
|
||||
if (item->index == gamepadEvent->index) {
|
||||
break;
|
||||
}
|
||||
prev = item;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
if (item == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (item->joystick) {
|
||||
item->joystick->hwdata = NULL;
|
||||
}
|
||||
|
||||
if (prev != NULL) {
|
||||
prev->next = item->next;
|
||||
} else {
|
||||
SDL_assert(SDL_joylist == item);
|
||||
SDL_joylist = item->next;
|
||||
}
|
||||
if (item == SDL_joylist_tail) {
|
||||
SDL_joylist_tail = prev;
|
||||
}
|
||||
|
||||
/* Need to decrement the joystick count before we post the event */
|
||||
--numjoysticks;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = item->device_instance;
|
||||
if ( (SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
#ifdef DEBUG_JOYSTICK
|
||||
SDL_Log("Removed joystick with id %d", item->device_instance);
|
||||
#endif
|
||||
SDL_free(item->name);
|
||||
SDL_free(item->mapping);
|
||||
SDL_free(item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
int retval, i, numjs;
|
||||
EmscriptenGamepadEvent gamepadState;
|
||||
|
||||
numjoysticks = 0;
|
||||
numjs = emscripten_get_num_gamepads();
|
||||
|
||||
/* Check if gamepad is supported by browser */
|
||||
if (numjs == EMSCRIPTEN_RESULT_NOT_SUPPORTED) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* handle already connected gamepads */
|
||||
if (numjs > 0) {
|
||||
for(i = 0; i < numjs; i++) {
|
||||
retval = emscripten_get_gamepad_status(i, &gamepadState);
|
||||
if (retval == EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
Emscripten_JoyStickConnected(EMSCRIPTEN_EVENT_GAMEPADCONNECTED,
|
||||
&gamepadState,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval = emscripten_set_gamepadconnected_callback(NULL,
|
||||
0,
|
||||
Emscripten_JoyStickConnected);
|
||||
|
||||
if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
SDL_SYS_JoystickQuit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = emscripten_set_gamepaddisconnected_callback(NULL,
|
||||
0,
|
||||
Emscripten_JoyStickDisconnected);
|
||||
if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
SDL_SYS_JoystickQuit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns item matching given SDL device index. */
|
||||
static SDL_joylist_item *
|
||||
JoystickByDeviceIndex(int device_index)
|
||||
{
|
||||
SDL_joylist_item *item = SDL_joylist;
|
||||
|
||||
while (0 < device_index) {
|
||||
--device_index;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/* Returns item matching given HTML gamepad index. */
|
||||
static SDL_joylist_item *
|
||||
JoystickByIndex(int index)
|
||||
{
|
||||
SDL_joylist_item *item = SDL_joylist;
|
||||
|
||||
if (index < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (item != NULL) {
|
||||
if (item->index == index) {
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return JoystickByDeviceIndex(device_index)->name;
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return JoystickByDeviceIndex(device_index)->device_instance;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
|
||||
|
||||
if (item == NULL ) {
|
||||
return SDL_SetError("No such device");
|
||||
}
|
||||
|
||||
if (item->joystick != NULL) {
|
||||
return SDL_SetError("Joystick already opened");
|
||||
}
|
||||
|
||||
joystick->instance_id = item->device_instance;
|
||||
joystick->hwdata = (struct joystick_hwdata *) item;
|
||||
item->joystick = joystick;
|
||||
|
||||
/* HTML5 Gamepad API doesn't say anything about these */
|
||||
joystick->nhats = 0;
|
||||
joystick->nballs = 0;
|
||||
|
||||
joystick->nbuttons = item->nbuttons;
|
||||
joystick->naxes = item->naxes;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return !joystick->closed && (joystick->hwdata != NULL);
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepadState;
|
||||
SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
|
||||
int i, result, buttonState;
|
||||
|
||||
if (item) {
|
||||
result = emscripten_get_gamepad_status(item->index, &gamepadState);
|
||||
if( result == EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
if(gamepadState.timestamp == 0 || gamepadState.timestamp != item->timestamp) {
|
||||
for(i = 0; i < item->nbuttons; i++) {
|
||||
if(item->digitalButton[i] != gamepadState.digitalButton[i]) {
|
||||
buttonState = gamepadState.digitalButton[i]? SDL_PRESSED: SDL_RELEASED;
|
||||
SDL_PrivateJoystickButton(item->joystick, i, buttonState);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < item->naxes; i++) {
|
||||
if(item->axis[i] != gamepadState.axis[i]) {
|
||||
// do we need to do conversion?
|
||||
SDL_PrivateJoystickAxis(item->joystick, i,
|
||||
(Sint16) (32767.*gamepadState.axis[i]));
|
||||
}
|
||||
}
|
||||
|
||||
item->timestamp = gamepadState.timestamp;
|
||||
for( i = 0; i < item->naxes; i++) {
|
||||
item->axis[i] = gamepadState.axis[i];
|
||||
}
|
||||
|
||||
for( i = 0; i < item->nbuttons; i++) {
|
||||
item->analogButton[i] = gamepadState.analogButton[i];
|
||||
item->digitalButton[i] = gamepadState.digitalButton[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata) {
|
||||
((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
joystick->closed = 1;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
SDL_joylist_item *item = NULL;
|
||||
SDL_joylist_item *next = NULL;
|
||||
|
||||
for (item = SDL_joylist; item; item = next) {
|
||||
next = item->next;
|
||||
SDL_free(item->mapping);
|
||||
SDL_free(item->name);
|
||||
SDL_free(item);
|
||||
}
|
||||
|
||||
SDL_joylist = SDL_joylist_tail = NULL;
|
||||
|
||||
numjoysticks = 0;
|
||||
instance_counter = 0;
|
||||
|
||||
emscripten_set_gamepadconnected_callback(NULL, 0, NULL);
|
||||
emscripten_set_gamepaddisconnected_callback(NULL, 0, NULL);
|
||||
}
|
||||
|
||||
SDL_JoystickGUID
|
||||
SDL_SYS_JoystickGetDeviceGUID(int device_index)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex(device_index);
|
||||
SDL_zero(guid);
|
||||
SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID
|
||||
SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero(guid);
|
||||
SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
|
||||
return guid;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_EMSCRIPTEN */
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_JOYSTICK_EMSCRIPTEN
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
/* A linked list of available joysticks */
|
||||
typedef struct SDL_joylist_item
|
||||
{
|
||||
int index;
|
||||
char *name;
|
||||
char *mapping;
|
||||
SDL_JoystickID device_instance;
|
||||
SDL_Joystick *joystick;
|
||||
int nbuttons;
|
||||
int naxes;
|
||||
double timestamp;
|
||||
double axis[64];
|
||||
double analogButton[64];
|
||||
EM_BOOL digitalButton[64];
|
||||
|
||||
struct SDL_joylist_item *next;
|
||||
} SDL_joylist_item;
|
||||
|
||||
typedef SDL_joylist_item joystick_hwdata;
|
||||
|
||||
#endif /* SDL_JOYSTICK_EMSCRIPTEN */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -53,8 +53,7 @@ extern "C"
|
||||
static int SDL_SYS_numjoysticks = 0;
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int SDL_SYS_JoystickInit(void)
|
||||
@@ -94,11 +93,6 @@ extern "C"
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
@@ -112,7 +106,7 @@ extern "C"
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#import "SDLUIAccelerationDelegate.h"
|
||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#import "../../../include/SDL_config_iphoneos.h"
|
||||
|
||||
static SDLUIAccelerationDelegate *sharedDelegate=nil;
|
||||
|
||||
@implementation SDLUIAccelerationDelegate
|
||||
|
||||
/*
|
||||
Returns a shared instance of the SDLUIAccelerationDelegate, creating the shared delegate if it doesn't exist yet.
|
||||
*/
|
||||
+(SDLUIAccelerationDelegate *)sharedDelegate {
|
||||
if (sharedDelegate == nil) {
|
||||
sharedDelegate = [[SDLUIAccelerationDelegate alloc] init];
|
||||
}
|
||||
return sharedDelegate;
|
||||
}
|
||||
/*
|
||||
UIAccelerometerDelegate delegate method. Invoked by the UIAccelerometer instance when it has new data for us.
|
||||
We just take the data and mark that we have new data available so that the joystick system will pump it to the
|
||||
events system when SDL_SYS_JoystickUpdate is called.
|
||||
*/
|
||||
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
|
||||
|
||||
x = acceleration.x;
|
||||
y = acceleration.y;
|
||||
z = acceleration.z;
|
||||
|
||||
hasNewData = YES;
|
||||
}
|
||||
/*
|
||||
getLastOrientation -- put last obtained accelerometer data into Sint16 array
|
||||
|
||||
Called from the joystick system when it needs the accelerometer data.
|
||||
Function grabs the last data sent to the accelerometer and converts it
|
||||
from floating point to Sint16, which is what the joystick system expects.
|
||||
|
||||
To do the conversion, the data is first clamped onto the interval
|
||||
[-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
|
||||
by MAX_SINT16 so that it is mapped to the full range of an Sint16.
|
||||
|
||||
You can customize the clamped range of this function by modifying the
|
||||
SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
|
||||
|
||||
Once converted to Sint16, the accelerometer data no longer has coherent units.
|
||||
You can convert the data back to units of g-force by multiplying it
|
||||
in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
|
||||
*/
|
||||
-(void)getLastOrientation:(Sint16 *)data {
|
||||
|
||||
#define MAX_SINT16 0x7FFF
|
||||
|
||||
/* clamp the data */
|
||||
if (x > SDL_IPHONE_MAX_GFORCE) x = SDL_IPHONE_MAX_GFORCE;
|
||||
else if (x < -SDL_IPHONE_MAX_GFORCE) x = -SDL_IPHONE_MAX_GFORCE;
|
||||
if (y > SDL_IPHONE_MAX_GFORCE) y = SDL_IPHONE_MAX_GFORCE;
|
||||
else if (y < -SDL_IPHONE_MAX_GFORCE) y = -SDL_IPHONE_MAX_GFORCE;
|
||||
if (z > SDL_IPHONE_MAX_GFORCE) z = SDL_IPHONE_MAX_GFORCE;
|
||||
else if (z < -SDL_IPHONE_MAX_GFORCE) z = -SDL_IPHONE_MAX_GFORCE;
|
||||
|
||||
/* pass in data mapped to range of SInt16 */
|
||||
data[0] = (x / SDL_IPHONE_MAX_GFORCE) * MAX_SINT16;
|
||||
data[1] = (y / SDL_IPHONE_MAX_GFORCE) * MAX_SINT16;
|
||||
data[2] = (z / SDL_IPHONE_MAX_GFORCE) * MAX_SINT16;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize SDLUIAccelerationDelegate. Since we don't have any data yet,
|
||||
just set our last received data to zero, and indicate we don't have any;
|
||||
*/
|
||||
-(id)init {
|
||||
self = [super init];
|
||||
x = y = z = 0.0;
|
||||
hasNewData = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc {
|
||||
sharedDelegate = nil;
|
||||
[self shutdown];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/*
|
||||
Lets our delegate start receiving accelerometer updates.
|
||||
*/
|
||||
-(void)startup {
|
||||
[UIAccelerometer sharedAccelerometer].delegate = self;
|
||||
isRunning = YES;
|
||||
}
|
||||
/*
|
||||
Stops our delegate from receiving accelerometer updates.
|
||||
*/
|
||||
-(void)shutdown {
|
||||
if ([UIAccelerometer sharedAccelerometer].delegate == self) {
|
||||
[UIAccelerometer sharedAccelerometer].delegate = nil;
|
||||
}
|
||||
isRunning = NO;
|
||||
}
|
||||
/*
|
||||
Our we currently receiving accelerometer updates?
|
||||
*/
|
||||
-(BOOL)isRunning {
|
||||
return isRunning;
|
||||
}
|
||||
/*
|
||||
Do we have any data that hasn't been pumped into SDL's event system?
|
||||
*/
|
||||
-(BOOL)hasNewData {
|
||||
return hasNewData;
|
||||
}
|
||||
/*
|
||||
When the joystick system grabs the new data, it sets this to NO.
|
||||
*/
|
||||
-(void)setHasNewData:(BOOL)value {
|
||||
hasNewData = value;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -23,15 +23,21 @@
|
||||
/* This is the iOS implementation of the SDL joystick API */
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#import "SDLUIAccelerationDelegate.h"
|
||||
|
||||
const char *accelerometerName = "iPhone accelerometer";
|
||||
#import <CoreMotion/CoreMotion.h>
|
||||
|
||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#import "SDL_config_iphoneos.h"
|
||||
|
||||
const char *accelerometerName = "iOS accelerometer";
|
||||
|
||||
static CMMotionManager *motionManager = nil;
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
@@ -49,11 +55,6 @@ void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
@@ -68,7 +69,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
@@ -79,7 +80,15 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
joystick->nhats = 0;
|
||||
joystick->nballs = 0;
|
||||
joystick->nbuttons = 0;
|
||||
[[SDLUIAccelerationDelegate sharedDelegate] startup];
|
||||
|
||||
if (motionManager == nil) {
|
||||
motionManager = [[CMMotionManager alloc] init];
|
||||
}
|
||||
|
||||
/* Shorter times between updates can significantly increase CPU usage. */
|
||||
motionManager.accelerometerUpdateInterval = 0.1;
|
||||
[motionManager startAccelerometerUpdates];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -89,6 +98,45 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
const float maxgforce = SDL_IPHONE_MAX_GFORCE;
|
||||
const SInt16 maxsint16 = 0x7FFF;
|
||||
CMAcceleration accel;
|
||||
|
||||
if (!motionManager.accelerometerActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
accel = [[motionManager accelerometerData] acceleration];
|
||||
|
||||
/*
|
||||
Convert accelerometer data from floating point to Sint16, which is what
|
||||
the joystick system expects.
|
||||
|
||||
To do the conversion, the data is first clamped onto the interval
|
||||
[-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
|
||||
by MAX_SINT16 so that it is mapped to the full range of an Sint16.
|
||||
|
||||
You can customize the clamped range of this function by modifying the
|
||||
SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
|
||||
|
||||
Once converted to Sint16, the accelerometer data no longer has coherent
|
||||
units. You can convert the data back to units of g-force by multiplying
|
||||
it in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
|
||||
*/
|
||||
|
||||
/* clamp the data */
|
||||
accel.x = SDL_min(SDL_max(accel.x, -maxgforce), maxgforce);
|
||||
accel.y = SDL_min(SDL_max(accel.y, -maxgforce), maxgforce);
|
||||
accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
|
||||
|
||||
/* pass in data mapped to range of SInt16 */
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
@@ -97,37 +145,25 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
|
||||
Sint16 orientation[3];
|
||||
|
||||
if ([[SDLUIAccelerationDelegate sharedDelegate] hasNewData]) {
|
||||
|
||||
[[SDLUIAccelerationDelegate sharedDelegate] getLastOrientation: orientation];
|
||||
[[SDLUIAccelerationDelegate sharedDelegate] setHasNewData: NO];
|
||||
|
||||
SDL_PrivateJoystickAxis(joystick, 0, orientation[0]);
|
||||
SDL_PrivateJoystickAxis(joystick, 1, -orientation[1]);
|
||||
SDL_PrivateJoystickAxis(joystick, 2, orientation[2]);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
SDL_SYS_AccelerometerUpdate(joystick);
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
if ([[SDLUIAccelerationDelegate sharedDelegate] isRunning]) {
|
||||
[[SDLUIAccelerationDelegate sharedDelegate] shutdown];
|
||||
}
|
||||
SDL_SetError("No joystick open with that index");
|
||||
[motionManager stopAccelerometerUpdates];
|
||||
joystick->closed = 1;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
if (motionManager != nil) {
|
||||
[motionManager release];
|
||||
motionManager = nil;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
|
||||
@@ -142,13 +142,15 @@ IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *gui
|
||||
#if SDL_USE_LIBUDEV
|
||||
void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
|
||||
{
|
||||
if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
|
||||
if (devpath == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch( udev_type )
|
||||
{
|
||||
|
||||
switch (udev_type) {
|
||||
case SDL_UDEV_DEVICEADDED:
|
||||
if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
|
||||
return;
|
||||
}
|
||||
MaybeAddDevice(devpath);
|
||||
break;
|
||||
|
||||
@@ -335,13 +337,12 @@ JoystickInitWithoutUdev(void)
|
||||
static int
|
||||
JoystickInitWithUdev(void)
|
||||
{
|
||||
|
||||
if (SDL_UDEV_Init() < 0) {
|
||||
return SDL_SetError("Could not initialize UDEV");
|
||||
}
|
||||
|
||||
/* Set up the udev callback */
|
||||
if ( SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
|
||||
if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("Could not set up joystick <-> udev callback");
|
||||
}
|
||||
@@ -392,15 +393,6 @@ void SDL_SYS_JoystickDetect()
|
||||
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
#if SDL_USE_LIBUDEV
|
||||
return SDL_TRUE;
|
||||
#endif
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static SDL_joylist_item *
|
||||
JoystickByDevIndex(int device_index)
|
||||
{
|
||||
@@ -574,7 +566,7 @@ ConfigJoystick(SDL_Joystick * joystick, int fd)
|
||||
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
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_JOYSTICK_PSP
|
||||
|
||||
/* This is the PSP implementation of the SDL joystick API */
|
||||
#include <pspctrl.h>
|
||||
@@ -97,16 +100,13 @@ int JoystickUpdate(void *data)
|
||||
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
* It should return number of joysticks, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* SDL_numjoysticks = 1; */
|
||||
|
||||
/* Setup input */
|
||||
sceCtrlSetSamplingCycle(0);
|
||||
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
|
||||
@@ -141,11 +141,6 @@ void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
@@ -169,7 +164,7 @@ const char *SDL_SYS_JoystickName(int index)
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
@@ -187,12 +182,12 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
|
||||
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
|
||||
{
|
||||
int i;
|
||||
@@ -270,5 +265,7 @@ SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
return guid;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_PSP */
|
||||
|
||||
/* vim: ts=4 sw=4
|
||||
*/
|
||||
|
||||
@@ -30,9 +30,9 @@ def write_controllers():
|
||||
for entry in sorted(controllers, key=lambda entry: entry[2]):
|
||||
line = "".join(entry) + "\n"
|
||||
if not line.endswith(",\n") and not line.endswith("*/\n"):
|
||||
print "Warning: '%s' is missing a comma at the end of the line" % (line)
|
||||
print("Warning: '%s' is missing a comma at the end of the line" % (line))
|
||||
if (entry[1] in controller_guids):
|
||||
print "Warning: entry '%s' is duplicate of entry '%s'" % (entry[2], controller_guids[entry[1]][2])
|
||||
print("Warning: entry '%s' is duplicate of entry '%s'" % (entry[2], controller_guids[entry[1]][2]))
|
||||
controller_guids[entry[1]] = entry
|
||||
|
||||
output.write(line)
|
||||
@@ -40,15 +40,17 @@ def write_controllers():
|
||||
controller_guids = {}
|
||||
|
||||
for line in input:
|
||||
if ( parsing_controllers ):
|
||||
if (parsing_controllers):
|
||||
if (line.startswith("{")):
|
||||
output.write(line)
|
||||
elif (line.startswith("#endif")):
|
||||
elif (line.startswith(" NULL")):
|
||||
parsing_controllers = False
|
||||
write_controllers()
|
||||
output.write(line)
|
||||
elif (line.startswith("#")):
|
||||
print "Parsing " + line.strip()
|
||||
elif (line.startswith("#if")):
|
||||
print("Parsing " + line.strip())
|
||||
output.write(line)
|
||||
elif (line.startswith("#endif")):
|
||||
write_controllers()
|
||||
output.write(line)
|
||||
else:
|
||||
@@ -60,4 +62,4 @@ for line in input:
|
||||
output.write(line)
|
||||
|
||||
output.close()
|
||||
print "Finished writing %s.new" % filename
|
||||
print("Finished writing %s.new" % filename)
|
||||
|
||||
@@ -0,0 +1,900 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_sysjoystick.h"
|
||||
#include "SDL_windowsjoystick_c.h"
|
||||
#include "SDL_dinputjoystick_c.h"
|
||||
#include "SDL_xinputjoystick_c.h"
|
||||
|
||||
|
||||
#if SDL_JOYSTICK_DINPUT
|
||||
|
||||
#ifndef DIDFT_OPTIONAL
|
||||
#define DIDFT_OPTIONAL 0x80000000
|
||||
#endif
|
||||
|
||||
#define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
|
||||
#define AXIS_MIN -32768 /* minimum value for axis coordinate */
|
||||
#define AXIS_MAX 32767 /* maximum value for axis coordinate */
|
||||
#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
|
||||
|
||||
/* external variables referenced. */
|
||||
extern HWND SDL_HelperWindow;
|
||||
|
||||
/* local variables */
|
||||
static SDL_bool coinitialized = SDL_FALSE;
|
||||
static LPDIRECTINPUT8 dinput = NULL;
|
||||
static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
|
||||
static UINT SDL_RawDevListCount = 0;
|
||||
|
||||
/* Taken from Wine - Thanks! */
|
||||
static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
|
||||
{ &GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_Slider, DIJOFS_SLIDER(0), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_Slider, DIJOFS_SLIDER(1), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_POV, DIJOFS_POV(0), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_POV, DIJOFS_POV(1), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_POV, DIJOFS_POV(2), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_POV, DIJOFS_POV(3), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(0), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(1), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(2), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(3), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(4), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(5), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(6), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(7), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(8), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(9), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(10), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(11), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(12), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(13), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(14), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(15), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(16), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(17), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(18), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(19), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(20), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(21), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(22), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(23), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(24), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(25), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(26), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(27), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(28), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(29), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(30), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(31), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(32), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(33), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(34), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(35), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(36), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(37), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(38), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(39), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(40), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(41), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(42), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(43), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(44), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(45), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(46), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(47), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(48), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(49), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(50), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(51), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(52), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(53), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(54), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(55), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(56), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(57), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(58), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(59), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(60), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(61), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(62), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(63), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(64), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(65), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(66), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(67), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(68), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(69), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(70), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(71), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(72), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(73), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(74), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(75), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(76), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(77), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(78), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(79), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(80), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(81), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(82), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(83), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(84), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(85), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(86), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(87), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(88), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(89), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(90), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(91), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(92), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(93), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(94), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(95), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(96), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(97), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(98), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(99), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(100), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(101), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(102), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(103), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(104), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(105), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(106), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(107), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(108), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(109), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(110), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(111), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(112), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(113), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(114), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(115), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(116), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(117), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(118), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(119), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(120), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(121), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(122), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(123), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(124), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(125), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(126), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ NULL, DIJOFS_BUTTON(127), DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
{ &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
|
||||
};
|
||||
|
||||
const DIDATAFORMAT c_dfDIJoystick2 = {
|
||||
sizeof(DIDATAFORMAT),
|
||||
sizeof(DIOBJECTDATAFORMAT),
|
||||
DIDF_ABSAXIS,
|
||||
sizeof(DIJOYSTATE2),
|
||||
SDL_arraysize(dfDIJoystick2),
|
||||
dfDIJoystick2
|
||||
};
|
||||
|
||||
/* Convert a DirectInput return code to a text message */
|
||||
static int
|
||||
SetDIerror(const char *function, HRESULT code)
|
||||
{
|
||||
/*
|
||||
return SDL_SetError("%s() [%s]: %s", function,
|
||||
DXGetErrorString9A(code), DXGetErrorDescription9A(code));
|
||||
*/
|
||||
return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
|
||||
{
|
||||
static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
|
||||
static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
|
||||
static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
|
||||
|
||||
static const GUID *s_XInputProductGUID[] = {
|
||||
&IID_ValveStreamingGamepad,
|
||||
&IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
|
||||
&IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
|
||||
};
|
||||
|
||||
size_t iDevice;
|
||||
UINT i;
|
||||
|
||||
if (!SDL_XINPUT_Enabled()) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Check for well known XInput device GUIDs */
|
||||
/* This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. */
|
||||
for (iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice) {
|
||||
if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go through RAWINPUT (WinXP and later) to find HID devices. */
|
||||
/* Cache this if we end up using it. */
|
||||
if (SDL_RawDevList == NULL) {
|
||||
if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
|
||||
return SDL_FALSE; /* oh well. */
|
||||
}
|
||||
|
||||
SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
|
||||
if (SDL_RawDevList == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
|
||||
SDL_free(SDL_RawDevList);
|
||||
SDL_RawDevList = NULL;
|
||||
return SDL_FALSE; /* oh well. */
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SDL_RawDevListCount; i++) {
|
||||
RID_DEVICE_INFO rdi;
|
||||
char devName[128];
|
||||
UINT rdiSize = sizeof(rdi);
|
||||
UINT nameSize = SDL_arraysize(devName);
|
||||
|
||||
rdi.cbSize = sizeof(rdi);
|
||||
if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
|
||||
(GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
|
||||
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
|
||||
(GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
|
||||
(SDL_strstr(devName, "IG_") != NULL)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_DINPUT_JoystickInit(void)
|
||||
{
|
||||
HRESULT result;
|
||||
HINSTANCE instance;
|
||||
|
||||
result = WIN_CoInitialize();
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("CoInitialize", result);
|
||||
}
|
||||
|
||||
coinitialized = SDL_TRUE;
|
||||
|
||||
result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IDirectInput8, (LPVOID)&dinput);
|
||||
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("CoCreateInstance", result);
|
||||
}
|
||||
|
||||
/* Because we used CoCreateInstance, we need to Initialize it, first. */
|
||||
instance = GetModuleHandle(NULL);
|
||||
if (instance == NULL) {
|
||||
return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError());
|
||||
}
|
||||
result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
|
||||
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInput::Initialize", result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function for direct input, gets called for each connected joystick */
|
||||
static BOOL CALLBACK
|
||||
EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
|
||||
{
|
||||
JoyStick_DeviceData *pNewJoystick;
|
||||
JoyStick_DeviceData *pPrevJoystick = NULL;
|
||||
|
||||
if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
|
||||
return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
|
||||
}
|
||||
|
||||
pNewJoystick = *(JoyStick_DeviceData **)pContext;
|
||||
while (pNewJoystick) {
|
||||
if (!SDL_memcmp(&pNewJoystick->dxdevice.guidInstance, &pdidInstance->guidInstance, sizeof(pNewJoystick->dxdevice.guidInstance))) {
|
||||
/* if we are replacing the front of the list then update it */
|
||||
if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
|
||||
*(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
|
||||
} else if (pPrevJoystick) {
|
||||
pPrevJoystick->pNext = pNewJoystick->pNext;
|
||||
}
|
||||
|
||||
pNewJoystick->pNext = SYS_Joystick;
|
||||
SYS_Joystick = pNewJoystick;
|
||||
|
||||
return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
|
||||
}
|
||||
|
||||
pPrevJoystick = pNewJoystick;
|
||||
pNewJoystick = pNewJoystick->pNext;
|
||||
}
|
||||
|
||||
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
|
||||
if (!pNewJoystick) {
|
||||
return DIENUM_CONTINUE; /* better luck next time? */
|
||||
}
|
||||
|
||||
SDL_zerop(pNewJoystick);
|
||||
pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
|
||||
if (!pNewJoystick->joystickname) {
|
||||
SDL_free(pNewJoystick);
|
||||
return DIENUM_CONTINUE; /* better luck next time? */
|
||||
}
|
||||
|
||||
SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
|
||||
sizeof(DIDEVICEINSTANCE));
|
||||
|
||||
SDL_memcpy(&pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid));
|
||||
SDL_SYS_AddJoystickDevice(pNewJoystick);
|
||||
|
||||
return DIENUM_CONTINUE; /* get next device, please */
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
|
||||
{
|
||||
IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY);
|
||||
|
||||
if (SDL_RawDevList) {
|
||||
SDL_free(SDL_RawDevList); /* in case we used this in DirectInput detection */
|
||||
SDL_RawDevList = NULL;
|
||||
}
|
||||
SDL_RawDevListCount = 0;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK
|
||||
EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
|
||||
{
|
||||
SDL_Joystick *joystick = (SDL_Joystick *)pvRef;
|
||||
HRESULT result;
|
||||
input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
|
||||
|
||||
if (dev->dwType & DIDFT_BUTTON) {
|
||||
in->type = BUTTON;
|
||||
in->num = joystick->nbuttons;
|
||||
in->ofs = DIJOFS_BUTTON(in->num);
|
||||
joystick->nbuttons++;
|
||||
} else if (dev->dwType & DIDFT_POV) {
|
||||
in->type = HAT;
|
||||
in->num = joystick->nhats;
|
||||
in->ofs = DIJOFS_POV(in->num);
|
||||
joystick->nhats++;
|
||||
} else if (dev->dwType & DIDFT_AXIS) {
|
||||
DIPROPRANGE diprg;
|
||||
DIPROPDWORD dilong;
|
||||
|
||||
in->type = AXIS;
|
||||
in->num = joystick->naxes;
|
||||
if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
|
||||
in->ofs = DIJOFS_X;
|
||||
else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
|
||||
in->ofs = DIJOFS_Y;
|
||||
else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
|
||||
in->ofs = DIJOFS_Z;
|
||||
else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
|
||||
in->ofs = DIJOFS_RX;
|
||||
else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
|
||||
in->ofs = DIJOFS_RY;
|
||||
else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
|
||||
in->ofs = DIJOFS_RZ;
|
||||
else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
|
||||
in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
|
||||
++joystick->hwdata->NumSliders;
|
||||
} else {
|
||||
return DIENUM_CONTINUE; /* not an axis we can grok */
|
||||
}
|
||||
|
||||
diprg.diph.dwSize = sizeof(diprg);
|
||||
diprg.diph.dwHeaderSize = sizeof(diprg.diph);
|
||||
diprg.diph.dwObj = dev->dwType;
|
||||
diprg.diph.dwHow = DIPH_BYID;
|
||||
diprg.lMin = AXIS_MIN;
|
||||
diprg.lMax = AXIS_MAX;
|
||||
|
||||
result =
|
||||
IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
|
||||
DIPROP_RANGE, &diprg.diph);
|
||||
if (FAILED(result)) {
|
||||
return DIENUM_CONTINUE; /* don't use this axis */
|
||||
}
|
||||
|
||||
/* Set dead zone to 0. */
|
||||
dilong.diph.dwSize = sizeof(dilong);
|
||||
dilong.diph.dwHeaderSize = sizeof(dilong.diph);
|
||||
dilong.diph.dwObj = dev->dwType;
|
||||
dilong.diph.dwHow = DIPH_BYID;
|
||||
dilong.dwData = 0;
|
||||
result =
|
||||
IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
|
||||
DIPROP_DEADZONE, &dilong.diph);
|
||||
if (FAILED(result)) {
|
||||
return DIENUM_CONTINUE; /* don't use this axis */
|
||||
}
|
||||
|
||||
joystick->naxes++;
|
||||
} else {
|
||||
/* not supported at this time */
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
joystick->hwdata->NumInputs++;
|
||||
|
||||
if (joystick->hwdata->NumInputs == MAX_INPUTS) {
|
||||
return DIENUM_STOP; /* too many */
|
||||
}
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
/* Sort using the data offset into the DInput struct.
|
||||
* This gives a reasonable ordering for the inputs.
|
||||
*/
|
||||
static int
|
||||
SortDevFunc(const void *a, const void *b)
|
||||
{
|
||||
const input_t *inputA = (const input_t*)a;
|
||||
const input_t *inputB = (const input_t*)b;
|
||||
|
||||
if (inputA->ofs < inputB->ofs)
|
||||
return -1;
|
||||
if (inputA->ofs > inputB->ofs)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sort the input objects and recalculate the indices for each input. */
|
||||
static void
|
||||
SortDevObjects(SDL_Joystick *joystick)
|
||||
{
|
||||
input_t *inputs = joystick->hwdata->Inputs;
|
||||
int nButtons = 0;
|
||||
int nHats = 0;
|
||||
int nAxis = 0;
|
||||
int n;
|
||||
|
||||
SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc);
|
||||
|
||||
for (n = 0; n < joystick->hwdata->NumInputs; n++) {
|
||||
switch (inputs[n].type) {
|
||||
case BUTTON:
|
||||
inputs[n].num = nButtons;
|
||||
nButtons++;
|
||||
break;
|
||||
|
||||
case HAT:
|
||||
inputs[n].num = nHats;
|
||||
nHats++;
|
||||
break;
|
||||
|
||||
case AXIS:
|
||||
inputs[n].num = nAxis;
|
||||
nAxis++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
|
||||
{
|
||||
HRESULT result;
|
||||
LPDIRECTINPUTDEVICE8 device;
|
||||
DIPROPDWORD dipdw;
|
||||
|
||||
joystick->hwdata->buffered = SDL_TRUE;
|
||||
joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
|
||||
|
||||
SDL_zero(dipdw);
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
|
||||
result =
|
||||
IDirectInput8_CreateDevice(dinput,
|
||||
&(joystickdevice->dxdevice.guidInstance), &device, NULL);
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInput::CreateDevice", result);
|
||||
}
|
||||
|
||||
/* Now get the IDirectInputDevice8 interface, instead. */
|
||||
result = IDirectInputDevice8_QueryInterface(device,
|
||||
&IID_IDirectInputDevice8,
|
||||
(LPVOID *)& joystick->
|
||||
hwdata->InputDevice);
|
||||
/* We are done with this object. Use the stored one from now on. */
|
||||
IDirectInputDevice8_Release(device);
|
||||
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::QueryInterface", result);
|
||||
}
|
||||
|
||||
/* Acquire shared access. Exclusive access is required for forces,
|
||||
* though. */
|
||||
result =
|
||||
IDirectInputDevice8_SetCooperativeLevel(joystick->hwdata->
|
||||
InputDevice, SDL_HelperWindow,
|
||||
DISCL_EXCLUSIVE |
|
||||
DISCL_BACKGROUND);
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::SetCooperativeLevel", result);
|
||||
}
|
||||
|
||||
/* Use the extended data structure: DIJOYSTATE2. */
|
||||
result =
|
||||
IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
|
||||
&c_dfDIJoystick2);
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
|
||||
}
|
||||
|
||||
/* Get device capabilities */
|
||||
result =
|
||||
IDirectInputDevice8_GetCapabilities(joystick->hwdata->InputDevice,
|
||||
&joystick->hwdata->Capabilities);
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::GetCapabilities", result);
|
||||
}
|
||||
|
||||
/* Force capable? */
|
||||
if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
|
||||
|
||||
result = IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::Acquire", result);
|
||||
}
|
||||
|
||||
/* reset all actuators. */
|
||||
result =
|
||||
IDirectInputDevice8_SendForceFeedbackCommand(joystick->hwdata->
|
||||
InputDevice,
|
||||
DISFFC_RESET);
|
||||
|
||||
/* Not necessarily supported, ignore if not supported.
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::SendForceFeedbackCommand", result);
|
||||
}
|
||||
*/
|
||||
|
||||
result = IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
|
||||
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::Unacquire", result);
|
||||
}
|
||||
|
||||
/* Turn on auto-centering for a ForceFeedback device (until told
|
||||
* otherwise). */
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = DIPROPAUTOCENTER_ON;
|
||||
|
||||
result =
|
||||
IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
|
||||
DIPROP_AUTOCENTER, &dipdw.diph);
|
||||
|
||||
/* Not necessarily supported, ignore if not supported.
|
||||
if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::SetProperty", result);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* What buttons and axes does it have? */
|
||||
IDirectInputDevice8_EnumObjects(joystick->hwdata->InputDevice,
|
||||
EnumDevObjectsCallback, joystick,
|
||||
DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
|
||||
|
||||
/* Reorder the input objects. Some devices do not report the X axis as
|
||||
* the first axis, for example. */
|
||||
SortDevObjects(joystick);
|
||||
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = INPUT_QSIZE;
|
||||
|
||||
/* Set the buffer size */
|
||||
result =
|
||||
IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice,
|
||||
DIPROP_BUFFERSIZE, &dipdw.diph);
|
||||
|
||||
if (result == DI_POLLEDDEVICE) {
|
||||
/* This device doesn't support buffering, so we're forced
|
||||
* to use less reliable polling. */
|
||||
joystick->hwdata->buffered = SDL_FALSE;
|
||||
} else if (FAILED(result)) {
|
||||
return SetDIerror("IDirectInputDevice8::SetProperty", result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint8
|
||||
TranslatePOV(DWORD value)
|
||||
{
|
||||
const int HAT_VALS[] = {
|
||||
SDL_HAT_UP,
|
||||
SDL_HAT_UP | SDL_HAT_RIGHT,
|
||||
SDL_HAT_RIGHT,
|
||||
SDL_HAT_DOWN | SDL_HAT_RIGHT,
|
||||
SDL_HAT_DOWN,
|
||||
SDL_HAT_DOWN | SDL_HAT_LEFT,
|
||||
SDL_HAT_LEFT,
|
||||
SDL_HAT_UP | SDL_HAT_LEFT
|
||||
};
|
||||
|
||||
if (LOWORD(value) == 0xFFFF)
|
||||
return SDL_HAT_CENTERED;
|
||||
|
||||
/* Round the value up: */
|
||||
value += 4500 / 2;
|
||||
value %= 36000;
|
||||
value /= 4500;
|
||||
|
||||
if (value >= 8)
|
||||
return SDL_HAT_CENTERED; /* shouldn't happen */
|
||||
|
||||
return HAT_VALS[value];
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateDINPUTJoystickState_Buffered(SDL_Joystick * joystick)
|
||||
{
|
||||
int i;
|
||||
HRESULT result;
|
||||
DWORD numevents;
|
||||
DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
|
||||
|
||||
numevents = INPUT_QSIZE;
|
||||
result =
|
||||
IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
|
||||
sizeof(DIDEVICEOBJECTDATA), evtbuf,
|
||||
&numevents, 0);
|
||||
if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
|
||||
IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
||||
result =
|
||||
IDirectInputDevice8_GetDeviceData(joystick->hwdata->InputDevice,
|
||||
sizeof(DIDEVICEOBJECTDATA),
|
||||
evtbuf, &numevents, 0);
|
||||
}
|
||||
|
||||
/* Handle the events or punt */
|
||||
if (FAILED(result)) {
|
||||
joystick->hwdata->send_remove_event = SDL_TRUE;
|
||||
joystick->hwdata->removed = SDL_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)numevents; ++i) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
|
||||
const input_t *in = &joystick->hwdata->Inputs[j];
|
||||
|
||||
if (evtbuf[i].dwOfs != in->ofs)
|
||||
continue;
|
||||
|
||||
switch (in->type) {
|
||||
case AXIS:
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData);
|
||||
break;
|
||||
case BUTTON:
|
||||
SDL_PrivateJoystickButton(joystick, in->num,
|
||||
(Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
|
||||
break;
|
||||
case HAT:
|
||||
{
|
||||
Uint8 pos = TranslatePOV(evtbuf[i].dwData);
|
||||
SDL_PrivateJoystickHat(joystick, in->num, pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
static void
|
||||
UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick)
|
||||
{
|
||||
DIJOYSTATE2 state;
|
||||
HRESULT result;
|
||||
int i;
|
||||
|
||||
result =
|
||||
IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
|
||||
sizeof(DIJOYSTATE2), &state);
|
||||
if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
|
||||
IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
||||
result =
|
||||
IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
|
||||
sizeof(DIJOYSTATE2), &state);
|
||||
}
|
||||
|
||||
if (result != DI_OK) {
|
||||
joystick->hwdata->send_remove_event = SDL_TRUE;
|
||||
joystick->hwdata->removed = SDL_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set each known axis, button and POV. */
|
||||
for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
|
||||
const input_t *in = &joystick->hwdata->Inputs[i];
|
||||
|
||||
switch (in->type) {
|
||||
case AXIS:
|
||||
switch (in->ofs) {
|
||||
case DIJOFS_X:
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
|
||||
break;
|
||||
case DIJOFS_Y:
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
|
||||
break;
|
||||
case DIJOFS_Z:
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
|
||||
break;
|
||||
case DIJOFS_RX:
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
|
||||
break;
|
||||
case DIJOFS_RY:
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
|
||||
break;
|
||||
case DIJOFS_RZ:
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
|
||||
break;
|
||||
case DIJOFS_SLIDER(0):
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
|
||||
break;
|
||||
case DIJOFS_SLIDER(1):
|
||||
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case BUTTON:
|
||||
SDL_PrivateJoystickButton(joystick, in->num,
|
||||
(Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
|
||||
break;
|
||||
case HAT:
|
||||
{
|
||||
Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
|
||||
SDL_PrivateJoystickHat(joystick, in->num, pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
HRESULT result;
|
||||
|
||||
result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
|
||||
if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
|
||||
IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice);
|
||||
IDirectInputDevice8_Poll(joystick->hwdata->InputDevice);
|
||||
}
|
||||
|
||||
if (joystick->hwdata->buffered) {
|
||||
UpdateDINPUTJoystickState_Buffered(joystick);
|
||||
} else {
|
||||
UpdateDINPUTJoystickState_Polled(joystick);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
|
||||
IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DINPUT_JoystickQuit(void)
|
||||
{
|
||||
if (dinput != NULL) {
|
||||
IDirectInput8_Release(dinput);
|
||||
dinput = NULL;
|
||||
}
|
||||
|
||||
if (coinitialized) {
|
||||
WIN_CoUninitialize();
|
||||
coinitialized = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !SDL_JOYSTICK_DINPUT */
|
||||
|
||||
|
||||
int
|
||||
SDL_DINPUT_JoystickInit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DINPUT_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DINPUT_JoystickQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_DINPUT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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"
|
||||
|
||||
extern int SDL_DINPUT_JoystickInit(void);
|
||||
extern void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
|
||||
extern int SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice);
|
||||
extern void SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick);
|
||||
extern void SDL_DINPUT_JoystickClose(SDL_Joystick * joystick);
|
||||
extern void SDL_DINPUT_JoystickQuit(void);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -143,8 +143,7 @@ GetJoystickName(int index, const char *szRegKey)
|
||||
static int SDL_SYS_numjoysticks = 0;
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* This function should set SDL_numjoysticks to the number of available
|
||||
* joysticks. Joystick 0 should be the system default joystick.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
@@ -193,11 +192,6 @@ void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
@@ -216,7 +210,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,574 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT
|
||||
|
||||
/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
|
||||
* A. Formiga's WINMM driver.
|
||||
*
|
||||
* Hats and sliders are completely untested; the app I'm writing this for mostly
|
||||
* doesn't use them and I don't own any joysticks with them.
|
||||
*
|
||||
* We don't bother to use event notification here. It doesn't seem to work
|
||||
* with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
|
||||
* let it return 0 events. */
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#endif
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#if !defined(__WINRT__)
|
||||
#include <dbt.h>
|
||||
#endif
|
||||
|
||||
#define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
|
||||
#include "SDL_windowsjoystick_c.h"
|
||||
#include "SDL_dinputjoystick_c.h"
|
||||
#include "SDL_xinputjoystick_c.h"
|
||||
|
||||
#include "../../haptic/windows/SDL_dinputhaptic_c.h" /* For haptic hot plugging */
|
||||
#include "../../haptic/windows/SDL_xinputhaptic_c.h" /* For haptic hot plugging */
|
||||
|
||||
|
||||
#ifndef DEVICE_NOTIFY_WINDOW_HANDLE
|
||||
#define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000
|
||||
#endif
|
||||
|
||||
/* local variables */
|
||||
static SDL_bool s_bDeviceAdded = SDL_FALSE;
|
||||
static SDL_bool s_bDeviceRemoved = SDL_FALSE;
|
||||
static SDL_JoystickID s_nInstanceID = -1;
|
||||
static SDL_cond *s_condJoystickThread = NULL;
|
||||
static SDL_mutex *s_mutexJoyStickEnum = NULL;
|
||||
static SDL_Thread *s_threadJoystick = NULL;
|
||||
static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
|
||||
|
||||
JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
|
||||
|
||||
static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
|
||||
|
||||
#ifdef __WINRT__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int unused;
|
||||
} SDL_DeviceNotificationData;
|
||||
|
||||
static void
|
||||
SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_CheckDeviceNotification(SDL_DeviceNotificationData *data)
|
||||
{
|
||||
}
|
||||
|
||||
#else /* !__WINRT__ */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HRESULT coinitialized;
|
||||
WNDCLASSEX wincl;
|
||||
HWND messageWindow;
|
||||
HDEVNOTIFY hNotify;
|
||||
} SDL_DeviceNotificationData;
|
||||
|
||||
|
||||
/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal */
|
||||
static LRESULT CALLBACK
|
||||
SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_DEVICECHANGE:
|
||||
switch (wParam) {
|
||||
case DBT_DEVICEARRIVAL:
|
||||
if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
|
||||
s_bWindowsDeviceChanged = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case DBT_DEVICEREMOVECOMPLETE:
|
||||
if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
|
||||
s_bWindowsDeviceChanged = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc (hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
|
||||
{
|
||||
if (data->hNotify)
|
||||
UnregisterDeviceNotification(data->hNotify);
|
||||
|
||||
if (data->messageWindow)
|
||||
DestroyWindow(data->messageWindow);
|
||||
|
||||
UnregisterClass(data->wincl.lpszClassName, data->wincl.hInstance);
|
||||
|
||||
if (data->coinitialized == S_OK) {
|
||||
WIN_CoUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
|
||||
{
|
||||
DEV_BROADCAST_DEVICEINTERFACE dbh;
|
||||
GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
|
||||
|
||||
SDL_zerop(data);
|
||||
|
||||
data->coinitialized = WIN_CoInitialize();
|
||||
|
||||
data->wincl.hInstance = GetModuleHandle(NULL);
|
||||
data->wincl.lpszClassName = L"Message";
|
||||
data->wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc; /* This function is called by windows */
|
||||
data->wincl.cbSize = sizeof (WNDCLASSEX);
|
||||
|
||||
if (!RegisterClassEx(&data->wincl)) {
|
||||
WIN_SetError("Failed to create register class for joystick autodetect");
|
||||
SDL_CleanupDeviceNotification(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->messageWindow = (HWND)CreateWindowEx(0, L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
|
||||
if (!data->messageWindow) {
|
||||
WIN_SetError("Failed to create message window for joystick autodetect");
|
||||
SDL_CleanupDeviceNotification(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_zero(dbh);
|
||||
dbh.dbcc_size = sizeof(dbh);
|
||||
dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||
dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
||||
|
||||
data->hNotify = RegisterDeviceNotification(data->messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
if (!data->hNotify) {
|
||||
WIN_SetError("Failed to create notify device for joystick autodetect");
|
||||
SDL_CleanupDeviceNotification(data);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_CheckDeviceNotification(SDL_DeviceNotificationData *data)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
if (!data->messageWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (PeekMessage(&msg, data->messageWindow, 0, 0, PM_NOREMOVE)) {
|
||||
if (GetMessage(&msg, data->messageWindow, 0, 0) != 0) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __WINRT__ */
|
||||
|
||||
/* Function/thread to scan the system for joysticks. */
|
||||
static int
|
||||
SDL_JoystickThread(void *_data)
|
||||
{
|
||||
SDL_DeviceNotificationData notification_data;
|
||||
|
||||
#if SDL_JOYSTICK_XINPUT
|
||||
SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
|
||||
SDL_zero(bOpenedXInputDevices);
|
||||
#endif
|
||||
|
||||
if (SDL_CreateDeviceNotification(¬ification_data) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_LockMutex(s_mutexJoyStickEnum);
|
||||
while (s_bJoystickThreadQuit == SDL_FALSE) {
|
||||
SDL_bool bXInputChanged = SDL_FALSE;
|
||||
|
||||
SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 300);
|
||||
|
||||
SDL_CheckDeviceNotification(¬ification_data);
|
||||
|
||||
#if SDL_JOYSTICK_XINPUT
|
||||
if (SDL_XINPUT_Enabled() && XINPUTGETCAPABILITIES) {
|
||||
/* scan for any change in XInput devices */
|
||||
Uint8 userId;
|
||||
for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
|
||||
XINPUT_CAPABILITIES capabilities;
|
||||
const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
|
||||
const SDL_bool available = (result == ERROR_SUCCESS);
|
||||
if (bOpenedXInputDevices[userId] != available) {
|
||||
bXInputChanged = SDL_TRUE;
|
||||
bOpenedXInputDevices[userId] = available;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_XINPUT */
|
||||
|
||||
if (s_bWindowsDeviceChanged || bXInputChanged) {
|
||||
SDL_UnlockMutex(s_mutexJoyStickEnum); /* let main thread go while we SDL_Delay(). */
|
||||
SDL_Delay(300); /* wait for direct input to find out about this device */
|
||||
SDL_LockMutex(s_mutexJoyStickEnum);
|
||||
|
||||
s_bDeviceRemoved = SDL_TRUE;
|
||||
s_bDeviceAdded = SDL_TRUE;
|
||||
s_bWindowsDeviceChanged = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
||||
|
||||
SDL_CleanupDeviceNotification(¬ification_data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SDL_SYS_AddJoystickDevice(JoyStick_DeviceData *device)
|
||||
{
|
||||
device->send_add_event = SDL_TRUE;
|
||||
device->nInstanceID = ++s_nInstanceID;
|
||||
device->pNext = SYS_Joystick;
|
||||
SYS_Joystick = device;
|
||||
|
||||
s_bDeviceAdded = SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
if (SDL_DINPUT_JoystickInit() < 0) {
|
||||
SDL_SYS_JoystickQuit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SDL_XINPUT_JoystickInit() < 0) {
|
||||
SDL_SYS_JoystickQuit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
s_mutexJoyStickEnum = SDL_CreateMutex();
|
||||
s_condJoystickThread = SDL_CreateCond();
|
||||
s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
|
||||
|
||||
SDL_SYS_JoystickDetect();
|
||||
|
||||
if (!s_threadJoystick) {
|
||||
s_bJoystickThreadQuit = SDL_FALSE;
|
||||
/* spin up the thread to detect hotplug of devices */
|
||||
#if defined(__WIN32__) && !defined(HAVE_LIBC)
|
||||
#undef SDL_CreateThread
|
||||
#if SDL_DYNAMIC_API
|
||||
s_threadJoystick= SDL_CreateThread_REAL(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
|
||||
#else
|
||||
s_threadJoystick= SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
|
||||
#endif
|
||||
#else
|
||||
s_threadJoystick = SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL);
|
||||
#endif
|
||||
}
|
||||
return SDL_SYS_NumJoysticks();
|
||||
}
|
||||
|
||||
/* return the number of joysticks that are connected right now */
|
||||
int
|
||||
SDL_SYS_NumJoysticks()
|
||||
{
|
||||
int nJoysticks = 0;
|
||||
JoyStick_DeviceData *device = SYS_Joystick;
|
||||
while (device) {
|
||||
nJoysticks++;
|
||||
device = device->pNext;
|
||||
}
|
||||
|
||||
return nJoysticks;
|
||||
}
|
||||
|
||||
/* detect any new joysticks being inserted into the system */
|
||||
void
|
||||
SDL_SYS_JoystickDetect()
|
||||
{
|
||||
JoyStick_DeviceData *pCurList = NULL;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
/* only enum the devices if the joystick thread told us something changed */
|
||||
if (!s_bDeviceAdded && !s_bDeviceRemoved) {
|
||||
return; /* thread hasn't signaled, nothing to do right now. */
|
||||
}
|
||||
|
||||
SDL_LockMutex(s_mutexJoyStickEnum);
|
||||
|
||||
s_bDeviceAdded = SDL_FALSE;
|
||||
s_bDeviceRemoved = SDL_FALSE;
|
||||
|
||||
pCurList = SYS_Joystick;
|
||||
SYS_Joystick = NULL;
|
||||
|
||||
/* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
|
||||
SDL_DINPUT_JoystickDetect(&pCurList);
|
||||
|
||||
/* Look for XInput devices. Do this last, so they're first in the final list. */
|
||||
SDL_XINPUT_JoystickDetect(&pCurList);
|
||||
|
||||
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
||||
|
||||
while (pCurList) {
|
||||
JoyStick_DeviceData *pListNext = NULL;
|
||||
|
||||
if (pCurList->bXInputDevice) {
|
||||
SDL_XINPUT_MaybeRemoveDevice(pCurList->XInputUserId);
|
||||
} else {
|
||||
SDL_DINPUT_MaybeRemoveDevice(&pCurList->dxdevice);
|
||||
}
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_zero(event);
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = pCurList->nInstanceID;
|
||||
if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
pListNext = pCurList->pNext;
|
||||
SDL_free(pCurList->joystickname);
|
||||
SDL_free(pCurList);
|
||||
pCurList = pListNext;
|
||||
}
|
||||
|
||||
if (s_bDeviceAdded) {
|
||||
JoyStick_DeviceData *pNewJoystick;
|
||||
int device_index = 0;
|
||||
s_bDeviceAdded = SDL_FALSE;
|
||||
pNewJoystick = SYS_Joystick;
|
||||
while (pNewJoystick) {
|
||||
if (pNewJoystick->send_add_event) {
|
||||
if (pNewJoystick->bXInputDevice) {
|
||||
SDL_XINPUT_MaybeAddDevice(pNewJoystick->XInputUserId);
|
||||
} else {
|
||||
SDL_DINPUT_MaybeAddDevice(&pNewJoystick->dxdevice);
|
||||
}
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_zero(event);
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = device_index;
|
||||
if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
pNewJoystick->send_add_event = SDL_FALSE;
|
||||
}
|
||||
device_index++;
|
||||
pNewJoystick = pNewJoystick->pNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
JoyStick_DeviceData *device = SYS_Joystick;
|
||||
|
||||
for (; device_index > 0; device_index--)
|
||||
device = device->pNext;
|
||||
|
||||
return device->joystickname;
|
||||
}
|
||||
|
||||
/* Function to perform the mapping between current device instance and this joysticks instance id */
|
||||
SDL_JoystickID
|
||||
SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
JoyStick_DeviceData *device = SYS_Joystick;
|
||||
int index;
|
||||
|
||||
for (index = device_index; index > 0; index--)
|
||||
device = device->pNext;
|
||||
|
||||
return device->nInstanceID;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the device index.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
JoyStick_DeviceData *joystickdevice = SYS_Joystick;
|
||||
|
||||
for (; device_index > 0; device_index--)
|
||||
joystickdevice = joystickdevice->pNext;
|
||||
|
||||
/* allocate memory for system specific hardware data */
|
||||
joystick->instance_id = joystickdevice->nInstanceID;
|
||||
joystick->closed = SDL_FALSE;
|
||||
joystick->hwdata =
|
||||
(struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
|
||||
if (joystick->hwdata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_zerop(joystick->hwdata);
|
||||
joystick->hwdata->guid = joystickdevice->guid;
|
||||
|
||||
if (joystickdevice->bXInputDevice) {
|
||||
return SDL_XINPUT_JoystickOpen(joystick, joystickdevice);
|
||||
} else {
|
||||
return SDL_DINPUT_JoystickOpen(joystick, joystickdevice);
|
||||
}
|
||||
}
|
||||
|
||||
/* return true if this joystick is plugged in right now */
|
||||
SDL_bool
|
||||
SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
|
||||
{
|
||||
return !joystick->closed && !joystick->hwdata->removed;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->closed || !joystick->hwdata) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (joystick->hwdata->bXInputDevice) {
|
||||
SDL_XINPUT_JoystickUpdate(joystick);
|
||||
} else {
|
||||
SDL_DINPUT_JoystickUpdate(joystick);
|
||||
}
|
||||
|
||||
if (joystick->hwdata->removed) {
|
||||
joystick->closed = SDL_TRUE;
|
||||
joystick->uncentered = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
if (joystick->hwdata->bXInputDevice) {
|
||||
SDL_XINPUT_JoystickClose(joystick);
|
||||
} else {
|
||||
SDL_DINPUT_JoystickClose(joystick);
|
||||
}
|
||||
|
||||
/* free system specific hardware data */
|
||||
SDL_free(joystick->hwdata);
|
||||
|
||||
joystick->closed = SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
JoyStick_DeviceData *device = SYS_Joystick;
|
||||
|
||||
while (device) {
|
||||
JoyStick_DeviceData *device_next = device->pNext;
|
||||
SDL_free(device->joystickname);
|
||||
SDL_free(device);
|
||||
device = device_next;
|
||||
}
|
||||
SYS_Joystick = NULL;
|
||||
|
||||
if (s_threadJoystick) {
|
||||
SDL_LockMutex(s_mutexJoyStickEnum);
|
||||
s_bJoystickThreadQuit = SDL_TRUE;
|
||||
SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
|
||||
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
||||
SDL_WaitThread(s_threadJoystick, NULL); /* wait for it to bugger off */
|
||||
|
||||
SDL_DestroyMutex(s_mutexJoyStickEnum);
|
||||
SDL_DestroyCond(s_condJoystickThread);
|
||||
s_condJoystickThread= NULL;
|
||||
s_mutexJoyStickEnum = NULL;
|
||||
s_threadJoystick = NULL;
|
||||
}
|
||||
|
||||
SDL_DINPUT_JoystickQuit();
|
||||
SDL_XINPUT_JoystickQuit();
|
||||
}
|
||||
|
||||
/* return the stable device guid for this device index */
|
||||
SDL_JoystickGUID
|
||||
SDL_SYS_JoystickGetDeviceGUID(int device_index)
|
||||
{
|
||||
JoyStick_DeviceData *device = SYS_Joystick;
|
||||
int index;
|
||||
|
||||
for (index = device_index; index > 0; index--)
|
||||
device = device->pNext;
|
||||
|
||||
return device->guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID
|
||||
SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
return joystick->hwdata->guid;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_events.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../../core/windows/SDL_directx.h"
|
||||
|
||||
#define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */
|
||||
|
||||
typedef struct JoyStick_DeviceData
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
char *joystickname;
|
||||
Uint8 send_add_event;
|
||||
SDL_JoystickID nInstanceID;
|
||||
SDL_bool bXInputDevice;
|
||||
BYTE SubType;
|
||||
Uint8 XInputUserId;
|
||||
DIDEVICEINSTANCE dxdevice;
|
||||
struct JoyStick_DeviceData *pNext;
|
||||
} JoyStick_DeviceData;
|
||||
|
||||
extern JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
|
||||
|
||||
typedef enum Type
|
||||
{
|
||||
BUTTON,
|
||||
AXIS,
|
||||
HAT
|
||||
} Type;
|
||||
|
||||
typedef struct input_t
|
||||
{
|
||||
/* DirectInput offset for this input type: */
|
||||
DWORD ofs;
|
||||
|
||||
/* Button, axis or hat: */
|
||||
Type type;
|
||||
|
||||
/* SDL input offset: */
|
||||
Uint8 num;
|
||||
} input_t;
|
||||
|
||||
/* The private structure used to keep track of a joystick */
|
||||
struct joystick_hwdata
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
SDL_bool removed;
|
||||
SDL_bool send_remove_event;
|
||||
|
||||
#if SDL_JOYSTICK_DINPUT
|
||||
LPDIRECTINPUTDEVICE8 InputDevice;
|
||||
DIDEVCAPS Capabilities;
|
||||
SDL_bool buffered;
|
||||
input_t Inputs[MAX_INPUTS];
|
||||
int NumInputs;
|
||||
int NumSliders;
|
||||
#endif
|
||||
|
||||
SDL_bool bXInputDevice; /* SDL_TRUE if this device supports using the xinput API rather than DirectInput */
|
||||
SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
|
||||
Uint8 userid; /* XInput userid index for this joystick */
|
||||
DWORD dwPacketNumber;
|
||||
};
|
||||
|
||||
extern void SDL_SYS_AddJoystickDevice(JoyStick_DeviceData *device);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_assert.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "SDL_windowsjoystick_c.h"
|
||||
#include "SDL_xinputjoystick_c.h"
|
||||
|
||||
|
||||
#if SDL_JOYSTICK_XINPUT
|
||||
|
||||
/*
|
||||
* Internal stuff.
|
||||
*/
|
||||
static SDL_bool s_bXInputEnabled = SDL_TRUE;
|
||||
|
||||
|
||||
static SDL_bool
|
||||
SDL_XInputUseOldJoystickMapping()
|
||||
{
|
||||
static int s_XInputUseOldJoystickMapping = -1;
|
||||
if (s_XInputUseOldJoystickMapping < 0) {
|
||||
const char *hint = SDL_GetHint(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING);
|
||||
s_XInputUseOldJoystickMapping = (hint && *hint == '1') ? 1 : 0;
|
||||
}
|
||||
return (s_XInputUseOldJoystickMapping > 0);
|
||||
}
|
||||
|
||||
SDL_bool SDL_XINPUT_Enabled(void)
|
||||
{
|
||||
return s_bXInputEnabled;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_JoystickInit(void)
|
||||
{
|
||||
const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
|
||||
if (env && !SDL_atoi(env)) {
|
||||
s_bXInputEnabled = SDL_FALSE;
|
||||
}
|
||||
|
||||
if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
|
||||
s_bXInputEnabled = SDL_FALSE; /* oh well. */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
GetXInputName(const Uint8 userid, BYTE SubType)
|
||||
{
|
||||
char name[32];
|
||||
|
||||
if (SDL_XInputUseOldJoystickMapping()) {
|
||||
SDL_snprintf(name, sizeof(name), "X360 Controller #%u", 1 + userid);
|
||||
} else {
|
||||
switch (SubType) {
|
||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||
SDL_snprintf(name, sizeof(name), "XInput Controller #%u", 1 + userid);
|
||||
break;
|
||||
case XINPUT_DEVSUBTYPE_WHEEL:
|
||||
SDL_snprintf(name, sizeof(name), "XInput Wheel #%u", 1 + userid);
|
||||
break;
|
||||
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
|
||||
SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%u", 1 + userid);
|
||||
break;
|
||||
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
|
||||
SDL_snprintf(name, sizeof(name), "XInput FlightStick #%u", 1 + userid);
|
||||
break;
|
||||
case XINPUT_DEVSUBTYPE_DANCE_PAD:
|
||||
SDL_snprintf(name, sizeof(name), "XInput DancePad #%u", 1 + userid);
|
||||
break;
|
||||
case XINPUT_DEVSUBTYPE_GUITAR:
|
||||
case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
|
||||
case XINPUT_DEVSUBTYPE_GUITAR_BASS:
|
||||
SDL_snprintf(name, sizeof(name), "XInput Guitar #%u", 1 + userid);
|
||||
break;
|
||||
case XINPUT_DEVSUBTYPE_DRUM_KIT:
|
||||
SDL_snprintf(name, sizeof(name), "XInput DrumKit #%u", 1 + userid);
|
||||
break;
|
||||
case XINPUT_DEVSUBTYPE_ARCADE_PAD:
|
||||
SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%u", 1 + userid);
|
||||
break;
|
||||
default:
|
||||
SDL_snprintf(name, sizeof(name), "XInput Device #%u", 1 + userid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SDL_strdup(name);
|
||||
}
|
||||
|
||||
static void
|
||||
AddXInputDevice(const Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
|
||||
{
|
||||
JoyStick_DeviceData *pPrevJoystick = NULL;
|
||||
JoyStick_DeviceData *pNewJoystick = *pContext;
|
||||
|
||||
if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
|
||||
return;
|
||||
|
||||
if (SubType == XINPUT_DEVSUBTYPE_UNKNOWN)
|
||||
return;
|
||||
|
||||
while (pNewJoystick) {
|
||||
if (pNewJoystick->bXInputDevice && (pNewJoystick->XInputUserId == userid) && (pNewJoystick->SubType == SubType)) {
|
||||
/* if we are replacing the front of the list then update it */
|
||||
if (pNewJoystick == *pContext) {
|
||||
*pContext = pNewJoystick->pNext;
|
||||
} else if (pPrevJoystick) {
|
||||
pPrevJoystick->pNext = pNewJoystick->pNext;
|
||||
}
|
||||
|
||||
pNewJoystick->pNext = SYS_Joystick;
|
||||
SYS_Joystick = pNewJoystick;
|
||||
return; /* already in the list. */
|
||||
}
|
||||
|
||||
pPrevJoystick = pNewJoystick;
|
||||
pNewJoystick = pNewJoystick->pNext;
|
||||
}
|
||||
|
||||
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
|
||||
if (!pNewJoystick) {
|
||||
return; /* better luck next time? */
|
||||
}
|
||||
SDL_zerop(pNewJoystick);
|
||||
|
||||
pNewJoystick->joystickname = GetXInputName(userid, SubType);
|
||||
if (!pNewJoystick->joystickname) {
|
||||
SDL_free(pNewJoystick);
|
||||
return; /* better luck next time? */
|
||||
}
|
||||
|
||||
pNewJoystick->bXInputDevice = SDL_TRUE;
|
||||
if (SDL_XInputUseOldJoystickMapping()) {
|
||||
SDL_zero(pNewJoystick->guid);
|
||||
} else {
|
||||
pNewJoystick->guid.data[0] = 'x';
|
||||
pNewJoystick->guid.data[1] = 'i';
|
||||
pNewJoystick->guid.data[2] = 'n';
|
||||
pNewJoystick->guid.data[3] = 'p';
|
||||
pNewJoystick->guid.data[4] = 'u';
|
||||
pNewJoystick->guid.data[5] = 't';
|
||||
pNewJoystick->guid.data[6] = SubType;
|
||||
}
|
||||
pNewJoystick->SubType = SubType;
|
||||
pNewJoystick->XInputUserId = userid;
|
||||
SDL_SYS_AddJoystickDevice(pNewJoystick);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
|
||||
{
|
||||
int iuserid;
|
||||
|
||||
if (!s_bXInputEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* iterate in reverse, so these are in the final list in ascending numeric order. */
|
||||
for (iuserid = XUSER_MAX_COUNT - 1; iuserid >= 0; iuserid--) {
|
||||
const Uint8 userid = (Uint8)iuserid;
|
||||
XINPUT_CAPABILITIES capabilities;
|
||||
if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
|
||||
AddXInputDevice(userid, capabilities.SubType, pContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
|
||||
{
|
||||
const Uint8 userId = joystickdevice->XInputUserId;
|
||||
XINPUT_CAPABILITIES capabilities;
|
||||
XINPUT_VIBRATION state;
|
||||
|
||||
SDL_assert(s_bXInputEnabled);
|
||||
SDL_assert(XINPUTGETCAPABILITIES);
|
||||
SDL_assert(XINPUTSETSTATE);
|
||||
SDL_assert(userId < XUSER_MAX_COUNT);
|
||||
|
||||
joystick->hwdata->bXInputDevice = SDL_TRUE;
|
||||
|
||||
if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
|
||||
SDL_free(joystick->hwdata);
|
||||
joystick->hwdata = NULL;
|
||||
return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
|
||||
}
|
||||
SDL_zero(state);
|
||||
joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS);
|
||||
joystick->hwdata->userid = userId;
|
||||
|
||||
/* The XInput API has a hard coded button/axis mapping, so we just match it */
|
||||
if (SDL_XInputUseOldJoystickMapping()) {
|
||||
joystick->naxes = 6;
|
||||
joystick->nbuttons = 15;
|
||||
} else {
|
||||
joystick->naxes = 6;
|
||||
joystick->nbuttons = 11;
|
||||
joystick->nhats = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
|
||||
{
|
||||
static WORD s_XInputButtons[] = {
|
||||
XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
|
||||
XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
|
||||
XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
||||
XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
|
||||
XINPUT_GAMEPAD_GUIDE
|
||||
};
|
||||
WORD wButtons = pXInputState->Gamepad.wButtons;
|
||||
Uint8 button;
|
||||
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
|
||||
SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX);
|
||||
SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
|
||||
SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
|
||||
SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
|
||||
|
||||
for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
|
||||
SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState)
|
||||
{
|
||||
static WORD s_XInputButtons[] = {
|
||||
XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
|
||||
XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
|
||||
XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
|
||||
XINPUT_GAMEPAD_GUIDE
|
||||
};
|
||||
WORD wButtons = pXInputState->Gamepad.wButtons;
|
||||
Uint8 button;
|
||||
Uint8 hat = SDL_HAT_CENTERED;
|
||||
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
|
||||
SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
|
||||
SDL_PrivateJoystickAxis(joystick, 3, (Sint16)pXInputState->Gamepad.sThumbRX);
|
||||
SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
|
||||
SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
|
||||
|
||||
for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
|
||||
SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
|
||||
}
|
||||
|
||||
if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
|
||||
hat |= SDL_HAT_UP;
|
||||
}
|
||||
if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
|
||||
hat |= SDL_HAT_DOWN;
|
||||
}
|
||||
if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
|
||||
hat |= SDL_HAT_LEFT;
|
||||
}
|
||||
if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
|
||||
hat |= SDL_HAT_RIGHT;
|
||||
}
|
||||
SDL_PrivateJoystickHat(joystick, 0, hat);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
HRESULT result;
|
||||
XINPUT_STATE_EX XInputState;
|
||||
|
||||
if (!XINPUTGETSTATE)
|
||||
return;
|
||||
|
||||
result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState);
|
||||
if (result == ERROR_DEVICE_NOT_CONNECTED) {
|
||||
joystick->hwdata->send_remove_event = SDL_TRUE;
|
||||
joystick->hwdata->removed = SDL_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* only fire events if the data changed from last time */
|
||||
if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
|
||||
if (SDL_XInputUseOldJoystickMapping()) {
|
||||
UpdateXInputJoystickState_OLD(joystick, &XInputState);
|
||||
} else {
|
||||
UpdateXInputJoystickState(joystick, &XInputState);
|
||||
}
|
||||
joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_JoystickQuit(void)
|
||||
{
|
||||
if (s_bXInputEnabled) {
|
||||
WIN_UnloadXInputDLL();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index)
|
||||
{
|
||||
JoyStick_DeviceData *device = SYS_Joystick;
|
||||
int index;
|
||||
|
||||
for (index = device_index; index > 0; index--)
|
||||
device = device->pNext;
|
||||
|
||||
return (device->SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
|
||||
}
|
||||
|
||||
#else /* !SDL_JOYSTICK_XINPUT */
|
||||
|
||||
|
||||
SDL_bool SDL_XINPUT_Enabled(void)
|
||||
{
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_JoystickInit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SDL_XINPUT_JoystickQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_XINPUT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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 "../../core/windows/SDL_xinput.h"
|
||||
|
||||
extern SDL_bool SDL_XINPUT_Enabled(void);
|
||||
extern int SDL_XINPUT_JoystickInit(void);
|
||||
extern void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
|
||||
extern int SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice);
|
||||
extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick);
|
||||
extern void SDL_XINPUT_JoystickClose(SDL_Joystick * joystick);
|
||||
extern void SDL_XINPUT_JoystickQuit(void);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -1,537 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_JOYSTICK_XINPUT
|
||||
|
||||
/* SDL_xinputjoystick.c implements an XInput-only joystick and game controller
|
||||
backend that is suitable for use on WinRT. SDL's DirectInput backend, also
|
||||
XInput-capable, was not used as DirectInput is not available on WinRT (or,
|
||||
at least, it isn't a public API). Some portions of this XInput backend
|
||||
may copy parts of the XInput-using code from the DirectInput backend.
|
||||
Refactoring the common parts into one location may be good to-do at some
|
||||
point.
|
||||
|
||||
TODO, WinRT: add hotplug support for XInput based game controllers
|
||||
*/
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "SDL_events.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Xinput.h>
|
||||
|
||||
struct joystick_hwdata {
|
||||
//Uint8 bXInputHaptic; // Supports force feedback via XInput.
|
||||
DWORD userIndex; // The XInput device index, in the range [0, XUSER_MAX_COUNT-1] (probably [0,3]).
|
||||
XINPUT_STATE XInputState; // the last-read in XInputState, kept around to compare old and new values
|
||||
SDL_bool isDeviceConnected; // was the device connected (on the last detection-polling, or during backend-initialization)?
|
||||
SDL_bool isDeviceConnectionEventPending; // was a device added, and is the associated add-event pending?
|
||||
SDL_bool isDeviceRemovalEventPending; // was the device removed, and is the associated remove-event pending?
|
||||
};
|
||||
|
||||
/* Keep track of data on all XInput devices, regardless of whether or not
|
||||
they've been opened (via SDL_JoystickOpen).
|
||||
*/
|
||||
static struct joystick_hwdata g_XInputData[XUSER_MAX_COUNT];
|
||||
|
||||
/* Device detection can be extremely costly performance-wise, in some cases.
|
||||
In particular, if no devices are connected, calls to detect a single device,
|
||||
via either XInputGetState() or XInputGetCapabilities(), can take upwards of
|
||||
20 ms on a 1st generation Surface RT, more if devices are detected across
|
||||
all of of XInput's four device slots. WinRT and XInput do not appear to
|
||||
have callback-based APIs to notify an app when a device is connected, at
|
||||
least as of Windows 8.1. The synchronous XInput calls must be used.
|
||||
|
||||
Once a device is connected, calling XInputGetState() is a much less costly
|
||||
operation, with individual calls costing well under 1 ms, and often under
|
||||
0.1 ms [on a 1st gen Surface RT].
|
||||
|
||||
With XInput's performance limitations in mind, a separate device-detection
|
||||
thread will be utilized (by SDL) to try to move costly XInput calls off the
|
||||
main thread. Polling of active devices still, however, occurs on the main
|
||||
thread.
|
||||
*/
|
||||
static SDL_Thread * g_DeviceDetectionThread = NULL;
|
||||
static SDL_mutex * g_DeviceInfoLock = NULL;
|
||||
static SDL_bool g_DeviceDetectionQuit = SDL_FALSE;
|
||||
|
||||
/* Main function for the device-detection thread.
|
||||
*/
|
||||
static int
|
||||
DeviceDetectionThreadMain(void * _data)
|
||||
{
|
||||
DWORD result;
|
||||
XINPUT_CAPABILITIES tempXInputCaps;
|
||||
int i;
|
||||
|
||||
while (1) {
|
||||
/* See if the device-detection thread is being asked to shutdown.
|
||||
*/
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
if (g_DeviceDetectionQuit) {
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
break;
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
|
||||
/* Add a short delay to prevent the device-detection thread from eating
|
||||
up too much CPU time:
|
||||
*/
|
||||
SDL_Delay(300);
|
||||
|
||||
/* TODO, WinRT: try making the device-detection thread wakeup sooner from its CPU-preserving SDL_Delay, if the thread was asked to quit.
|
||||
*/
|
||||
|
||||
/* See if any new devices are connected. */
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
if (!g_XInputData[i].isDeviceConnected &&
|
||||
!g_XInputData[i].isDeviceConnectionEventPending &&
|
||||
!g_XInputData[i].isDeviceRemovalEventPending)
|
||||
{
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
result = XInputGetCapabilities(i, 0, &tempXInputCaps);
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
/* Yes, a device is connected. Mark it as such.
|
||||
Others will be told about this (via an
|
||||
SDL_JOYDEVICEADDED event) in the next call to
|
||||
SDL_SYS_JoystickDetect.
|
||||
*/
|
||||
g_XInputData[i].isDeviceConnected = SDL_TRUE;
|
||||
g_XInputData[i].isDeviceConnectionEventPending = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* It should return 0, or -1 on an unrecoverable fatal error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
XINPUT_STATE tempXInputState;
|
||||
int i;
|
||||
|
||||
SDL_zero(g_XInputData);
|
||||
|
||||
/* Make initial notes on whether or not devices are connected (or not).
|
||||
*/
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
result = XInputGetState(i, &tempXInputState);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
g_XInputData[i].isDeviceConnected = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start up the device-detection thread.
|
||||
*/
|
||||
g_DeviceDetectionQuit = SDL_FALSE;
|
||||
g_DeviceInfoLock = SDL_CreateMutex();
|
||||
g_DeviceDetectionThread = SDL_CreateThread(DeviceDetectionThreadMain, "SDL_joystick", NULL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int SDL_SYS_NumJoysticks()
|
||||
{
|
||||
int joystickCount = 0;
|
||||
DWORD i;
|
||||
|
||||
/* Iterate through each possible XInput device and see if something
|
||||
was connected (at joystick init, or during the last polling).
|
||||
*/
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
if (g_XInputData[i].isDeviceConnected) {
|
||||
++joystickCount;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
|
||||
return joystickCount;
|
||||
}
|
||||
|
||||
void SDL_SYS_JoystickDetect()
|
||||
{
|
||||
DWORD i;
|
||||
SDL_Event event;
|
||||
|
||||
/* Iterate through each possible XInput device, seeing if any devices
|
||||
have been connected, or if they were removed.
|
||||
*/
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
for (i = 0; i < XUSER_MAX_COUNT; ++i) {
|
||||
/* See if any new devices are connected. */
|
||||
if (g_XInputData[i].isDeviceConnectionEventPending) {
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_zero(event);
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = i;
|
||||
if ((SDL_EventOK == NULL)
|
||||
|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
g_XInputData[i].isDeviceConnectionEventPending = SDL_FALSE;
|
||||
} else if (g_XInputData[i].isDeviceRemovalEventPending) {
|
||||
/* A device was previously marked as removed (by
|
||||
SDL_SYS_JoystickUpdate). Tell others about the device removal.
|
||||
*/
|
||||
|
||||
g_XInputData[i].isDeviceRemovalEventPending = SDL_FALSE;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_zero(event);
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = i; //joystick->hwdata->userIndex;
|
||||
if ((SDL_EventOK == NULL)
|
||||
|| (*SDL_EventOK) (SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_JoystickNeedsPolling()
|
||||
{
|
||||
/* Since XInput, or WinRT, provides any events to indicate when a game
|
||||
controller gets connected, and instead indicates device availability
|
||||
solely through polling, we'll poll (for new devices).
|
||||
*/
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Internal function to retreive device capabilities.
|
||||
This function will return an SDL-standard value of 0 on success
|
||||
(a device is connected, and data on it was retrieved), or -1
|
||||
on failure (no device was connected, or some other error
|
||||
occurred. SDL_SetError() will be invoked to set an appropriate
|
||||
error message.
|
||||
*/
|
||||
static int
|
||||
SDL_XInput_GetDeviceCapabilities(int device_index, XINPUT_CAPABILITIES * pDeviceCaps)
|
||||
{
|
||||
HRESULT dwResult;
|
||||
|
||||
/* Make sure that the device index is a valid one. If not, return to the
|
||||
caller with an error.
|
||||
*/
|
||||
if (device_index < 0 || device_index >= XUSER_MAX_COUNT) {
|
||||
return SDL_SetError("invalid/unavailable device index");
|
||||
}
|
||||
|
||||
/* See if a device exists, and if so, what its capabilities are. If a
|
||||
device is not available, return to the caller with an error.
|
||||
*/
|
||||
switch ((dwResult = XInputGetCapabilities(device_index, 0, pDeviceCaps))) {
|
||||
case ERROR_SUCCESS:
|
||||
/* A device is available, and its capabilities were retrieved! */
|
||||
return 0;
|
||||
case ERROR_DEVICE_NOT_CONNECTED:
|
||||
return SDL_SetError("no device is connected at joystick index, %d", device_index);
|
||||
default:
|
||||
return SDL_SetError("an unknown error occurred when retrieving info on a device at joystick index, %d", device_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to get the device-dependent name of a joystick */
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
XINPUT_CAPABILITIES deviceCaps;
|
||||
|
||||
if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
|
||||
/* Uh oh. Device capabilities couldn't be retrieved. Return to the
|
||||
caller. SDL_SetError() has already been invoked (with relevant
|
||||
information).
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (deviceCaps.SubType) {
|
||||
default:
|
||||
if (deviceCaps.Type == XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return "Undefined game controller";
|
||||
} else {
|
||||
return "Undefined controller";
|
||||
}
|
||||
case XINPUT_DEVSUBTYPE_UNKNOWN:
|
||||
if (deviceCaps.Type == XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return "Unknown game controller";
|
||||
} else {
|
||||
return "Unknown controller";
|
||||
}
|
||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||
return "Gamepad controller";
|
||||
case XINPUT_DEVSUBTYPE_WHEEL:
|
||||
return "Racing wheel controller";
|
||||
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
|
||||
return "Arcade stick controller";
|
||||
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
|
||||
return "Flight stick controller";
|
||||
case XINPUT_DEVSUBTYPE_DANCE_PAD:
|
||||
return "Dance pad controller";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR:
|
||||
return "Guitar controller";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
|
||||
return "Guitar controller, Alternate";
|
||||
case XINPUT_DEVSUBTYPE_GUITAR_BASS:
|
||||
return "Guitar controller, Bass";
|
||||
case XINPUT_DEVSUBTYPE_DRUM_KIT:
|
||||
return "Drum controller";
|
||||
case XINPUT_DEVSUBTYPE_ARCADE_PAD:
|
||||
return "Arcade pad controller";
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
The joystick to open is specified by the index field of the joystick.
|
||||
This should fill the nbuttons and naxes fields of the joystick structure.
|
||||
It returns 0, or -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
XINPUT_CAPABILITIES deviceCaps;
|
||||
|
||||
if (SDL_XInput_GetDeviceCapabilities(device_index, &deviceCaps) != 0) {
|
||||
/* Uh oh. Device capabilities couldn't be retrieved. Return to the
|
||||
caller. SDL_SetError() has already been invoked (with relevant
|
||||
information).
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* For now, only game pads are supported. If the device is something other
|
||||
than that, return an error to the caller.
|
||||
*/
|
||||
if (deviceCaps.Type != XINPUT_DEVTYPE_GAMEPAD) {
|
||||
return SDL_SetError("a device is connected (at joystick index, %d), but it is of an unknown device type (deviceCaps.Flags=%ul)",
|
||||
device_index, (unsigned int)deviceCaps.Flags);
|
||||
}
|
||||
|
||||
/* Create the joystick data structure */
|
||||
joystick->instance_id = device_index;
|
||||
joystick->hwdata = &g_XInputData[device_index];
|
||||
|
||||
// The XInput API has a hard coded button/axis mapping, so we just match it
|
||||
joystick->naxes = 6;
|
||||
joystick->nbuttons = 15;
|
||||
joystick->nballs = 0;
|
||||
joystick->nhats = 0;
|
||||
|
||||
/* We're done! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Function to determine is this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_bool isDeviceConnected;
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
isDeviceConnected = joystick->hwdata->isDeviceConnected;
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
return isDeviceConnected;
|
||||
}
|
||||
|
||||
/* Function to return > 0 if a bit array of buttons differs after applying a mask
|
||||
*/
|
||||
static int ButtonChanged( int ButtonsNow, int ButtonsPrev, int ButtonMask )
|
||||
{
|
||||
return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
* This function shouldn't update the joystick structure directly,
|
||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||
* and update joystick device state.
|
||||
*/
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
HRESULT result;
|
||||
XINPUT_STATE prevXInputState;
|
||||
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
|
||||
/* Before polling for new data, make note of the old data */
|
||||
prevXInputState = joystick->hwdata->XInputState;
|
||||
|
||||
/* Poll for new data */
|
||||
result = XInputGetState(joystick->hwdata->userIndex, &joystick->hwdata->XInputState);
|
||||
if (result == ERROR_DEVICE_NOT_CONNECTED) {
|
||||
if (joystick->hwdata->isDeviceConnected) {
|
||||
joystick->hwdata->isDeviceConnected = SDL_FALSE;
|
||||
joystick->hwdata->isDeviceRemovalEventPending = SDL_TRUE;
|
||||
/* TODO, WinRT: make sure isDeviceRemovalEventPending gets cleared as appropriate, and that quick re-plugs don't cause trouble */
|
||||
}
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure the device is marked as connected */
|
||||
joystick->hwdata->isDeviceConnected = SDL_TRUE;
|
||||
|
||||
// only fire events if the data changed from last time
|
||||
if ( joystick->hwdata->XInputState.dwPacketNumber != 0
|
||||
&& joystick->hwdata->XInputState.dwPacketNumber != prevXInputState.dwPacketNumber )
|
||||
{
|
||||
XINPUT_STATE *pXInputState = &joystick->hwdata->XInputState;
|
||||
XINPUT_STATE *pXInputStatePrev = &prevXInputState;
|
||||
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX );
|
||||
SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-1*pXInputState->Gamepad.sThumbLY-1) );
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX );
|
||||
SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-1*pXInputState->Gamepad.sThumbRY-1) );
|
||||
SDL_PrivateJoystickAxis(joystick, 4, (Sint16)((int)pXInputState->Gamepad.bLeftTrigger*32767/255) );
|
||||
SDL_PrivateJoystickAxis(joystick, 5, (Sint16)((int)pXInputState->Gamepad.bRightTrigger*32767/255) );
|
||||
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_UP ) )
|
||||
SDL_PrivateJoystickButton(joystick, 0, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_DOWN ) )
|
||||
SDL_PrivateJoystickButton(joystick, 1, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_LEFT ) )
|
||||
SDL_PrivateJoystickButton(joystick, 2, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_RIGHT ) )
|
||||
SDL_PrivateJoystickButton(joystick, 3, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_START ) )
|
||||
SDL_PrivateJoystickButton(joystick, 4, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_START ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_BACK ) )
|
||||
SDL_PrivateJoystickButton(joystick, 5, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_THUMB ) )
|
||||
SDL_PrivateJoystickButton(joystick, 6, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_THUMB ) )
|
||||
SDL_PrivateJoystickButton(joystick, 7, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_SHOULDER ) )
|
||||
SDL_PrivateJoystickButton(joystick, 8, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_SHOULDER ) )
|
||||
SDL_PrivateJoystickButton(joystick, 9, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_A ) )
|
||||
SDL_PrivateJoystickButton(joystick, 10, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_A ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_B ) )
|
||||
SDL_PrivateJoystickButton(joystick, 11, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_B ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_X ) )
|
||||
SDL_PrivateJoystickButton(joystick, 12, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_X ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_Y ) )
|
||||
SDL_PrivateJoystickButton(joystick, 13, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_Y ? SDL_PRESSED : SDL_RELEASED );
|
||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, 0x400 ) )
|
||||
SDL_PrivateJoystickButton(joystick, 14, pXInputState->Gamepad.wButtons & 0x400 ? SDL_PRESSED : SDL_RELEASED ); // 0x400 is the undocumented code for the guide button
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
/* Clear cached button data on the joystick */
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
SDL_zero(joystick->hwdata->XInputState);
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
|
||||
/* There's need to free 'hwdata', as it's a pointer to a global array.
|
||||
The field will be cleared anyways, just to indicate that it's not
|
||||
currently needed.
|
||||
*/
|
||||
joystick->hwdata = NULL;
|
||||
}
|
||||
|
||||
/* Function to perform any system-specific joystick related cleanup */
|
||||
void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
/* Tell the joystick detection thread to stop, then wait for it to finish */
|
||||
SDL_LockMutex(g_DeviceInfoLock);
|
||||
g_DeviceDetectionQuit = SDL_TRUE;
|
||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||
SDL_WaitThread(g_DeviceDetectionThread, NULL);
|
||||
|
||||
/* Clean up device-detection stuff */
|
||||
SDL_DestroyMutex(g_DeviceInfoLock);
|
||||
g_DeviceInfoLock = NULL;
|
||||
g_DeviceDetectionThread = NULL;
|
||||
g_DeviceDetectionQuit = SDL_FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
// the GUID is just the first 16 chars of the name for now
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
// the GUID is just the first 16 chars of the name for now
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_bool SDL_SYS_IsXInputDeviceIndex(int device_index)
|
||||
{
|
||||
/* The XInput-capable DirectInput joystick backend implements the same
|
||||
function (SDL_SYS_IsXInputDeviceIndex), however in that case, not all
|
||||
joystick devices are XInput devices. In this case, with the
|
||||
WinRT-enabled XInput-only backend, all "joystick" devices are XInput
|
||||
devices.
|
||||
*/
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_XINPUT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -134,6 +134,8 @@ static const char rcsid[] =
|
||||
#include "math_libm.h"
|
||||
#include "math_private.h"
|
||||
|
||||
#include "SDL_assert.h"
|
||||
|
||||
libm_hidden_proto(scalbn)
|
||||
libm_hidden_proto(floor)
|
||||
#ifdef __STDC__
|
||||
@@ -181,10 +183,13 @@ __kernel_rem_pio2(x, y, e0, nx, prec, ipio2)
|
||||
double z, fw, f[20], fq[20], q[20];
|
||||
|
||||
/* initialize jk */
|
||||
SDL_assert((prec >= 0) && (prec < SDL_arraysize(init_jk)));
|
||||
jk = init_jk[prec];
|
||||
SDL_assert((jk >= 2) && (jk <= 6));
|
||||
jp = jk;
|
||||
|
||||
/* determine jx,jv,q0, note that 3>q0 */
|
||||
SDL_assert(nx > 0);
|
||||
jx = nx - 1;
|
||||
jv = (e0 - 3) / 24;
|
||||
if (jv < 0)
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
/* __kernel_tan( x, y, k )
|
||||
* kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
|
||||
* Input x is assumed to be bounded by ~pi/4 in magnitude.
|
||||
* Input y is the tail of x.
|
||||
* Input k indicates whether tan (if k=1) or
|
||||
* -1/tan (if k= -1) is returned.
|
||||
*
|
||||
* Algorithm
|
||||
* 1. Since tan(-x) = -tan(x), we need only to consider positive x.
|
||||
* 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
|
||||
* 3. tan(x) is approximated by a odd polynomial of degree 27 on
|
||||
* [0,0.67434]
|
||||
* 3 27
|
||||
* tan(x) ~ x + T1*x + ... + T13*x
|
||||
* where
|
||||
*
|
||||
* |tan(x) 2 4 26 | -59.2
|
||||
* |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
|
||||
* | x |
|
||||
*
|
||||
* Note: tan(x+y) = tan(x) + tan'(x)*y
|
||||
* ~ tan(x) + (1+x*x)*y
|
||||
* Therefore, for better accuracy in computing tan(x+y), let
|
||||
* 3 2 2 2 2
|
||||
* r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
|
||||
* then
|
||||
* 3 2
|
||||
* tan(x+y) = x + (T1*x + (x *(r+y)+y))
|
||||
*
|
||||
* 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
|
||||
* tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
|
||||
* = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
|
||||
*/
|
||||
|
||||
#include "math_libm.h"
|
||||
#include "math_private.h"
|
||||
|
||||
static const double
|
||||
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
|
||||
pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
|
||||
pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */
|
||||
T[] = {
|
||||
3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */
|
||||
1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */
|
||||
5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */
|
||||
2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */
|
||||
8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */
|
||||
3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */
|
||||
1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */
|
||||
5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */
|
||||
2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */
|
||||
7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */
|
||||
7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */
|
||||
-1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */
|
||||
2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */
|
||||
};
|
||||
|
||||
double __kernel_tan(double x, double y, int iy)
|
||||
{
|
||||
double z,r,v,w,s;
|
||||
int32_t ix,hx;
|
||||
GET_HIGH_WORD(hx,x);
|
||||
ix = hx&0x7fffffff; /* high word of |x| */
|
||||
if(ix<0x3e300000) /* x < 2**-28 */
|
||||
{if((int)x==0) { /* generate inexact */
|
||||
u_int32_t low;
|
||||
GET_LOW_WORD(low,x);
|
||||
if(((ix|low)|(iy+1))==0) return one/fabs(x);
|
||||
else return (iy==1)? x: -one/x;
|
||||
}
|
||||
}
|
||||
if(ix>=0x3FE59428) { /* |x|>=0.6744 */
|
||||
if(hx<0) {x = -x; y = -y;}
|
||||
z = pio4-x;
|
||||
w = pio4lo-y;
|
||||
x = z+w; y = 0.0;
|
||||
}
|
||||
z = x*x;
|
||||
w = z*z;
|
||||
/* Break x^5*(T[1]+x^2*T[2]+...) into
|
||||
* x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
|
||||
* x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
|
||||
*/
|
||||
r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
|
||||
v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
|
||||
s = z*x;
|
||||
r = y + z*(s*(r+v)+y);
|
||||
r += T[0]*s;
|
||||
w = x+r;
|
||||
if(ix>=0x3FE59428) {
|
||||
v = (double)iy;
|
||||
return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r)));
|
||||
}
|
||||
if(iy==1) return w;
|
||||
else { /* if allow error up to 2 ulp,
|
||||
simply return -1.0/(x+r) here */
|
||||
/* compute -1.0/(x+r) accurately */
|
||||
double a,t;
|
||||
z = w;
|
||||
SET_LOW_WORD(z,0);
|
||||
v = r-(z - x); /* z+v = r+x */
|
||||
t = a = -1.0/w; /* a = -1.0/w */
|
||||
SET_LOW_WORD(t,0);
|
||||
s = 1.0+t*z;
|
||||
return t+a*(s+t*v);
|
||||
}
|
||||
}
|
||||
@@ -33,5 +33,6 @@ double SDL_uclibc_pow(double x, double y);
|
||||
double SDL_uclibc_scalbn(double x, int n);
|
||||
double SDL_uclibc_sin(double x);
|
||||
double SDL_uclibc_sqrt(double x);
|
||||
double SDL_uclibc_tan(double x);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef unsigned int u_int32_t;
|
||||
#define scalbn SDL_uclibc_scalbn
|
||||
#define sin SDL_uclibc_sin
|
||||
#define __ieee754_sqrt SDL_uclibc_sqrt
|
||||
#define tan SDL_uclibc_tan
|
||||
|
||||
/* The original fdlibm code used statements like:
|
||||
n0 = ((*(int*)&one)>>29)^1; * index of high word *
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user