mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-26 14:55:39 +00:00
Update to SDL2.0.10
This commit is contained in:
parent
600859bd63
commit
c932bda8dd
915 changed files with 116675 additions and 21754 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -33,6 +33,7 @@
|
|||
#include "events/SDL_events_c.h"
|
||||
#include "haptic/SDL_haptic_c.h"
|
||||
#include "joystick/SDL_joystick_c.h"
|
||||
#include "sensor/SDL_sensor_c.h"
|
||||
|
||||
/* Initialization/Cleanup routines */
|
||||
#if !SDL_TIMERS_DISABLED
|
||||
|
|
@ -123,11 +124,11 @@ SDL_InitSubSystem(Uint32 flags)
|
|||
}
|
||||
|
||||
#if SDL_VIDEO_DRIVER_WINDOWS
|
||||
if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
|
||||
if (SDL_HelperWindowCreate() < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
|
||||
if (SDL_HelperWindowCreate() < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SDL_TIMERS_DISABLED
|
||||
|
|
@ -138,10 +139,9 @@ SDL_InitSubSystem(Uint32 flags)
|
|||
if ((flags & SDL_INIT_EVENTS)) {
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
if (SDL_PrivateShouldInitSubsystem(SDL_INIT_EVENTS)) {
|
||||
if (SDL_StartEventLoop() < 0) {
|
||||
if (SDL_EventsInit() < 0) {
|
||||
return (-1);
|
||||
}
|
||||
SDL_QuitInit();
|
||||
}
|
||||
SDL_PrivateSubsystemRefCountIncr(SDL_INIT_EVENTS);
|
||||
#else
|
||||
|
|
@ -232,6 +232,20 @@ SDL_InitSubSystem(Uint32 flags)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Initialize the sensor subsystem */
|
||||
if ((flags & SDL_INIT_SENSOR)){
|
||||
#if !SDL_SENSOR_DISABLED
|
||||
if (SDL_PrivateShouldInitSubsystem(SDL_INIT_SENSOR)) {
|
||||
if (SDL_SensorInit() < 0) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
SDL_PrivateSubsystemRefCountIncr(SDL_INIT_SENSOR);
|
||||
#else
|
||||
return SDL_SetError("SDL not built with sensor support");
|
||||
#endif
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -245,6 +259,15 @@ void
|
|||
SDL_QuitSubSystem(Uint32 flags)
|
||||
{
|
||||
/* Shut down requested initialized subsystems */
|
||||
#if !SDL_SENSOR_DISABLED
|
||||
if ((flags & SDL_INIT_SENSOR)) {
|
||||
if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_SENSOR)) {
|
||||
SDL_SensorQuit();
|
||||
}
|
||||
SDL_PrivateSubsystemRefCountDecr(SDL_INIT_SENSOR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SDL_JOYSTICK_DISABLED
|
||||
if ((flags & SDL_INIT_GAMECONTROLLER)) {
|
||||
/* game controller implies joystick */
|
||||
|
|
@ -309,8 +332,7 @@ SDL_QuitSubSystem(Uint32 flags)
|
|||
#if !SDL_EVENTS_DISABLED
|
||||
if ((flags & SDL_INIT_EVENTS)) {
|
||||
if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_EVENTS)) {
|
||||
SDL_QuitQuit();
|
||||
SDL_StopEventLoop();
|
||||
SDL_EventsQuit();
|
||||
}
|
||||
SDL_PrivateSubsystemRefCountDecr(SDL_INIT_EVENTS);
|
||||
}
|
||||
|
|
@ -324,6 +346,12 @@ SDL_WasInit(Uint32 flags)
|
|||
int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount);
|
||||
Uint32 initialized = 0;
|
||||
|
||||
/* Fast path for checking one flag */
|
||||
if (SDL_HasExactlyOneBitSet32(flags)) {
|
||||
int subsystem_index = SDL_MostSignificantBitIndex32(flags);
|
||||
return SDL_SubsystemRefCount[subsystem_index] ? flags : 0;
|
||||
}
|
||||
|
||||
if (!flags) {
|
||||
flags = SDL_INIT_EVERYTHING;
|
||||
}
|
||||
|
|
@ -451,6 +479,20 @@ SDL_GetPlatform()
|
|||
#endif
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_IsTablet()
|
||||
{
|
||||
#if __ANDROID__
|
||||
extern SDL_bool SDL_IsAndroidTablet(void);
|
||||
return SDL_IsAndroidTablet();
|
||||
#elif __IPHONEOS__
|
||||
extern SDL_bool SDL_IsIPad(void);
|
||||
return SDL_IsIPad();
|
||||
#else
|
||||
return SDL_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__WIN32__)
|
||||
|
||||
#if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -120,20 +120,36 @@ static void SDL_GenerateAssertionReport(void)
|
|||
}
|
||||
|
||||
|
||||
#if defined(__WATCOMC__)
|
||||
#pragma aux SDL_ExitProcess aborts;
|
||||
#endif
|
||||
static SDL_NORETURN void SDL_ExitProcess(int exitcode)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
/* "if you do not know the state of all threads in your process, it is
|
||||
better to call TerminateProcess than ExitProcess"
|
||||
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */
|
||||
TerminateProcess(GetCurrentProcess(), exitcode);
|
||||
/* MingW doesn't have TerminateProcess marked as noreturn, so add an
|
||||
ExitProcess here that will never be reached but make MingW happy. */
|
||||
ExitProcess(exitcode);
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
emscripten_cancel_main_loop(); /* this should "kill" the app. */
|
||||
emscripten_force_exit(exitcode); /* this should "kill" the app. */
|
||||
exit(exitcode);
|
||||
#elif defined(__HAIKU__) /* Haiku has _Exit, but it's not marked noreturn. */
|
||||
_exit(exitcode);
|
||||
#elif defined(HAVE__EXIT) /* Upper case _Exit() */
|
||||
_Exit(exitcode);
|
||||
#else
|
||||
_exit(exitcode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(__WATCOMC__)
|
||||
#pragma aux SDL_AbortAssertion aborts;
|
||||
#endif
|
||||
static SDL_NORETURN void SDL_AbortAssertion(void)
|
||||
{
|
||||
SDL_Quit();
|
||||
|
|
@ -168,6 +184,7 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
|
|||
|
||||
(void) userdata; /* unused in default handler. */
|
||||
|
||||
/* !!! FIXME: why is this using SDL_stack_alloc and not just "char message[SDL_MAX_LOG_MESSAGE];" ? */
|
||||
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
|
||||
if (!message) {
|
||||
/* Uh oh, we're in real trouble now... */
|
||||
|
|
@ -239,7 +256,7 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
|
|||
SDL_bool okay = SDL_TRUE;
|
||||
char *buf = (char *) EM_ASM_INT({
|
||||
var str =
|
||||
Pointer_stringify($0) + '\n\n' +
|
||||
UTF8ToString($0) + '\n\n' +
|
||||
'Abort/Retry/Ignore/AlwaysIgnore? [ariA] :';
|
||||
var reply = window.prompt(str, "i");
|
||||
if (reply === null) {
|
||||
|
|
@ -359,10 +376,6 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
|
|||
|
||||
switch (state)
|
||||
{
|
||||
case SDL_ASSERTION_ABORT:
|
||||
SDL_AbortAssertion();
|
||||
return SDL_ASSERTION_IGNORE; /* shouldn't return, but oh well. */
|
||||
|
||||
case SDL_ASSERTION_ALWAYS_IGNORE:
|
||||
state = SDL_ASSERTION_IGNORE;
|
||||
data->always_ignore = 1;
|
||||
|
|
@ -372,6 +385,10 @@ SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
|
|||
case SDL_ASSERTION_RETRY:
|
||||
case SDL_ASSERTION_BREAK:
|
||||
break; /* macro handles these. */
|
||||
|
||||
case SDL_ASSERTION_ABORT:
|
||||
SDL_AbortAssertion();
|
||||
/*break; ...shouldn't return, but oh well. */
|
||||
}
|
||||
|
||||
assertion_running--;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -19,6 +19,11 @@
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_assert_c_h_
|
||||
#define SDL_assert_c_h_
|
||||
|
||||
extern void SDL_AssertionsQuit(void);
|
||||
|
||||
#endif /* SDL_assert_c_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -81,7 +81,7 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
|||
case 0: /* Malformed format string.. */
|
||||
--fmt;
|
||||
break;
|
||||
case 'i': case 'd': case 'u':
|
||||
case 'i': case 'd': case 'u': case 'x': case 'X':
|
||||
error->args[error->argc++].value_l = va_arg(ap, long);
|
||||
break;
|
||||
}
|
||||
|
|
@ -234,7 +234,7 @@ SDL_GetErrorMsg(char *errstr, int maxlen)
|
|||
*spot++ = *fmt++;
|
||||
*spot++ = '\0';
|
||||
switch (spot[-2]) {
|
||||
case 'i': case 'd': case 'u':
|
||||
case 'i': case 'd': case 'u': case 'x': case 'X':
|
||||
len = SDL_snprintf(msg, maxlen, tmp,
|
||||
error->args[argi++].value_l);
|
||||
if (len > 0) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -35,6 +35,10 @@
|
|||
#define SDL_VARIABLE_LENGTH_ARRAY
|
||||
#endif
|
||||
|
||||
#define SDL_MAX_SMALL_ALLOC_STACKSIZE 128
|
||||
#define SDL_small_alloc(type, count, pisstack) ( (*(pisstack) = ((sizeof(type)*(count)) < SDL_MAX_SMALL_ALLOC_STACKSIZE)), (*(pisstack) ? SDL_stack_alloc(type, count) : (type*)SDL_malloc(sizeof(type)*(count))) )
|
||||
#define SDL_small_free(ptr, isstack) if ((isstack)) { SDL_stack_free(ptr); } else { SDL_free(ptr); }
|
||||
|
||||
#include "dynapi/SDL_dynapi.h"
|
||||
|
||||
#if SDL_DYNAMIC_API
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -282,6 +282,7 @@ SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list
|
|||
return;
|
||||
}
|
||||
|
||||
/* !!! FIXME: why not just "char message[SDL_MAX_LOG_MESSAGE];" ? */
|
||||
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
|
||||
if (!message) {
|
||||
return;
|
||||
|
|
@ -321,6 +322,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
char *output;
|
||||
size_t length;
|
||||
LPTSTR tstr;
|
||||
SDL_bool isstack;
|
||||
|
||||
#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
|
||||
BOOL attachResult;
|
||||
|
|
@ -364,7 +366,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
|
||||
|
||||
length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
|
||||
output = SDL_stack_alloc(char, length);
|
||||
output = SDL_small_alloc(char, length, &isstack);
|
||||
SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message);
|
||||
tstr = WIN_UTF8ToString(output);
|
||||
|
||||
|
|
@ -389,7 +391,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
|
||||
|
||||
SDL_free(tstr);
|
||||
SDL_stack_free(output);
|
||||
SDL_small_free(output, isstack);
|
||||
}
|
||||
#elif defined(__ANDROID__)
|
||||
{
|
||||
|
|
@ -398,13 +400,13 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
|||
SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
|
||||
__android_log_write(SDL_android_priority[priority], tag, message);
|
||||
}
|
||||
#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
|
||||
/* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now.
|
||||
#elif defined(__APPLE__) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT))
|
||||
/* Technically we don't need Cocoa/UIKit, but that's where this function is defined for now.
|
||||
*/
|
||||
extern void SDL_NSLog(const char *text);
|
||||
{
|
||||
char *text;
|
||||
|
||||
/* !!! FIXME: why not just "char text[SDL_MAX_LOG_MESSAGE];" ? */
|
||||
text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
|
||||
if (text) {
|
||||
SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -53,10 +53,11 @@
|
|||
#endif
|
||||
|
||||
#if defined(__WATCOMC__) && defined(__386__)
|
||||
SDL_COMPILE_TIME_ASSERT(intsize, 4==sizeof(int));
|
||||
#define HAVE_WATCOM_ATOMICS
|
||||
extern _inline int _SDL_xchg_watcom(volatile int *a, int v);
|
||||
#pragma aux _SDL_xchg_watcom = \
|
||||
"xchg [ecx], eax" \
|
||||
"lock xchg [ecx], eax" \
|
||||
parm [ecx] [eax] \
|
||||
value [eax] \
|
||||
modify exact [eax];
|
||||
|
|
@ -288,6 +289,10 @@ SDL_AtomicGetPtr(void **a)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef SDL_MEMORY_BARRIER_USES_FUNCTION
|
||||
#error This file should be built in arm mode so the mcr instruction is available for memory barriers
|
||||
#endif
|
||||
|
||||
void
|
||||
SDL_MemoryBarrierReleaseFunction(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -32,11 +32,15 @@
|
|||
#include <atomic.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(__WATCOMC__) && defined(__386__)
|
||||
SDL_COMPILE_TIME_ASSERT(locksize, 4==sizeof(SDL_SpinLock));
|
||||
extern _inline int _SDL_xchg_watcom(volatile int *a, int v);
|
||||
#pragma aux _SDL_xchg_watcom = \
|
||||
"xchg [ecx], eax" \
|
||||
"lock xchg [ecx], eax" \
|
||||
parm [ecx] [eax] \
|
||||
value [eax] \
|
||||
modify exact [eax];
|
||||
|
|
@ -116,12 +120,32 @@ SDL_AtomicTryLock(SDL_SpinLock *lock)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define PAUSE_INSTRUCTION() __asm__ __volatile__("pause\n") /* Some assemblers can't do REP NOP, so go with PAUSE. */
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
#define PAUSE_INSTRUCTION() _mm_pause() /* this is actually "rep nop" and not a SIMD instruction. No inline asm in MSVC x86-64! */
|
||||
#elif defined(__WATCOMC__) && defined(__386__)
|
||||
/* watcom assembler rejects PAUSE if CPU < i686, and it refuses REP NOP as an invalid combination. Hardcode the bytes. */
|
||||
extern _inline void PAUSE_INSTRUCTION(void);
|
||||
#pragma aux PAUSE_INSTRUCTION = "db 0f3h,90h"
|
||||
#else
|
||||
#define PAUSE_INSTRUCTION()
|
||||
#endif
|
||||
|
||||
void
|
||||
SDL_AtomicLock(SDL_SpinLock *lock)
|
||||
{
|
||||
int iterations = 0;
|
||||
/* FIXME: Should we have an eventual timeout? */
|
||||
while (!SDL_AtomicTryLock(lock)) {
|
||||
SDL_Delay(0);
|
||||
if (iterations < 32) {
|
||||
iterations++;
|
||||
PAUSE_INSTRUCTION();
|
||||
} else {
|
||||
/* !!! FIXME: this doesn't definitely give up the current timeslice, it does different things on various platforms. */
|
||||
SDL_Delay(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -89,6 +89,9 @@ static const AudioBootStrap *const bootstrap[] = {
|
|||
#if SDL_AUDIO_DRIVER_FUSIONSOUND
|
||||
&FUSIONSOUND_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_OPENSLES
|
||||
&openslES_bootstrap,
|
||||
#endif
|
||||
#if SDL_AUDIO_DRIVER_ANDROID
|
||||
&ANDROIDAUDIO_bootstrap,
|
||||
#endif
|
||||
|
|
@ -245,12 +248,6 @@ SDL_AudioPlayDevice_Default(_THIS)
|
|||
{ /* no-op. */
|
||||
}
|
||||
|
||||
static int
|
||||
SDL_AudioGetPendingBytes_Default(_THIS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
SDL_AudioGetDeviceBuf_Default(_THIS)
|
||||
{
|
||||
|
|
@ -358,7 +355,6 @@ finish_audio_entry_points_init(void)
|
|||
FILL_STUB(BeginLoopIteration);
|
||||
FILL_STUB(WaitDevice);
|
||||
FILL_STUB(PlayDevice);
|
||||
FILL_STUB(GetPendingBytes);
|
||||
FILL_STUB(GetDeviceBuf);
|
||||
FILL_STUB(CaptureFromDevice);
|
||||
FILL_STUB(FlushCapture);
|
||||
|
|
@ -378,21 +374,57 @@ static int
|
|||
add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
|
||||
{
|
||||
int retval = -1;
|
||||
const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
|
||||
SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
SDL_AudioDeviceItem *item;
|
||||
const SDL_AudioDeviceItem *i;
|
||||
int dupenum = 0;
|
||||
|
||||
SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
|
||||
SDL_assert(name != NULL);
|
||||
|
||||
item = (SDL_AudioDeviceItem *) SDL_malloc(sizeof (SDL_AudioDeviceItem));
|
||||
if (!item) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
item->original_name = SDL_strdup(name);
|
||||
if (!item->original_name) {
|
||||
SDL_free(item);
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
item->dupenum = 0;
|
||||
item->name = item->original_name;
|
||||
item->handle = handle;
|
||||
SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
|
||||
|
||||
SDL_LockMutex(current_audio.detectionLock);
|
||||
|
||||
for (i = *devices; i != NULL; i = i->next) {
|
||||
if (SDL_strcmp(name, i->original_name) == 0) {
|
||||
dupenum = i->dupenum + 1;
|
||||
break; /* stop at the highest-numbered dupe. */
|
||||
}
|
||||
}
|
||||
|
||||
if (dupenum) {
|
||||
const size_t len = SDL_strlen(name) + 16;
|
||||
char *replacement = (char *) SDL_malloc(len);
|
||||
if (!replacement) {
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
SDL_free(item->original_name);
|
||||
SDL_free(item);
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_snprintf(replacement, len, "%s (%d)", name, dupenum + 1);
|
||||
item->dupenum = dupenum;
|
||||
item->name = replacement;
|
||||
}
|
||||
|
||||
item->next = *devices;
|
||||
*devices = item;
|
||||
retval = (*devCount)++;
|
||||
retval = (*devCount)++; /* !!! FIXME: this should be an atomic increment */
|
||||
|
||||
SDL_UnlockMutex(current_audio.detectionLock);
|
||||
|
||||
return retval;
|
||||
|
|
@ -420,6 +452,11 @@ free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
|
|||
if (item->handle != NULL) {
|
||||
current_audio.impl.FreeDeviceHandle(item->handle);
|
||||
}
|
||||
/* these two pointers are the same if not a duplicate devname */
|
||||
if (item->name != item->original_name) {
|
||||
SDL_free(item->name);
|
||||
}
|
||||
SDL_free(item->original_name);
|
||||
SDL_free(item);
|
||||
}
|
||||
*devices = NULL;
|
||||
|
|
@ -451,7 +488,11 @@ void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
|
|||
SDL_assert(get_audio_device(device->id) == device);
|
||||
|
||||
if (!SDL_AtomicGet(&device->enabled)) {
|
||||
return;
|
||||
return; /* don't report disconnects more than once. */
|
||||
}
|
||||
|
||||
if (SDL_AtomicGet(&device->shutdown)) {
|
||||
return; /* don't report disconnect if we're trying to close device. */
|
||||
}
|
||||
|
||||
/* Ends the audio callback and mark the device as STOPPED, but the
|
||||
|
|
@ -606,11 +647,9 @@ SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
|
|||
}
|
||||
|
||||
/* Nothing to do unless we're set up for queueing. */
|
||||
if (device->callbackspec.callback == SDL_BufferQueueDrainCallback) {
|
||||
current_audio.impl.LockDevice(device);
|
||||
retval = ((Uint32) SDL_CountDataQueue(device->buffer_queue)) + current_audio.impl.GetPendingBytes(device);
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
} else if (device->callbackspec.callback == SDL_BufferQueueFillCallback) {
|
||||
if (device->callbackspec.callback == SDL_BufferQueueDrainCallback ||
|
||||
device->callbackspec.callback == SDL_BufferQueueFillCallback)
|
||||
{
|
||||
current_audio.impl.LockDevice(device);
|
||||
retval = (Uint32) SDL_CountDataQueue(device->buffer_queue);
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
|
|
@ -650,8 +689,16 @@ SDL_RunAudio(void *devicep)
|
|||
|
||||
SDL_assert(!device->iscapture);
|
||||
|
||||
#if SDL_AUDIO_DRIVER_ANDROID
|
||||
{
|
||||
/* Set thread priority to THREAD_PRIORITY_AUDIO */
|
||||
extern void Android_JNI_AudioSetThreadPriority(int, int);
|
||||
Android_JNI_AudioSetThreadPriority(device->iscapture, device->id);
|
||||
}
|
||||
#else
|
||||
/* The audio mixing is always a high priority thread */
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
|
||||
#endif
|
||||
|
||||
/* Perform any thread setup */
|
||||
device->threadid = SDL_ThreadID();
|
||||
|
|
@ -747,8 +794,16 @@ SDL_CaptureAudio(void *devicep)
|
|||
|
||||
SDL_assert(device->iscapture);
|
||||
|
||||
#if SDL_AUDIO_DRIVER_ANDROID
|
||||
{
|
||||
/* Set thread priority to THREAD_PRIORITY_AUDIO */
|
||||
extern void Android_JNI_AudioSetThreadPriority(int, int);
|
||||
Android_JNI_AudioSetThreadPriority(device->iscapture, device->id);
|
||||
}
|
||||
#else
|
||||
/* The audio mixing is always a high priority thread */
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
|
||||
#endif
|
||||
|
||||
/* Perform any thread setup */
|
||||
device->threadid = SDL_ThreadID();
|
||||
|
|
@ -971,6 +1026,11 @@ clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *re
|
|||
} else {
|
||||
*devices = next;
|
||||
}
|
||||
/* these two pointers are the same if not a duplicate devname */
|
||||
if (item->name != item->original_name) {
|
||||
SDL_free(item->name);
|
||||
}
|
||||
SDL_free(item->original_name);
|
||||
SDL_free(item);
|
||||
}
|
||||
item = next;
|
||||
|
|
@ -997,7 +1057,6 @@ SDL_GetNumAudioDevices(int iscapture)
|
|||
|
||||
if (!iscapture && current_audio.outputDevicesRemoved) {
|
||||
clean_out_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount, ¤t_audio.outputDevicesRemoved);
|
||||
current_audio.outputDevicesRemoved = SDL_FALSE;
|
||||
}
|
||||
|
||||
retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
|
||||
|
|
@ -1054,16 +1113,14 @@ close_audio_device(SDL_AudioDevice * device)
|
|||
return;
|
||||
}
|
||||
|
||||
if (device->id > 0) {
|
||||
SDL_AudioDevice *opendev = open_devices[device->id - 1];
|
||||
SDL_assert((opendev == device) || (opendev == NULL));
|
||||
if (opendev == device) {
|
||||
open_devices[device->id - 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure the device is paused before we do anything else, so the
|
||||
audio callback definitely won't fire again. */
|
||||
current_audio.impl.LockDevice(device);
|
||||
SDL_AtomicSet(&device->paused, 1);
|
||||
SDL_AtomicSet(&device->shutdown, 1);
|
||||
SDL_AtomicSet(&device->enabled, 0);
|
||||
current_audio.impl.UnlockDevice(device);
|
||||
|
||||
if (device->thread != NULL) {
|
||||
SDL_WaitThread(device->thread, NULL);
|
||||
}
|
||||
|
|
@ -1074,6 +1131,14 @@ close_audio_device(SDL_AudioDevice * device)
|
|||
SDL_free(device->work_buffer);
|
||||
SDL_FreeAudioStream(device->stream);
|
||||
|
||||
if (device->id > 0) {
|
||||
SDL_AudioDevice *opendev = open_devices[device->id - 1];
|
||||
SDL_assert((opendev == device) || (opendev == NULL));
|
||||
if (opendev == device) {
|
||||
open_devices[device->id - 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (device->hidden != NULL) {
|
||||
current_audio.impl.CloseDevice(device);
|
||||
}
|
||||
|
|
@ -1118,8 +1183,9 @@ prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
|
|||
}
|
||||
case 1: /* Mono */
|
||||
case 2: /* Stereo */
|
||||
case 4: /* surround */
|
||||
case 6: /* surround with center and lfe */
|
||||
case 4: /* Quadrophonic */
|
||||
case 6: /* 5.1 surround */
|
||||
case 8: /* 7.1 surround */
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unsupported number of audio channels.");
|
||||
|
|
@ -1312,15 +1378,12 @@ open_audio_device(const char *devname, int iscapture,
|
|||
build_stream = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* !!! FIXME in 2.1: add SDL_AUDIO_ALLOW_SAMPLES_CHANGE flag?
|
||||
As of 2.0.6, we will build a stream to buffer the difference between
|
||||
what the app wants to feed and the device wants to eat, so everyone
|
||||
gets their way. In prior releases, SDL would force the callback to
|
||||
feed at the rate the device requested, adjusted for resampling.
|
||||
*/
|
||||
if (device->spec.samples != obtained->samples) {
|
||||
build_stream = SDL_TRUE;
|
||||
if (allowed_changes & SDL_AUDIO_ALLOW_SAMPLES_CHANGE) {
|
||||
obtained->samples = device->spec.samples;
|
||||
} else {
|
||||
build_stream = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(obtained); /* recalc after possible changes. */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -718,13 +718,19 @@ SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format
|
|||
/* !!! FIXME: remove this if we can get the resampler to work in-place again. */
|
||||
float *dst = (float *) (cvt->buf + srclen);
|
||||
const int dstlen = (cvt->len * cvt->len_mult) - srclen;
|
||||
const int paddingsamples = (ResamplerPadding(inrate, outrate) * chans);
|
||||
const int requestedpadding = ResamplerPadding(inrate, outrate);
|
||||
int paddingsamples;
|
||||
float *padding;
|
||||
|
||||
if (requestedpadding < SDL_MAX_SINT32 / chans) {
|
||||
paddingsamples = requestedpadding * chans;
|
||||
} else {
|
||||
paddingsamples = 0;
|
||||
}
|
||||
SDL_assert(format == AUDIO_F32SYS);
|
||||
|
||||
/* we keep no streaming state here, so pad with silence on both ends. */
|
||||
padding = (float *) SDL_calloc(paddingsamples, sizeof (float));
|
||||
padding = (float *) SDL_calloc(paddingsamples ? paddingsamples : 1, sizeof (float));
|
||||
if (!padding) {
|
||||
SDL_OutOfMemory();
|
||||
return;
|
||||
|
|
@ -889,10 +895,14 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
|
|||
return SDL_SetError("Invalid source channels");
|
||||
} else if (!SDL_SupportedChannelCount(dst_channels)) {
|
||||
return SDL_SetError("Invalid destination channels");
|
||||
} else if (src_rate == 0) {
|
||||
return SDL_SetError("Source rate is zero");
|
||||
} else if (dst_rate == 0) {
|
||||
return SDL_SetError("Destination rate is zero");
|
||||
} else if (src_rate <= 0) {
|
||||
return SDL_SetError("Source rate is equal to or less than zero");
|
||||
} else if (dst_rate <= 0) {
|
||||
return SDL_SetError("Destination rate is equal to or less than zero");
|
||||
} else if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
|
||||
return SDL_SetError("Source rate is too high");
|
||||
} else if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
|
||||
return SDL_SetError("Destination rate is too high");
|
||||
}
|
||||
|
||||
#if DEBUG_CONVERT
|
||||
|
|
@ -1291,7 +1301,7 @@ SDL_NewAudioStream(const SDL_AudioFormat src_format,
|
|||
retval->packetlen = packetlen;
|
||||
retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
|
||||
retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels;
|
||||
retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples, sizeof (float));
|
||||
retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples ? retval->resampler_padding_samples : 1, sizeof (float));
|
||||
|
||||
if (retval->resampler_padding == NULL) {
|
||||
SDL_FreeAudioStream(retval);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -18,6 +18,10 @@
|
|||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_audiodev_c_h_
|
||||
#define SDL_audiodev_c_h_
|
||||
|
||||
#include "SDL.h"
|
||||
#include "../SDL_internal.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
|
@ -35,4 +39,6 @@
|
|||
|
||||
extern void SDL_EnumUnixAudioDevices(const int classic, int (*test)(int));
|
||||
|
||||
#endif /* SDL_audiodev_c_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -25,8 +25,9 @@
|
|||
#include "SDL_cpuinfo.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
/* !!! FIXME: write NEON code. */
|
||||
#define HAVE_NEON_INTRINSICS 0
|
||||
#ifdef __ARM_NEON
|
||||
#define HAVE_NEON_INTRINSICS 1
|
||||
#endif
|
||||
|
||||
#ifdef __SSE2__
|
||||
#define HAVE_SSE2_INTRINSICS 1
|
||||
|
|
@ -62,7 +63,7 @@ SDL_AudioFilter SDL_Convert_F32_to_S32 = NULL;
|
|||
|
||||
#define DIVBY128 0.0078125f
|
||||
#define DIVBY32768 0.000030517578125f
|
||||
#define DIVBY2147483648 0.00000000046566128730773926
|
||||
#define DIVBY8388607 0.00000011920930376163766f
|
||||
|
||||
|
||||
#if NEED_SCALAR_CONVERTER_FALLBACKS
|
||||
|
|
@ -152,7 +153,7 @@ SDL_Convert_S32_to_F32_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
LOG_DEBUG_CONVERT("AUDIO_S32", "AUDIO_F32");
|
||||
|
||||
for (i = cvt->len_cvt / sizeof (Sint32); i; --i, ++src, ++dst) {
|
||||
*dst = (float) (((double) *src) * DIVBY2147483648);
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
}
|
||||
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
|
|
@ -171,10 +172,10 @@ SDL_Convert_F32_to_S8_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample > 1.0f) {
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample < -1.0f) {
|
||||
*dst = -127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
|
|
@ -197,9 +198,9 @@ SDL_Convert_F32_to_U8_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample > 1.0f) {
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample < -1.0f) {
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
|
|
@ -223,10 +224,10 @@ SDL_Convert_F32_to_S16_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample > 1.0f) {
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample < -1.0f) {
|
||||
*dst = -32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
|
|
@ -249,9 +250,9 @@ SDL_Convert_F32_to_U16_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample > 1.0f) {
|
||||
*dst = 65534;
|
||||
} else if (sample < -1.0f) {
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
|
|
@ -275,12 +276,12 @@ SDL_Convert_F32_to_S32_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample > 1.0f) {
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample < -1.0f) {
|
||||
*dst = -2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = (Sint32) -2147483648LL;
|
||||
} else {
|
||||
*dst = (Sint32)((double)sample * 2147483647.0);
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -509,16 +510,6 @@ SDL_Convert_U16_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 4)
|
||||
/* these were added as of gcc-4.0: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19418 */
|
||||
static inline __m128 _mm_castsi128_ps(__m128i __A) {
|
||||
return (__m128) __A;
|
||||
}
|
||||
static inline __m128i _mm_castps_si128(__m128 __A) {
|
||||
return (__m128i) __A;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
|
|
@ -530,23 +521,19 @@ SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (Sint32); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = (float) (((double) *src) * DIVBY2147483648);
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
SDL_assert(!i || ((((size_t) src) & 15) == 0));
|
||||
|
||||
{
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128d divby2147483648 = _mm_set1_pd(DIVBY2147483648);
|
||||
const __m128 divby8388607 = _mm_set1_ps(DIVBY8388607);
|
||||
const __m128i *mmsrc = (const __m128i *) src;
|
||||
while (i >= 4) { /* 4 * sint32 */
|
||||
const __m128i ints = _mm_load_si128(mmsrc);
|
||||
/* bitshift the whole register over, so _mm_cvtepi32_pd can read the top ints in the bottom of the vector. */
|
||||
const __m128d doubles1 = _mm_mul_pd(_mm_cvtepi32_pd(_mm_srli_si128(ints, 8)), divby2147483648);
|
||||
const __m128d doubles2 = _mm_mul_pd(_mm_cvtepi32_pd(ints), divby2147483648);
|
||||
/* convert to float32, bitshift/or to get these into a vector to store. */
|
||||
_mm_store_ps(dst, _mm_castsi128_ps(_mm_or_si128(_mm_slli_si128(_mm_castps_si128(_mm_cvtpd_ps(doubles1)), 8), _mm_castps_si128(_mm_cvtpd_ps(doubles2)))));
|
||||
/* shift out lowest bits so int fits in a float32. Small precision loss, but much faster. */
|
||||
_mm_store_ps(dst, _mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_load_si128(mmsrc), 8)), divby8388607));
|
||||
i -= 4; mmsrc++; dst += 4;
|
||||
}
|
||||
src = (const Sint32 *) mmsrc;
|
||||
|
|
@ -554,7 +541,7 @@ SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (float) (((double) *src) * DIVBY2147483648);
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -574,7 +561,14 @@ SDL_Convert_F32_to_S8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = (Sint8) (*src * 127.0f);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -582,13 +576,15 @@ SDL_Convert_F32_to_S8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
const __m128 mulby127 = _mm_set1_ps(127.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+4), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+8), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+12), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+4)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+8)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+12)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
_mm_store_si128(mmdst, _mm_packs_epi16(_mm_packs_epi32(ints1, ints2), _mm_packs_epi32(ints3, ints4))); /* pack down, store out. */
|
||||
i -= 16; src += 16; mmdst++;
|
||||
}
|
||||
|
|
@ -597,7 +593,14 @@ SDL_Convert_F32_to_S8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (Sint8) (*src * 127.0f);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -618,7 +621,14 @@ SDL_Convert_F32_to_U8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = (Uint8) ((*src + 1.0f) * 127.0f);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -626,14 +636,15 @@ SDL_Convert_F32_to_U8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128 add1 = _mm_set1_ps(1.0f);
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
const __m128 mulby127 = _mm_set1_ps(127.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_load_ps(src), add1), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_load_ps(src+4), add1), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_load_ps(src+8), add1), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_load_ps(src+12), add1), mulby127)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+4)), one), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+8)), one), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_add_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+12)), one), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
_mm_store_si128(mmdst, _mm_packus_epi16(_mm_packs_epi32(ints1, ints2), _mm_packs_epi32(ints3, ints4))); /* pack down, store out. */
|
||||
i -= 16; src += 16; mmdst++;
|
||||
}
|
||||
|
|
@ -642,7 +653,14 @@ SDL_Convert_F32_to_U8_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (Uint8) ((*src + 1.0f) * 127.0f);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -663,7 +681,14 @@ SDL_Convert_F32_to_S16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = (Sint16) (*src * 32767.0f);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -671,11 +696,13 @@ SDL_Convert_F32_to_S16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
const __m128 mulby32767 = _mm_set1_ps(32767.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src), mulby32767)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+4), mulby32767)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
_mm_store_si128(mmdst, _mm_packs_epi32(ints1, ints2)); /* pack to sint16, store out. */
|
||||
i -= 8; src += 8; mmdst++;
|
||||
}
|
||||
|
|
@ -684,7 +711,14 @@ SDL_Convert_F32_to_S16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (Sint16) (*src * 32767.0f);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -705,7 +739,14 @@ SDL_Convert_F32_to_U16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = (Uint16) ((*src + 1.0f) * 32767.0f);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -722,10 +763,12 @@ SDL_Convert_F32_to_U16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
though it looks like dark magic. */
|
||||
const __m128 mulby32767 = _mm_set1_ps(32767.0f);
|
||||
const __m128i topbit = _mm_set1_epi16(-32768);
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src), mulby32767)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(src+4), mulby32767)); /* load 4 floats, convert to sint32 */
|
||||
const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src+4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
_mm_store_si128(mmdst, _mm_xor_si128(_mm_packs_epi32(ints1, ints2), topbit)); /* pack to sint16, xor top bit, store out. */
|
||||
i -= 8; src += 8; mmdst++;
|
||||
}
|
||||
|
|
@ -734,7 +777,14 @@ SDL_Convert_F32_to_U16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (Uint16) ((*src + 1.0f) * 32767.0f);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -755,7 +805,14 @@ SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = (Sint32) (((double) *src) * 2147483647.0);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = (Sint32) -2147483648LL;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
|
@ -763,14 +820,12 @@ SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
{
|
||||
/* Aligned! Do SSE blocks as long as we have 16 bytes available. */
|
||||
const __m128d mulby2147483647 = _mm_set1_pd(2147483647.0);
|
||||
const __m128 one = _mm_set1_ps(1.0f);
|
||||
const __m128 negone = _mm_set1_ps(-1.0f);
|
||||
const __m128 mulby8388607 = _mm_set1_ps(8388607.0f);
|
||||
__m128i *mmdst = (__m128i *) dst;
|
||||
while (i >= 4) { /* 4 * float32 */
|
||||
const __m128 floats = _mm_load_ps(src);
|
||||
/* bitshift the whole register over, so _mm_cvtps_pd can read the top floats in the bottom of the vector. */
|
||||
const __m128d doubles1 = _mm_mul_pd(_mm_cvtps_pd(_mm_castsi128_ps(_mm_srli_si128(_mm_castps_si128(floats), 8))), mulby2147483647);
|
||||
const __m128d doubles2 = _mm_mul_pd(_mm_cvtps_pd(floats), mulby2147483647);
|
||||
_mm_store_si128(mmdst, _mm_or_si128(_mm_slli_si128(_mm_cvtpd_epi32(doubles1), 8), _mm_cvtpd_epi32(doubles2)));
|
||||
_mm_store_si128(mmdst, _mm_slli_epi32(_mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby8388607)), 8)); /* load 4 floats, clamp, convert to sint32 */
|
||||
i -= 4; src += 4; mmdst++;
|
||||
}
|
||||
dst = (Sint32 *) mmdst;
|
||||
|
|
@ -778,7 +833,14 @@ SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (Sint32) (((double) *src) * 2147483647.0);
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = (Sint32) -2147483648LL;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
|
|
@ -789,6 +851,538 @@ SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
|||
#endif
|
||||
|
||||
|
||||
#if HAVE_NEON_INTRINSICS
|
||||
static void SDLCALL
|
||||
SDL_Convert_S8_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Sint8 *src = ((const Sint8 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
float *dst = ((float *) (cvt->buf + cvt->len_cvt * 4)) - 1;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_S8", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
for (i = cvt->len_cvt; i && (((size_t) (dst-15)) & 15); --i, --src, --dst) {
|
||||
*dst = ((float) *src) * DIVBY128;
|
||||
}
|
||||
|
||||
src -= 15; dst -= 15; /* adjust to read NEON blocks from the start. */
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const int8_t *mmsrc = (const int8_t *) src;
|
||||
const float32x4_t divby128 = vdupq_n_f32(DIVBY128);
|
||||
while (i >= 16) { /* 16 * 8-bit */
|
||||
const int8x16_t bytes = vld1q_s8(mmsrc); /* get 16 sint8 into a NEON register. */
|
||||
const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes)); /* convert top 8 bytes to 8 int16 */
|
||||
const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes)); /* convert bottom 8 bytes to 8 int16 */
|
||||
/* split int16 to two int32, then convert to float, then multiply to normalize, store. */
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16hi))), divby128));
|
||||
vst1q_f32(dst+4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16hi))), divby128));
|
||||
vst1q_f32(dst+8, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16lo))), divby128));
|
||||
vst1q_f32(dst+12, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16lo))), divby128));
|
||||
i -= 16; mmsrc -= 16; dst -= 16;
|
||||
}
|
||||
|
||||
src = (const Sint8 *) mmsrc;
|
||||
}
|
||||
|
||||
src += 15; dst += 15; /* adjust for any scalar finishing. */
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = ((float) *src) * DIVBY128;
|
||||
i--; src--; dst--;
|
||||
}
|
||||
|
||||
cvt->len_cvt *= 4;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_U8_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Uint8 *src = ((const Uint8 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
float *dst = ((float *) (cvt->buf + cvt->len_cvt * 4)) - 1;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_U8", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
for (i = cvt->len_cvt; i && (((size_t) (dst-15)) & 15); --i, --src, --dst) {
|
||||
*dst = (((float) *src) * DIVBY128) - 1.0f;
|
||||
}
|
||||
|
||||
src -= 15; dst -= 15; /* adjust to read NEON blocks from the start. */
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const uint8_t *mmsrc = (const uint8_t *) src;
|
||||
const float32x4_t divby128 = vdupq_n_f32(DIVBY128);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
while (i >= 16) { /* 16 * 8-bit */
|
||||
const uint8x16_t bytes = vld1q_u8(mmsrc); /* get 16 uint8 into a NEON register. */
|
||||
const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes)); /* convert top 8 bytes to 8 uint16 */
|
||||
const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes)); /* convert bottom 8 bytes to 8 uint16 */
|
||||
/* split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. */
|
||||
vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16hi))), divby128));
|
||||
vst1q_f32(dst+4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128));
|
||||
vst1q_f32(dst+8, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128));
|
||||
vst1q_f32(dst+12, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128));
|
||||
i -= 16; mmsrc -= 16; dst -= 16;
|
||||
}
|
||||
|
||||
src = (const Uint8 *) mmsrc;
|
||||
}
|
||||
|
||||
src += 15; dst += 15; /* adjust for any scalar finishing. */
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (((float) *src) * DIVBY128) - 1.0f;
|
||||
i--; src--; dst--;
|
||||
}
|
||||
|
||||
cvt->len_cvt *= 4;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_S16_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Sint16 *src = ((const Sint16 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
float *dst = ((float *) (cvt->buf + cvt->len_cvt * 2)) - 1;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_S16", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
for (i = cvt->len_cvt / sizeof (Sint16); i && (((size_t) (dst-7)) & 15); --i, --src, --dst) {
|
||||
*dst = ((float) *src) * DIVBY32768;
|
||||
}
|
||||
|
||||
src -= 7; dst -= 7; /* adjust to read NEON blocks from the start. */
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768);
|
||||
while (i >= 8) { /* 8 * 16-bit */
|
||||
const int16x8_t ints = vld1q_s16((int16_t const *) src); /* get 8 sint16 into a NEON register. */
|
||||
/* split int16 to two int32, then convert to float, then multiply to normalize, store. */
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(ints))), divby32768));
|
||||
vst1q_f32(dst+4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(ints))), divby32768));
|
||||
i -= 8; src -= 8; dst -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
src += 7; dst += 7; /* adjust for any scalar finishing. */
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = ((float) *src) * DIVBY32768;
|
||||
i--; src--; dst--;
|
||||
}
|
||||
|
||||
cvt->len_cvt *= 2;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_U16_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Uint16 *src = ((const Uint16 *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
float *dst = ((float *) (cvt->buf + cvt->len_cvt * 2)) - 1;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_U16", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) */
|
||||
for (i = cvt->len_cvt / sizeof (Sint16); i && (((size_t) (dst-7)) & 15); --i, --src, --dst) {
|
||||
*dst = (((float) *src) * DIVBY32768) - 1.0f;
|
||||
}
|
||||
|
||||
src -= 7; dst -= 7; /* adjust to read NEON blocks from the start. */
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
while (i >= 8) { /* 8 * 16-bit */
|
||||
const uint16x8_t uints = vld1q_u16((uint16_t const *) src); /* get 8 uint16 into a NEON register. */
|
||||
/* split uint16 to two int32, then convert to float, then multiply to normalize, subtract for sign, store. */
|
||||
vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uints))), divby32768));
|
||||
vst1q_f32(dst+4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uints))), divby32768));
|
||||
i -= 8; src -= 8; dst -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
src += 7; dst += 7; /* adjust for any scalar finishing. */
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = (((float) *src) * DIVBY32768) - 1.0f;
|
||||
i--; src--; dst--;
|
||||
}
|
||||
|
||||
cvt->len_cvt *= 2;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_S32_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const Sint32 *src = (const Sint32 *) cvt->buf;
|
||||
float *dst = (float *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_S32", "AUDIO_F32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (Sint32); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t divby8388607 = vdupq_n_f32(DIVBY8388607);
|
||||
const int32_t *mmsrc = (const int32_t *) src;
|
||||
while (i >= 4) { /* 4 * sint32 */
|
||||
/* shift out lowest bits so int fits in a float32. Small precision loss, but much faster. */
|
||||
vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vshrq_n_s32(vld1q_s32(mmsrc), 8)), divby8388607));
|
||||
i -= 4; mmsrc += 4; dst += 4;
|
||||
}
|
||||
src = (const Sint32 *) mmsrc;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
*dst = ((float) (*src>>8)) * DIVBY8388607;
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_S8_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Sint8 *dst = (Sint8 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S8 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby127 = vdupq_n_f32(127.0f);
|
||||
int8_t *mmdst = (int8_t *) dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+4)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints3 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+8)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints4 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+12)), one), mulby127)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int8x8_t i8lo = vmovn_s16(vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); /* narrow to sint16, combine, narrow to sint8 */
|
||||
const int8x8_t i8hi = vmovn_s16(vcombine_s16(vmovn_s32(ints3), vmovn_s32(ints4))); /* narrow to sint16, combine, narrow to sint8 */
|
||||
vst1q_s8(mmdst, vcombine_s8(i8lo, i8hi)); /* combine to int8x16_t, store out */
|
||||
i -= 16; src += 16; mmdst += 16;
|
||||
}
|
||||
dst = (Sint8 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 127;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -128;
|
||||
} else {
|
||||
*dst = (Sint8)(sample * 127.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
cvt->len_cvt /= 4;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_S8);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_U8_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Uint8 *dst = (Uint8 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_U8 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby127 = vdupq_n_f32(127.0f);
|
||||
uint8_t *mmdst = (uint8_t *) dst;
|
||||
while (i >= 16) { /* 16 * float32 */
|
||||
const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+4)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints3 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+8)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints4 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+12)), one), one), mulby127)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint8x8_t ui8lo = vmovn_u16(vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); /* narrow to uint16, combine, narrow to uint8 */
|
||||
const uint8x8_t ui8hi = vmovn_u16(vcombine_u16(vmovn_u32(uints3), vmovn_u32(uints4))); /* narrow to uint16, combine, narrow to uint8 */
|
||||
vst1q_u8(mmdst, vcombine_u8(ui8lo, ui8hi)); /* combine to uint8x16_t, store out */
|
||||
i -= 16; src += 16; mmdst += 16;
|
||||
}
|
||||
|
||||
dst = (Uint8 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 255;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint8)((sample + 1.0f) * 127.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
cvt->len_cvt /= 4;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_U8);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_S16_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Sint16 *dst = (Sint16 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S16 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby32767 = vdupq_n_f32(32767.0f);
|
||||
int16_t *mmdst = (int16_t *) dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
|
||||
vst1q_s16(mmdst, vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); /* narrow to sint16, combine, store out. */
|
||||
i -= 8; src += 8; mmdst += 8;
|
||||
}
|
||||
dst = (Sint16 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 32767;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = -32768;
|
||||
} else {
|
||||
*dst = (Sint16)(sample * 32767.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
cvt->len_cvt /= 2;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_S16SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_U16_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Uint16 *dst = (Uint16 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_U16 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
|
||||
/* Make sure src is aligned too. */
|
||||
if ((((size_t) src) & 15) == 0) {
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby32767 = vdupq_n_f32(32767.0f);
|
||||
uint16_t *mmdst = (uint16_t *) dst;
|
||||
while (i >= 8) { /* 8 * float32 */
|
||||
const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby32767)); /* load 4 floats, clamp, convert to uint32 */
|
||||
const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src+4)), one), one), mulby32767)); /* load 4 floats, clamp, convert to uint32 */
|
||||
vst1q_u16(mmdst, vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); /* narrow to uint16, combine, store out. */
|
||||
i -= 8; src += 8; mmdst += 8;
|
||||
}
|
||||
dst = (Uint16 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 65535;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = 0;
|
||||
} else {
|
||||
*dst = (Uint16)((sample + 1.0f) * 32767.0f);
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
cvt->len_cvt /= 2;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_U16SYS);
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL
|
||||
SDL_Convert_F32_to_S32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
|
||||
{
|
||||
const float *src = (const float *) cvt->buf;
|
||||
Sint32 *dst = (Sint32 *) cvt->buf;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S32 (using NEON)");
|
||||
|
||||
/* Get dst aligned to 16 bytes */
|
||||
for (i = cvt->len_cvt / sizeof (float); i && (((size_t) dst) & 15); --i, ++src, ++dst) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = (-2147483647) - 1;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(!i || ((((size_t) dst) & 15) == 0));
|
||||
SDL_assert(!i || ((((size_t) src) & 15) == 0));
|
||||
|
||||
{
|
||||
/* Aligned! Do NEON blocks as long as we have 16 bytes available. */
|
||||
const float32x4_t one = vdupq_n_f32(1.0f);
|
||||
const float32x4_t negone = vdupq_n_f32(-1.0f);
|
||||
const float32x4_t mulby8388607 = vdupq_n_f32(8388607.0f);
|
||||
int32_t *mmdst = (int32_t *) dst;
|
||||
while (i >= 4) { /* 4 * float32 */
|
||||
vst1q_s32(mmdst, vshlq_n_s32(vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby8388607)), 8));
|
||||
i -= 4; src += 4; mmdst += 4;
|
||||
}
|
||||
dst = (Sint32 *) mmdst;
|
||||
}
|
||||
|
||||
/* Finish off any leftovers with scalar operations. */
|
||||
while (i) {
|
||||
const float sample = *src;
|
||||
if (sample >= 1.0f) {
|
||||
*dst = 2147483647;
|
||||
} else if (sample <= -1.0f) {
|
||||
*dst = (-2147483647) - 1;
|
||||
} else {
|
||||
*dst = ((Sint32)(sample * 8388607.0f)) << 8;
|
||||
}
|
||||
i--; src++; dst++;
|
||||
}
|
||||
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index](cvt, AUDIO_S32SYS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void SDL_ChooseAudioConverters(void)
|
||||
{
|
||||
static SDL_bool converters_chosen = SDL_FALSE;
|
||||
|
|
@ -817,6 +1411,13 @@ void SDL_ChooseAudioConverters(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_NEON_INTRINSICS
|
||||
if (SDL_HasNEON()) {
|
||||
SET_CONVERTER_FUNCS(NEON);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NEED_SCALAR_CONVERTER_FALLBACKS
|
||||
SET_CONVERTER_FUNCS(Scalar);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -71,7 +71,6 @@ typedef struct SDL_AudioDriverImpl
|
|||
void (*BeginLoopIteration)(_THIS); /* Called by audio thread at top of loop */
|
||||
void (*WaitDevice) (_THIS);
|
||||
void (*PlayDevice) (_THIS);
|
||||
int (*GetPendingBytes) (_THIS);
|
||||
Uint8 *(*GetDeviceBuf) (_THIS);
|
||||
int (*CaptureFromDevice) (_THIS, void *buffer, int buflen);
|
||||
void (*FlushCapture) (_THIS);
|
||||
|
|
@ -98,8 +97,10 @@ typedef struct SDL_AudioDriverImpl
|
|||
typedef struct SDL_AudioDeviceItem
|
||||
{
|
||||
void *handle;
|
||||
char *name;
|
||||
char *original_name;
|
||||
int dupenum;
|
||||
struct SDL_AudioDeviceItem *next;
|
||||
char name[SDL_VARIABLE_LENGTH_ARRAY];
|
||||
} SDL_AudioDeviceItem;
|
||||
|
||||
|
||||
|
|
@ -202,6 +203,7 @@ extern AudioBootStrap COREAUDIO_bootstrap;
|
|||
extern AudioBootStrap DISKAUDIO_bootstrap;
|
||||
extern AudioBootStrap DUMMYAUDIO_bootstrap;
|
||||
extern AudioBootStrap FUSIONSOUND_bootstrap;
|
||||
extern AudioBootStrap openslES_bootstrap;
|
||||
extern AudioBootStrap ANDROIDAUDIO_bootstrap;
|
||||
extern AudioBootStrap PSPAUDIO_bootstrap;
|
||||
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -20,11 +20,12 @@
|
|||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
/* WAVE files are little-endian */
|
||||
/* RIFF WAVE files are little-endian */
|
||||
|
||||
/*******************************************/
|
||||
/* Define values for Microsoft WAVE format */
|
||||
/*******************************************/
|
||||
/* FOURCC */
|
||||
#define RIFF 0x46464952 /* "RIFF" */
|
||||
#define WAVE 0x45564157 /* "WAVE" */
|
||||
#define FACT 0x74636166 /* "fact" */
|
||||
|
|
@ -33,45 +34,116 @@
|
|||
#define JUNK 0x4B4E554A /* "JUNK" */
|
||||
#define FMT 0x20746D66 /* "fmt " */
|
||||
#define DATA 0x61746164 /* "data" */
|
||||
/* Format tags */
|
||||
#define UNKNOWN_CODE 0x0000
|
||||
#define PCM_CODE 0x0001
|
||||
#define MS_ADPCM_CODE 0x0002
|
||||
#define IEEE_FLOAT_CODE 0x0003
|
||||
#define ALAW_CODE 0x0006
|
||||
#define MULAW_CODE 0x0007
|
||||
#define IMA_ADPCM_CODE 0x0011
|
||||
#define MP3_CODE 0x0055
|
||||
#define MPEG_CODE 0x0050
|
||||
#define MPEGLAYER3_CODE 0x0055
|
||||
#define EXTENSIBLE_CODE 0xFFFE
|
||||
#define WAVE_MONO 1
|
||||
#define WAVE_STEREO 2
|
||||
|
||||
/* Normally, these three chunks come consecutively in a WAVE file */
|
||||
typedef struct WaveFMT
|
||||
/* Stores the WAVE format information. */
|
||||
typedef struct WaveFormat
|
||||
{
|
||||
/* Not saved in the chunk we read:
|
||||
Uint32 FMTchunk;
|
||||
Uint32 fmtlen;
|
||||
*/
|
||||
Uint16 encoding;
|
||||
Uint16 channels; /* 1 = mono, 2 = stereo */
|
||||
Uint32 frequency; /* One of 11025, 22050, or 44100 Hz */
|
||||
Uint32 byterate; /* Average bytes per second */
|
||||
Uint16 blockalign; /* Bytes per sample block */
|
||||
Uint16 bitspersample; /* One of 8, 12, 16, or 4 for ADPCM */
|
||||
} WaveFMT;
|
||||
Uint16 formattag; /* Raw value of the first field in the fmt chunk data. */
|
||||
Uint16 encoding; /* Actual encoding, possibly from the extensible header. */
|
||||
Uint16 channels; /* Number of channels. */
|
||||
Uint32 frequency; /* Sampling rate in Hz. */
|
||||
Uint32 byterate; /* Average bytes per second. */
|
||||
Uint16 blockalign; /* Bytes per block. */
|
||||
Uint16 bitspersample; /* Currently supported are 8, 16, 24, 32, and 4 for ADPCM. */
|
||||
|
||||
/* The general chunk found in the WAVE file */
|
||||
typedef struct Chunk
|
||||
{
|
||||
Uint32 magic;
|
||||
Uint32 length;
|
||||
Uint8 *data;
|
||||
} Chunk;
|
||||
/* Extra information size. Number of extra bytes starting at byte 18 in the
|
||||
* fmt chunk data. This is at least 22 for the extensible header.
|
||||
*/
|
||||
Uint16 extsize;
|
||||
|
||||
typedef struct WaveExtensibleFMT
|
||||
{
|
||||
WaveFMT format;
|
||||
Uint16 size;
|
||||
Uint16 validbits;
|
||||
/* Extensible WAVE header fields */
|
||||
Uint16 validsamplebits;
|
||||
Uint32 samplesperblock; /* For compressed formats. Can be zero. Actually 16 bits in the header. */
|
||||
Uint32 channelmask;
|
||||
Uint8 subformat[16]; /* a GUID. */
|
||||
} WaveExtensibleFMT;
|
||||
Uint8 subformat[16]; /* A format GUID. */
|
||||
} WaveFormat;
|
||||
|
||||
/* Stores information on the fact chunk. */
|
||||
typedef struct WaveFact {
|
||||
/* Represents the state of the fact chunk in the WAVE file.
|
||||
* Set to -1 if the fact chunk is invalid.
|
||||
* Set to 0 if the fact chunk is not present
|
||||
* Set to 1 if the fact chunk is present and valid.
|
||||
* Set to 2 if samplelength is going to be used as the number of sample frames.
|
||||
*/
|
||||
Sint32 status;
|
||||
|
||||
/* Version 1 of the RIFF specification calls the field in the fact chunk
|
||||
* dwFileSize. The Standards Update then calls it dwSampleLength and specifies
|
||||
* that it is 'the length of the data in samples'. WAVE files from Windows
|
||||
* with this chunk have it set to the samples per channel (sample frames).
|
||||
* This is useful to truncate compressed audio to a specific sample count
|
||||
* because a compressed block is usually decoded to a fixed number of
|
||||
* sample frames.
|
||||
*/
|
||||
Uint32 samplelength; /* Raw sample length value from the fact chunk. */
|
||||
} WaveFact;
|
||||
|
||||
/* Generic struct for the chunks in the WAVE file. */
|
||||
typedef struct WaveChunk
|
||||
{
|
||||
Uint32 fourcc; /* FOURCC of the chunk. */
|
||||
Uint32 length; /* Size of the chunk data. */
|
||||
Sint64 position; /* Position of the data in the stream. */
|
||||
Uint8 *data; /* When allocated, this points to the chunk data. length is used for the malloc size. */
|
||||
size_t size; /* Number of bytes in data that could be read from the stream. Can be smaller than length. */
|
||||
} WaveChunk;
|
||||
|
||||
/* Controls how the size of the RIFF chunk affects the loading of a WAVE file. */
|
||||
typedef enum WaveRiffSizeHint {
|
||||
RiffSizeNoHint,
|
||||
RiffSizeForce,
|
||||
RiffSizeIgnoreZero,
|
||||
RiffSizeIgnore,
|
||||
RiffSizeMaximum
|
||||
} WaveRiffSizeHint;
|
||||
|
||||
/* Controls how a truncated WAVE file is handled. */
|
||||
typedef enum WaveTruncationHint {
|
||||
TruncNoHint,
|
||||
TruncVeryStrict,
|
||||
TruncStrict,
|
||||
TruncDropFrame,
|
||||
TruncDropBlock
|
||||
} WaveTruncationHint;
|
||||
|
||||
/* Controls how the fact chunk affects the loading of a WAVE file. */
|
||||
typedef enum WaveFactChunkHint {
|
||||
FactNoHint,
|
||||
FactTruncate,
|
||||
FactStrict,
|
||||
FactIgnoreZero,
|
||||
FactIgnore
|
||||
} WaveFactChunkHint;
|
||||
|
||||
typedef struct WaveFile
|
||||
{
|
||||
WaveChunk chunk;
|
||||
WaveFormat format;
|
||||
WaveFact fact;
|
||||
|
||||
/* Number of sample frames that will be decoded. Calculated either with the
|
||||
* size of the data chunk or, if the appropriate hint is enabled, with the
|
||||
* sample length value from the fact chunk.
|
||||
*/
|
||||
Sint64 sampleframes;
|
||||
|
||||
void *decoderdata; /* Some decoders require extra data for a state. */
|
||||
|
||||
WaveRiffSizeHint riffhint;
|
||||
WaveTruncationHint trunchint;
|
||||
WaveFactChunkHint facthint;
|
||||
} WaveFile;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
#if SDL_AUDIO_DRIVER_ALSA
|
||||
|
||||
#ifndef SDL_ALSA_NON_BLOCKING
|
||||
#define SDL_ALSA_NON_BLOCKING 0
|
||||
#endif
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
|
@ -68,7 +72,9 @@ static int (*ALSA_snd_pcm_hw_params_set_period_size_near)
|
|||
(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
|
||||
static int (*ALSA_snd_pcm_hw_params_get_period_size)
|
||||
(const snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
|
||||
static int (*ALSA_snd_pcm_hw_params_set_periods_near)
|
||||
static int (*ALSA_snd_pcm_hw_params_set_periods_min)
|
||||
(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
|
||||
static int (*ALSA_snd_pcm_hw_params_set_periods_first)
|
||||
(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
|
||||
static int (*ALSA_snd_pcm_hw_params_get_periods)
|
||||
(const snd_pcm_hw_params_t *, unsigned int *, int *);
|
||||
|
|
@ -90,6 +96,7 @@ static int (*ALSA_snd_pcm_reset)(snd_pcm_t *);
|
|||
static int (*ALSA_snd_device_name_hint) (int, const char *, void ***);
|
||||
static char* (*ALSA_snd_device_name_get_hint) (const void *, const char *);
|
||||
static int (*ALSA_snd_device_name_free_hint) (void **);
|
||||
static snd_pcm_sframes_t (*ALSA_snd_pcm_avail)(snd_pcm_t *);
|
||||
#ifdef SND_CHMAP_API_VERSION
|
||||
static snd_pcm_chmap_t* (*ALSA_snd_pcm_get_chmap) (snd_pcm_t *);
|
||||
static int (*ALSA_snd_pcm_chmap_print) (const snd_pcm_chmap_t *map, size_t maxlen, char *buf);
|
||||
|
|
@ -143,7 +150,8 @@ load_alsa_syms(void)
|
|||
SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_near);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_min);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_first);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_get_periods);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_buffer_size_near);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_get_buffer_size);
|
||||
|
|
@ -158,6 +166,7 @@ load_alsa_syms(void)
|
|||
SDL_ALSA_SYM(snd_device_name_hint);
|
||||
SDL_ALSA_SYM(snd_device_name_get_hint);
|
||||
SDL_ALSA_SYM(snd_device_name_free_hint);
|
||||
SDL_ALSA_SYM(snd_pcm_avail);
|
||||
#ifdef SND_CHMAP_API_VERSION
|
||||
SDL_ALSA_SYM(snd_pcm_get_chmap);
|
||||
SDL_ALSA_SYM(snd_pcm_chmap_print);
|
||||
|
|
@ -243,7 +252,24 @@ get_audio_device(void *handle, const int channels)
|
|||
static void
|
||||
ALSA_WaitDevice(_THIS)
|
||||
{
|
||||
/* We're in blocking mode, so there's nothing to do here */
|
||||
#if SDL_ALSA_NON_BLOCKING
|
||||
const snd_pcm_sframes_t needed = (snd_pcm_sframes_t) this->spec.samples;
|
||||
while (SDL_AtomicGet(&this->enabled)) {
|
||||
const snd_pcm_sframes_t rc = ALSA_snd_pcm_avail(this->hidden->pcm_handle);
|
||||
if ((rc < 0) && (rc != -EAGAIN)) {
|
||||
/* Hmm, not much we can do - abort */
|
||||
fprintf(stderr, "ALSA snd_pcm_avail failed (unrecoverable): %s\n",
|
||||
ALSA_snd_strerror(rc));
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
return;
|
||||
} else if (rc < needed) {
|
||||
const Uint32 delay = ((needed - (SDL_max(rc, 0))) * 1000) / this->spec.freq;
|
||||
SDL_Delay(SDL_max(delay, 10));
|
||||
} else {
|
||||
break; /* ready to go! */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -422,7 +448,7 @@ static void
|
|||
ALSA_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden->pcm_handle) {
|
||||
/* Wait for the submitted audio to drain
|
||||
/* Wait for the submitted audio to drain
|
||||
ALSA_snd_pcm_drop() can hang, so don't use that.
|
||||
*/
|
||||
Uint32 delay = ((this->spec.samples * 1000) / this->spec.freq) * 2;
|
||||
|
|
@ -435,10 +461,38 @@ ALSA_CloseDevice(_THIS)
|
|||
}
|
||||
|
||||
static int
|
||||
ALSA_finalize_hardware(_THIS, snd_pcm_hw_params_t *hwparams, int override)
|
||||
ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params)
|
||||
{
|
||||
int status;
|
||||
snd_pcm_uframes_t bufsize;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_uframes_t persize;
|
||||
unsigned int periods;
|
||||
|
||||
/* Copy the hardware parameters for this setup */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
ALSA_snd_pcm_hw_params_copy(hwparams, params);
|
||||
|
||||
/* Attempt to match the period size to the requested buffer size */
|
||||
persize = this->spec.samples;
|
||||
status = ALSA_snd_pcm_hw_params_set_period_size_near(
|
||||
this->hidden->pcm_handle, hwparams, &persize, NULL);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Need to at least double buffer */
|
||||
periods = 2;
|
||||
status = ALSA_snd_pcm_hw_params_set_periods_min(
|
||||
this->hidden->pcm_handle, hwparams, &periods, NULL);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
status = ALSA_snd_pcm_hw_params_set_periods_first(
|
||||
this->hidden->pcm_handle, hwparams, &periods, NULL);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* "set" the hardware with the desired parameters */
|
||||
status = ALSA_snd_pcm_hw_params(this->hidden->pcm_handle, hwparams);
|
||||
|
|
@ -446,25 +500,13 @@ ALSA_finalize_hardware(_THIS, snd_pcm_hw_params_t *hwparams, int override)
|
|||
return(-1);
|
||||
}
|
||||
|
||||
/* Get samples for the actual buffer size */
|
||||
status = ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
if ( !override && bufsize != this->spec.samples * 2 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* !!! FIXME: Is this safe to do? */
|
||||
this->spec.samples = bufsize / 2;
|
||||
this->spec.samples = persize;
|
||||
|
||||
/* This is useful for debugging */
|
||||
if ( SDL_getenv("SDL_AUDIO_ALSA_DEBUG") ) {
|
||||
snd_pcm_uframes_t persize = 0;
|
||||
unsigned int periods = 0;
|
||||
snd_pcm_uframes_t bufsize;
|
||||
|
||||
ALSA_snd_pcm_hw_params_get_period_size(hwparams, &persize, NULL);
|
||||
ALSA_snd_pcm_hw_params_get_periods(hwparams, &periods, NULL);
|
||||
ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize);
|
||||
|
||||
fprintf(stderr,
|
||||
"ALSA: period size = %ld, periods = %u, buffer size = %lu\n",
|
||||
|
|
@ -474,78 +516,6 @@ ALSA_finalize_hardware(_THIS, snd_pcm_hw_params_t *hwparams, int override)
|
|||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_set_period_size(_THIS, snd_pcm_hw_params_t *params, int override)
|
||||
{
|
||||
const char *env;
|
||||
int status;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_uframes_t frames;
|
||||
unsigned int periods;
|
||||
|
||||
/* Copy the hardware parameters for this setup */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
ALSA_snd_pcm_hw_params_copy(hwparams, params);
|
||||
|
||||
if ( !override ) {
|
||||
env = SDL_getenv("SDL_AUDIO_ALSA_SET_PERIOD_SIZE");
|
||||
if ( env ) {
|
||||
override = SDL_atoi(env);
|
||||
if ( override == 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frames = this->spec.samples;
|
||||
status = ALSA_snd_pcm_hw_params_set_period_size_near(
|
||||
this->hidden->pcm_handle, hwparams, &frames, NULL);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
periods = 2;
|
||||
status = ALSA_snd_pcm_hw_params_set_periods_near(
|
||||
this->hidden->pcm_handle, hwparams, &periods, NULL);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return ALSA_finalize_hardware(this, hwparams, override);
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params, int override)
|
||||
{
|
||||
const char *env;
|
||||
int status;
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_uframes_t frames;
|
||||
|
||||
/* Copy the hardware parameters for this setup */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
ALSA_snd_pcm_hw_params_copy(hwparams, params);
|
||||
|
||||
if ( !override ) {
|
||||
env = SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE");
|
||||
if ( env ) {
|
||||
override = SDL_atoi(env);
|
||||
if ( override == 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frames = this->spec.samples * 2;
|
||||
status = ALSA_snd_pcm_hw_params_set_buffer_size_near(
|
||||
this->hidden->pcm_handle, hwparams, &frames);
|
||||
if ( status < 0 ) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return ALSA_finalize_hardware(this, hwparams, override);
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
|
|
@ -692,14 +662,11 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
this->spec.freq = rate;
|
||||
|
||||
/* Set the buffer size, in samples */
|
||||
if ( ALSA_set_period_size(this, hwparams, 0) < 0 &&
|
||||
ALSA_set_buffer_size(this, hwparams, 0) < 0 ) {
|
||||
/* Failed to set desired buffer size, do the best you can... */
|
||||
status = ALSA_set_period_size(this, hwparams, 1);
|
||||
if (status < 0) {
|
||||
return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
|
||||
}
|
||||
status = ALSA_set_buffer_size(this, hwparams);
|
||||
if (status < 0) {
|
||||
return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
|
||||
}
|
||||
|
||||
/* Set the software parameters */
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
|
||||
|
|
@ -737,9 +704,11 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
|
||||
}
|
||||
|
||||
#if !SDL_ALSA_NON_BLOCKING
|
||||
if (!iscapture) {
|
||||
ALSA_snd_pcm_nonblock(pcm_handle, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 0;
|
||||
|
|
@ -828,7 +797,7 @@ ALSA_HotplugThread(void *arg)
|
|||
ALSA_Device *seen;
|
||||
ALSA_Device *prev;
|
||||
|
||||
if (ALSA_snd_device_name_hint(-1, "pcm", &hints) != -1) {
|
||||
if (ALSA_snd_device_name_hint(-1, "pcm", &hints) == 0) {
|
||||
int i, j;
|
||||
const char *match = NULL;
|
||||
int bestmatch = 0xFFFF;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -57,7 +57,9 @@ ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
|
||||
test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
while (test_format != 0) { /* no "UNKNOWN" constant */
|
||||
if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
|
||||
if ((test_format == AUDIO_U8) ||
|
||||
(test_format == AUDIO_S16) ||
|
||||
(test_format == AUDIO_F32)) {
|
||||
this->spec.format = test_format;
|
||||
break;
|
||||
}
|
||||
|
|
@ -69,25 +71,8 @@ ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
return SDL_SetError("No compatible audio format!");
|
||||
}
|
||||
|
||||
if (this->spec.channels > 1) {
|
||||
this->spec.channels = 2;
|
||||
} else {
|
||||
this->spec.channels = 1;
|
||||
}
|
||||
|
||||
if (this->spec.freq < 8000) {
|
||||
this->spec.freq = 8000;
|
||||
}
|
||||
if (this->spec.freq > 48000) {
|
||||
this->spec.freq = 48000;
|
||||
}
|
||||
|
||||
/* TODO: pass in/return a (Java) device ID */
|
||||
this->spec.samples = Android_JNI_OpenAudioDevice(iscapture, this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
|
||||
|
||||
if (this->spec.samples == 0) {
|
||||
/* Init failed? */
|
||||
return SDL_SetError("Java-side initialization failed!");
|
||||
if (Android_JNI_OpenAudioDevice(iscapture, &this->spec) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
#include "SDL_name.h"
|
||||
#include "SDL_loadso.h"
|
||||
#else
|
||||
#define SDL_NAME(X) X
|
||||
#define SDL_NAME(X) X
|
||||
#endif
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -354,7 +354,7 @@ static BOOL update_audio_session(_THIS, SDL_bool open)
|
|||
return NO;
|
||||
}
|
||||
|
||||
if (open_playback_devices + open_capture_devices == 1) {
|
||||
if (open && (open_playback_devices + open_capture_devices) == 1) {
|
||||
if (![session setActive:YES error:&err]) {
|
||||
NSString *desc = err.description;
|
||||
SDL_SetError("Could not activate Audio Session: %s", desc.UTF8String);
|
||||
|
|
@ -376,25 +376,26 @@ static BOOL update_audio_session(_THIS, SDL_bool open)
|
|||
/* An interruption end notification is not guaranteed to be sent if
|
||||
we were previously interrupted... resuming if needed when the app
|
||||
becomes active seems to be the way to go. */
|
||||
// Note: object: below needs to be nil, as otherwise it filters by the object, and session doesn't send foreground / active notifications. johna
|
||||
[center addObserver:listener
|
||||
selector:@selector(applicationBecameActive:)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:session];
|
||||
object:nil];
|
||||
|
||||
[center addObserver:listener
|
||||
selector:@selector(applicationBecameActive:)
|
||||
name:UIApplicationWillEnterForegroundNotification
|
||||
object:session];
|
||||
object:nil];
|
||||
|
||||
this->hidden->interruption_listener = CFBridgingRetain(listener);
|
||||
} else {
|
||||
if (this->hidden->interruption_listener != NULL) {
|
||||
SDLInterruptionListener *listener = nil;
|
||||
listener = (SDLInterruptionListener *) CFBridgingRelease(this->hidden->interruption_listener);
|
||||
[center removeObserver:listener];
|
||||
@synchronized (listener) {
|
||||
listener.device = NULL;
|
||||
}
|
||||
[center removeObserver:listener];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -728,6 +729,8 @@ audioqueue_thread(void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
|
||||
|
||||
/* init was successful, alert parent thread and start running... */
|
||||
SDL_SemPost(this->hidden->ready_semaphore);
|
||||
while (!SDL_AtomicGet(&this->hidden->shutdown)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -477,8 +477,8 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
SDL_bool tried_format = SDL_FALSE;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
LPGUID guid = (LPGUID) handle;
|
||||
DWORD bufsize;
|
||||
|
||||
DWORD bufsize;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
|
|
@ -526,7 +526,7 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
(int) (DSBSIZE_MAX / numchunks));
|
||||
} else {
|
||||
int rc;
|
||||
WAVEFORMATEX wfmt;
|
||||
WAVEFORMATEX wfmt;
|
||||
SDL_zero(wfmt);
|
||||
if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
|
||||
wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -35,6 +35,7 @@ FeedAudioDevice(_THIS, const void *buf, const int buflen)
|
|||
{
|
||||
const int framelen = (SDL_AUDIO_BITSIZE(this->spec.format) / 8) * this->spec.channels;
|
||||
EM_ASM_ARGS({
|
||||
var SDL2 = Module['SDL2'];
|
||||
var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels'];
|
||||
for (var c = 0; c < numChannels; ++c) {
|
||||
var channelData = SDL2.audio.currentOutputBuffer['getChannelData'](c);
|
||||
|
|
@ -100,6 +101,7 @@ HandleCaptureProcess(_THIS)
|
|||
}
|
||||
|
||||
EM_ASM_ARGS({
|
||||
var SDL2 = Module['SDL2'];
|
||||
var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
|
||||
for (var c = 0; c < numChannels; ++c) {
|
||||
var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(c);
|
||||
|
|
@ -145,6 +147,7 @@ static void
|
|||
EMSCRIPTENAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
EM_ASM_({
|
||||
var SDL2 = Module['SDL2'];
|
||||
if ($0) {
|
||||
if (SDL2.capture.silenceTimer !== undefined) {
|
||||
clearTimeout(SDL2.capture.silenceTimer);
|
||||
|
|
@ -196,11 +199,12 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscaptu
|
|||
|
||||
/* based on parts of library_sdl.js */
|
||||
|
||||
/* create context (TODO: this puts stuff in the global namespace...)*/
|
||||
/* create context */
|
||||
result = EM_ASM_INT({
|
||||
if(typeof(SDL2) === 'undefined') {
|
||||
SDL2 = {};
|
||||
if(typeof(Module['SDL2']) === 'undefined') {
|
||||
Module['SDL2'] = {};
|
||||
}
|
||||
var SDL2 = Module['SDL2'];
|
||||
if (!$0) {
|
||||
SDL2.audio = {};
|
||||
} else {
|
||||
|
|
@ -246,9 +250,13 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscaptu
|
|||
}
|
||||
SDL_zerop(this->hidden);
|
||||
#endif
|
||||
this->hidden = (struct SDL_PrivateAudioData *)0x1;
|
||||
|
||||
/* limit to native freq */
|
||||
this->spec.freq = EM_ASM_INT_V({ return SDL2.audioContext.sampleRate; });
|
||||
this->spec.freq = EM_ASM_INT_V({
|
||||
var SDL2 = Module['SDL2'];
|
||||
return SDL2.audioContext.sampleRate;
|
||||
});
|
||||
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
|
|
@ -270,6 +278,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscaptu
|
|||
to be honest. */
|
||||
|
||||
EM_ASM_({
|
||||
var SDL2 = Module['SDL2'];
|
||||
var have_microphone = function(stream) {
|
||||
//console.log('SDL audio capture: we have a microphone! Replacing silence callback.');
|
||||
if (SDL2.capture.silenceTimer !== undefined) {
|
||||
|
|
@ -282,7 +291,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscaptu
|
|||
if ((SDL2 === undefined) || (SDL2.capture === undefined)) { return; }
|
||||
audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
|
||||
SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
|
||||
Runtime.dynCall('vi', $2, [$3]);
|
||||
dynCall('vi', $2, [$3]);
|
||||
};
|
||||
SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
|
||||
SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
|
||||
|
|
@ -298,7 +307,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscaptu
|
|||
SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0);
|
||||
var silence_callback = function() {
|
||||
SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
|
||||
Runtime.dynCall('vi', $2, [$3]);
|
||||
dynCall('vi', $2, [$3]);
|
||||
};
|
||||
|
||||
SDL2.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000);
|
||||
|
|
@ -312,11 +321,12 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscaptu
|
|||
} else {
|
||||
/* setup a ScriptProcessorNode */
|
||||
EM_ASM_ARGS({
|
||||
var SDL2 = Module['SDL2'];
|
||||
SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
|
||||
SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
|
||||
if ((SDL2 === undefined) || (SDL2.audio === undefined)) { return; }
|
||||
SDL2.audio.currentOutputBuffer = e['outputBuffer'];
|
||||
Runtime.dynCall('vi', $2, [$3]);
|
||||
dynCall('vi', $2, [$3]);
|
||||
};
|
||||
SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
|
||||
}, this->spec.channels, this->spec.samples, HandleAudioProcess, this);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -44,7 +44,9 @@ static const char ** (*JACK_jack_get_ports) (jack_client_t *, const char *, cons
|
|||
static jack_nframes_t (*JACK_jack_get_sample_rate) (jack_client_t *);
|
||||
static jack_nframes_t (*JACK_jack_get_buffer_size) (jack_client_t *);
|
||||
static jack_port_t * (*JACK_jack_port_register) (jack_client_t *, const char *, const char *, unsigned long, unsigned long);
|
||||
static jack_port_t * (*JACK_jack_port_by_name) (jack_client_t *, const char *);
|
||||
static const char * (*JACK_jack_port_name) (const jack_port_t *);
|
||||
static const char * (*JACK_jack_port_type) (const jack_port_t *);
|
||||
static int (*JACK_jack_connect) (jack_client_t *, const char *, const char *);
|
||||
static int (*JACK_jack_set_process_callback) (jack_client_t *, JackProcessCallback, void *);
|
||||
|
||||
|
|
@ -135,7 +137,9 @@ load_jack_syms(void)
|
|||
SDL_JACK_SYM(jack_get_sample_rate);
|
||||
SDL_JACK_SYM(jack_get_buffer_size);
|
||||
SDL_JACK_SYM(jack_port_register);
|
||||
SDL_JACK_SYM(jack_port_by_name);
|
||||
SDL_JACK_SYM(jack_port_name);
|
||||
SDL_JACK_SYM(jack_port_type);
|
||||
SDL_JACK_SYM(jack_connect);
|
||||
SDL_JACK_SYM(jack_set_process_callback);
|
||||
return 0;
|
||||
|
|
@ -273,10 +277,6 @@ JACK_CloseDevice(_THIS)
|
|||
SDL_DestroySemaphore(this->hidden->iosem);
|
||||
}
|
||||
|
||||
if (this->hidden->devports) {
|
||||
JACK_jack_free(this->hidden->devports);
|
||||
}
|
||||
|
||||
SDL_free(this->hidden->iobuffer);
|
||||
}
|
||||
|
||||
|
|
@ -292,9 +292,11 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
const JackProcessCallback callback = iscapture ? jackProcessCaptureCallback : jackProcessPlaybackCallback;
|
||||
const char *sdlportstr = iscapture ? "input" : "output";
|
||||
const char **devports = NULL;
|
||||
int *audio_ports;
|
||||
jack_client_t *client = NULL;
|
||||
jack_status_t status;
|
||||
int channels = 0;
|
||||
int ports = 0;
|
||||
int i;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
|
|
@ -311,15 +313,30 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
}
|
||||
|
||||
devports = JACK_jack_get_ports(client, NULL, NULL, JackPortIsPhysical | sysportflags);
|
||||
this->hidden->devports = devports;
|
||||
if (!devports || !devports[0]) {
|
||||
return SDL_SetError("No physical JACK ports available");
|
||||
}
|
||||
|
||||
while (devports[++channels]) {
|
||||
while (devports[++ports]) {
|
||||
/* spin to count devports */
|
||||
}
|
||||
|
||||
/* Filter out non-audio ports */
|
||||
audio_ports = SDL_calloc(ports, sizeof *audio_ports);
|
||||
for (i = 0; i < ports; i++) {
|
||||
const jack_port_t *dport = JACK_jack_port_by_name(client, devports[i]);
|
||||
const char *type = JACK_jack_port_type(dport);
|
||||
const int len = SDL_strlen(type);
|
||||
/* See if type ends with "audio" */
|
||||
if (len >= 5 && !SDL_memcmp(type+len-5, "audio", 5)) {
|
||||
audio_ports[channels++] = i;
|
||||
}
|
||||
}
|
||||
if (channels == 0) {
|
||||
return SDL_SetError("No physical JACK ports available");
|
||||
}
|
||||
|
||||
|
||||
/* !!! FIXME: docs say about buffer size: "This size may change, clients that depend on it must register a bufsize_callback so they will be notified if it does." */
|
||||
|
||||
/* Jack pretty much demands what it wants. */
|
||||
|
|
@ -368,16 +385,16 @@ JACK_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
/* once activated, we can connect all the ports. */
|
||||
for (i = 0; i < channels; i++) {
|
||||
const char *sdlport = JACK_jack_port_name(this->hidden->sdlports[i]);
|
||||
const char *srcport = iscapture ? devports[i] : sdlport;
|
||||
const char *dstport = iscapture ? sdlport : devports[i];
|
||||
const char *srcport = iscapture ? devports[audio_ports[i]] : sdlport;
|
||||
const char *dstport = iscapture ? sdlport : devports[audio_ports[i]];
|
||||
if (JACK_jack_connect(client, srcport, dstport) != 0) {
|
||||
return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport);
|
||||
}
|
||||
}
|
||||
|
||||
/* don't need these anymore. */
|
||||
this->hidden->devports = NULL;
|
||||
JACK_jack_free(devports);
|
||||
SDL_free(audio_ports);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -33,7 +33,6 @@ struct SDL_PrivateAudioData
|
|||
jack_client_t *client;
|
||||
SDL_sem *iosem;
|
||||
float *iobuffer;
|
||||
const char **devports;
|
||||
jack_port_t **sdlports;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -43,12 +43,7 @@
|
|||
#include "../SDL_audiodev_c.h"
|
||||
#include "SDL_netbsdaudio.h"
|
||||
|
||||
/* Use timer for synchronization */
|
||||
/* #define USE_TIMER_SYNC */
|
||||
|
||||
/* #define DEBUG_AUDIO */
|
||||
/* #define DEBUG_AUDIO_STREAM */
|
||||
|
||||
|
||||
static void
|
||||
NETBSDAUDIO_DetectDevices(void)
|
||||
|
|
@ -63,14 +58,14 @@ NETBSDAUDIO_Status(_THIS)
|
|||
#ifdef DEBUG_AUDIO
|
||||
/* *INDENT-OFF* */
|
||||
audio_info_t info;
|
||||
const audio_prinfo *prinfo;
|
||||
const struct audio_prinfo *prinfo;
|
||||
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
|
||||
fprintf(stderr, "AUDIO_GETINFO failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
prinfo = this->iscapture ? &info.play : &info.record;
|
||||
prinfo = this->iscapture ? &info.record : &info.play;
|
||||
|
||||
fprintf(stderr, "\n"
|
||||
"[%s info]\n"
|
||||
|
|
@ -115,90 +110,37 @@ NETBSDAUDIO_Status(_THIS)
|
|||
(info.mode == AUMODE_PLAY) ? "PLAY"
|
||||
: (info.mode = AUMODE_RECORD) ? "RECORD"
|
||||
: (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
|
||||
|
||||
fprintf(stderr, "\n"
|
||||
"[audio spec]\n"
|
||||
"format : 0x%x\n"
|
||||
"size : %u\n"
|
||||
"",
|
||||
this->spec.format,
|
||||
this->spec.size);
|
||||
/* *INDENT-ON* */
|
||||
#endif /* DEBUG_AUDIO */
|
||||
}
|
||||
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
NETBSDAUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
#ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */
|
||||
/* See if we need to use timed audio synchronization */
|
||||
if (this->hidden->frame_ticks) {
|
||||
/* Use timer for general audio synchronization */
|
||||
Sint32 ticks;
|
||||
|
||||
ticks = ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
|
||||
if (ticks > 0) {
|
||||
SDL_Delay(ticks);
|
||||
}
|
||||
} else {
|
||||
/* Use SDL_IOReady() for audio synchronization */
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Waiting for audio to get ready\n");
|
||||
#endif
|
||||
if (SDL_IOReady(this->hidden->audio_fd, SDL_TRUE, 10 * 1000)
|
||||
<= 0) {
|
||||
const char *message =
|
||||
"Audio timeout - buggy audio driver? (disabled)";
|
||||
/* In general we should never print to the screen,
|
||||
but in this case we have no other way of letting
|
||||
the user know what happened.
|
||||
*/
|
||||
fprintf(stderr, "SDL: %s\n", message);
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
/* Don't try to close - may hang */
|
||||
this->hidden->audio_fd = -1;
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Done disabling audio\n");
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Ready!\n");
|
||||
#endif
|
||||
}
|
||||
#endif /* !USE_BLOCKING_WRITES */
|
||||
}
|
||||
|
||||
static void
|
||||
NETBSDAUDIO_PlayDevice(_THIS)
|
||||
{
|
||||
int written, p = 0;
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
int written;
|
||||
|
||||
/* Write the audio data, checking for EAGAIN on broken audio drivers */
|
||||
do {
|
||||
written = write(this->hidden->audio_fd,
|
||||
&this->hidden->mixbuf[p], this->hidden->mixlen - p);
|
||||
|
||||
if (written > 0)
|
||||
p += written;
|
||||
if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
|
||||
/* Non recoverable error has occurred. It should be reported!!! */
|
||||
perror("audio");
|
||||
break;
|
||||
}
|
||||
/* Write the audio data */
|
||||
written = write(h->audio_fd, h->mixbuf, h->mixlen);
|
||||
if (written == -1) {
|
||||
/* Non recoverable error has occurred. It should be reported!!! */
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
perror("audio");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
#endif
|
||||
|
||||
if (p < this->hidden->mixlen
|
||||
|| ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
|
||||
SDL_Delay(1); /* Let a little CPU time go by */
|
||||
}
|
||||
} while (p < this->hidden->mixlen);
|
||||
|
||||
/* If timer synchronization is enabled, set the next write frame */
|
||||
if (this->hidden->frame_ticks) {
|
||||
this->hidden->next_frame += this->hidden->frame_ticks;
|
||||
}
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written < 0) {
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
}
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
|
|
@ -212,28 +154,19 @@ static int
|
|||
NETBSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
|
||||
{
|
||||
Uint8 *buffer = (Uint8 *) _buffer;
|
||||
int br, p = 0;
|
||||
int br;
|
||||
|
||||
/* Capture the audio data, checking for EAGAIN on broken audio drivers */
|
||||
do {
|
||||
br = read(this->hidden->audio_fd, buffer + p, buflen - p);
|
||||
if (br > 0)
|
||||
p += br;
|
||||
if (br == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
|
||||
/* Non recoverable error has occurred. It should be reported!!! */
|
||||
perror("audio");
|
||||
return p ? p : -1;
|
||||
}
|
||||
br = read(this->hidden->audio_fd, buffer, buflen);
|
||||
if (br == -1) {
|
||||
/* Non recoverable error has occurred. It should be reported!!! */
|
||||
perror("audio");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Captured %d bytes of audio data\n", br);
|
||||
fprintf(stderr, "Captured %d bytes of audio data\n", br);
|
||||
#endif
|
||||
|
||||
if (p < buflen
|
||||
|| ((br < 0) && ((errno == 0) || (errno == EAGAIN)))) {
|
||||
SDL_Delay(1); /* Let a little CPU time go by */
|
||||
}
|
||||
} while (p < buflen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -271,10 +204,9 @@ NETBSDAUDIO_CloseDevice(_THIS)
|
|||
static int
|
||||
NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
|
||||
SDL_AudioFormat format = 0;
|
||||
audio_info_t info;
|
||||
audio_prinfo *prinfo = iscapture ? &info.play : &info.record;
|
||||
struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play;
|
||||
|
||||
/* We don't care what the devname is...we'll try to open anything. */
|
||||
/* ...but default to first name in the list... */
|
||||
|
|
@ -294,25 +226,16 @@ NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
SDL_zerop(this->hidden);
|
||||
|
||||
/* Open the audio device */
|
||||
this->hidden->audio_fd = open(devname, flags, 0);
|
||||
this->hidden->audio_fd = open(devname, iscapture ? O_RDONLY : O_WRONLY);
|
||||
if (this->hidden->audio_fd < 0) {
|
||||
return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
|
||||
}
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
prinfo->encoding = AUDIO_ENCODING_NONE;
|
||||
|
||||
/* Set to play mode */
|
||||
info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
|
||||
return SDL_SetError("Couldn't put device into play mode");
|
||||
}
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
for (format = SDL_FirstAudioFormat(this->spec.format);
|
||||
format; format = SDL_NextAudioFormat()) {
|
||||
for (format = SDL_FirstAudioFormat(this->spec.format); format;) {
|
||||
switch (format) {
|
||||
case AUDIO_U8:
|
||||
prinfo->encoding = AUDIO_ENCODING_ULINEAR;
|
||||
|
|
@ -338,34 +261,33 @@ NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
|
||||
prinfo->precision = 16;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
|
||||
if (prinfo->encoding != AUDIO_ENCODING_NONE) {
|
||||
break;
|
||||
}
|
||||
format = SDL_NextAudioFormat();
|
||||
}
|
||||
|
||||
if (!format) {
|
||||
if (prinfo->encoding == AUDIO_ENCODING_NONE) {
|
||||
return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
|
||||
}
|
||||
|
||||
this->spec.format = format;
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
prinfo->channels = this->spec.channels;
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
|
||||
this->spec.channels = 1;
|
||||
}
|
||||
AUDIO_INITINFO(&info);
|
||||
prinfo->sample_rate = this->spec.freq;
|
||||
/* Calculate spec parameters based on our chosen format */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
|
||||
info.blocksize = this->spec.size;
|
||||
info.hiwat = 5;
|
||||
info.lowat = 3;
|
||||
prinfo->sample_rate = this->spec.freq;
|
||||
prinfo->channels = this->spec.channels;
|
||||
(void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
|
||||
|
||||
(void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
|
||||
this->spec.freq = prinfo->sample_rate;
|
||||
this->spec.channels = prinfo->channels;
|
||||
|
||||
if (!iscapture) {
|
||||
/* Allocate mixing buffer */
|
||||
|
|
@ -390,7 +312,6 @@ NETBSDAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->DetectDevices = NETBSDAUDIO_DetectDevices;
|
||||
impl->OpenDevice = NETBSDAUDIO_OpenDevice;
|
||||
impl->PlayDevice = NETBSDAUDIO_PlayDevice;
|
||||
impl->WaitDevice = NETBSDAUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = NETBSDAUDIO_CloseDevice;
|
||||
impl->CaptureFromDevice = NETBSDAUDIO_CaptureFromDevice;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
643
Engine/lib/sdl/src/audio/openslES/SDL_openslES.c
Normal file
643
Engine/lib/sdl/src/audio/openslES/SDL_openslES.c
Normal file
|
|
@ -0,0 +1,643 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_OPENSLES
|
||||
|
||||
/* For more discussion of low latency audio on Android, see this:
|
||||
https://googlesamples.github.io/android-audio-high-performance/guides/opensl_es.html
|
||||
*/
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_openslES.h"
|
||||
|
||||
/* for native audio */
|
||||
#include <SLES/OpenSLES.h>
|
||||
#include <SLES/OpenSLES_Android.h>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOG_TAG "SDL_openslES"
|
||||
|
||||
#if 0
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
//#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGV(...)
|
||||
#else
|
||||
#define LOGE(...)
|
||||
#define LOGI(...)
|
||||
#define LOGV(...)
|
||||
#endif
|
||||
|
||||
/* engine interfaces */
|
||||
static SLObjectItf engineObject = NULL;
|
||||
static SLEngineItf engineEngine = NULL;
|
||||
|
||||
/* output mix interfaces */
|
||||
static SLObjectItf outputMixObject = NULL;
|
||||
// static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
|
||||
|
||||
/* aux effect on the output mix, used by the buffer queue player */
|
||||
/* static const SLEnvironmentalReverbSettings reverbSettings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR; */
|
||||
|
||||
/* buffer queue player interfaces */
|
||||
static SLObjectItf bqPlayerObject = NULL;
|
||||
static SLPlayItf bqPlayerPlay = NULL;
|
||||
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue = NULL;
|
||||
#if 0
|
||||
static SLEffectSendItf bqPlayerEffectSend = NULL;
|
||||
static SLMuteSoloItf bqPlayerMuteSolo = NULL;
|
||||
static SLVolumeItf bqPlayerVolume = NULL;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* recorder interfaces TODO */
|
||||
static SLObjectItf recorderObject = NULL;
|
||||
static SLRecordItf recorderRecord;
|
||||
static SLAndroidSimpleBufferQueueItf recorderBufferQueue;
|
||||
#endif
|
||||
|
||||
/* pointer and size of the next player buffer to enqueue, and number of remaining buffers */
|
||||
#if 0
|
||||
static short *nextBuffer;
|
||||
static unsigned nextSize;
|
||||
static int nextCount;
|
||||
#endif
|
||||
|
||||
// static SDL_AudioDevice* audioDevice = NULL;
|
||||
|
||||
#if 0
|
||||
static const char *sldevaudiorecorderstr = "SLES Audio Recorder";
|
||||
static const char *sldevaudioplayerstr = "SLES Audio Player";
|
||||
|
||||
#define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr
|
||||
#define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr
|
||||
static void openslES_DetectDevices( int iscapture )
|
||||
{
|
||||
LOGI( "openSLES_DetectDevices()" );
|
||||
if ( iscapture )
|
||||
addfn( SLES_DEV_AUDIO_RECORDER );
|
||||
else
|
||||
addfn( SLES_DEV_AUDIO_PLAYER );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void openslES_DestroyEngine();
|
||||
|
||||
static int
|
||||
openslES_CreateEngine()
|
||||
{
|
||||
SLresult result;
|
||||
|
||||
LOGI("openSLES_CreateEngine()");
|
||||
|
||||
/* create engine */
|
||||
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("slCreateEngine failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
LOGI("slCreateEngine OK");
|
||||
|
||||
/* realize the engine */
|
||||
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("RealizeEngine failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
LOGI("RealizeEngine OK");
|
||||
|
||||
/* get the engine interface, which is needed in order to create other objects */
|
||||
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("EngineGetInterface failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
LOGI("EngineGetInterface OK");
|
||||
|
||||
/* create output mix, with environmental reverb specified as a non-required interface */
|
||||
/* const SLInterfaceID ids[1] = { SL_IID_ENVIRONMENTALREVERB }; */
|
||||
/* const SLboolean req[1] = { SL_BOOLEAN_FALSE }; */
|
||||
|
||||
const SLInterfaceID ids[1] = { SL_IID_VOLUME };
|
||||
const SLboolean req[1] = { SL_BOOLEAN_FALSE };
|
||||
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
|
||||
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("CreateOutputMix failed");
|
||||
goto error;
|
||||
}
|
||||
LOGI("CreateOutputMix OK");
|
||||
|
||||
/* realize the output mix */
|
||||
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("RealizeOutputMix failed");
|
||||
goto error;
|
||||
}
|
||||
return 1;
|
||||
|
||||
error:
|
||||
openslES_DestroyEngine();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void openslES_DestroyPCMPlayer(_THIS);
|
||||
static void openslES_DestroyPCMRecorder(_THIS);
|
||||
|
||||
static void openslES_DestroyEngine()
|
||||
{
|
||||
LOGI("openslES_DestroyEngine()");
|
||||
|
||||
// openslES_DestroyPCMPlayer(this);
|
||||
// openslES_DestroyPCMRecorder(this);
|
||||
|
||||
/* destroy output mix object, and invalidate all associated interfaces */
|
||||
if (outputMixObject != NULL) {
|
||||
(*outputMixObject)->Destroy(outputMixObject);
|
||||
outputMixObject = NULL;
|
||||
/* outputMixEnvironmentalReverb = NULL; */
|
||||
}
|
||||
|
||||
/* destroy engine object, and invalidate all associated interfaces */
|
||||
if (engineObject != NULL) {
|
||||
(*engineObject)->Destroy(engineObject);
|
||||
engineObject = NULL;
|
||||
engineEngine = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* this callback handler is called every time a buffer finishes playing */
|
||||
static void
|
||||
bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context;
|
||||
LOGV("SLES: Playback Callmeback");
|
||||
SDL_SemPost(audiodata->playsem);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
openslES_CreatePCMRecorder(_THIS)
|
||||
{
|
||||
/* struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden; */
|
||||
|
||||
LOGE("openslES_CreatePCMRecorder not implimented yet!");
|
||||
return SDL_SetError("openslES_CreatePCMRecorder not implimented yet!");
|
||||
}
|
||||
|
||||
static void
|
||||
openslES_DestroyPCMRecorder(_THIS)
|
||||
{
|
||||
/* struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden; */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
openslES_CreatePCMPlayer(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
|
||||
SLDataFormat_PCM format_pcm;
|
||||
SLresult result;
|
||||
int i;
|
||||
|
||||
/* If we want to add floating point audio support (requires API level 21)
|
||||
it can be done as described here:
|
||||
https://developer.android.com/ndk/guides/audio/opensl/android-extensions.html#floating-point
|
||||
*/
|
||||
#if 1
|
||||
/* Just go with signed 16-bit audio as it's the most compatible */
|
||||
this->spec.format = AUDIO_S16SYS;
|
||||
#else
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
while (test_format != 0) {
|
||||
if (SDL_AUDIO_ISSIGNED(test_format) && SDL_AUDIO_ISINT(test_format)) {
|
||||
break;
|
||||
}
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
|
||||
if (test_format == 0) {
|
||||
/* Didn't find a compatible format : */
|
||||
LOGI( "No compatible audio format, using signed 16-bit audio" );
|
||||
test_format = AUDIO_S16SYS;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
#endif
|
||||
|
||||
/* Update the fragment size as size in bytes */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
LOGI("Try to open %u hz %u bit chan %u %s samples %u",
|
||||
this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format),
|
||||
this->spec.channels, (this->spec.format & 0x1000) ? "BE" : "LE", this->spec.samples);
|
||||
|
||||
/* configure audio source */
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
|
||||
|
||||
format_pcm.formatType = SL_DATAFORMAT_PCM;
|
||||
format_pcm.numChannels = this->spec.channels;
|
||||
format_pcm.samplesPerSec = this->spec.freq * 1000; /* / kilo Hz to milli Hz */
|
||||
format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
|
||||
if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) {
|
||||
format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
|
||||
} else {
|
||||
format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
|
||||
}
|
||||
|
||||
/*
|
||||
#define SL_SPEAKER_FRONT_LEFT ((SLuint32) 0x00000001)
|
||||
#define SL_SPEAKER_FRONT_RIGHT ((SLuint32) 0x00000002)
|
||||
#define SL_SPEAKER_FRONT_CENTER ((SLuint32) 0x00000004)
|
||||
#define SL_SPEAKER_LOW_FREQUENCY ((SLuint32) 0x00000008)
|
||||
#define SL_SPEAKER_BACK_LEFT ((SLuint32) 0x00000010)
|
||||
#define SL_SPEAKER_BACK_RIGHT ((SLuint32) 0x00000020)
|
||||
#define SL_SPEAKER_FRONT_LEFT_OF_CENTER ((SLuint32) 0x00000040)
|
||||
#define SL_SPEAKER_FRONT_RIGHT_OF_CENTER ((SLuint32) 0x00000080)
|
||||
#define SL_SPEAKER_BACK_CENTER ((SLuint32) 0x00000100)
|
||||
#define SL_SPEAKER_SIDE_LEFT ((SLuint32) 0x00000200)
|
||||
#define SL_SPEAKER_SIDE_RIGHT ((SLuint32) 0x00000400)
|
||||
#define SL_SPEAKER_TOP_CENTER ((SLuint32) 0x00000800)
|
||||
#define SL_SPEAKER_TOP_FRONT_LEFT ((SLuint32) 0x00001000)
|
||||
#define SL_SPEAKER_TOP_FRONT_CENTER ((SLuint32) 0x00002000)
|
||||
#define SL_SPEAKER_TOP_FRONT_RIGHT ((SLuint32) 0x00004000)
|
||||
#define SL_SPEAKER_TOP_BACK_LEFT ((SLuint32) 0x00008000)
|
||||
#define SL_SPEAKER_TOP_BACK_CENTER ((SLuint32) 0x00010000)
|
||||
#define SL_SPEAKER_TOP_BACK_RIGHT ((SLuint32) 0x00020000)
|
||||
*/
|
||||
#define SL_ANDROID_SPEAKER_STEREO (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT)
|
||||
#define SL_ANDROID_SPEAKER_QUAD (SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT)
|
||||
#define SL_ANDROID_SPEAKER_5DOT1 (SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY)
|
||||
#define SL_ANDROID_SPEAKER_7DOT1 (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT)
|
||||
|
||||
switch (this->spec.channels)
|
||||
{
|
||||
case 1:
|
||||
format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT;
|
||||
break;
|
||||
case 2:
|
||||
format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO;
|
||||
break;
|
||||
case 3:
|
||||
format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_FRONT_CENTER;
|
||||
break;
|
||||
case 4:
|
||||
format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD;
|
||||
break;
|
||||
case 5:
|
||||
format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER;
|
||||
break;
|
||||
case 6:
|
||||
format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1;
|
||||
break;
|
||||
case 7:
|
||||
format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER;
|
||||
break;
|
||||
case 8:
|
||||
format_pcm.channelMask = SL_ANDROID_SPEAKER_7DOT1;
|
||||
break;
|
||||
default:
|
||||
/* Unknown number of channels, fall back to stereo */
|
||||
this->spec.channels = 2;
|
||||
format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
SLDataSource audioSrc = { &loc_bufq, &format_pcm };
|
||||
|
||||
/* configure audio sink */
|
||||
SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
|
||||
SLDataSink audioSnk = { &loc_outmix, NULL };
|
||||
|
||||
/* create audio player */
|
||||
const SLInterfaceID ids[2] = {
|
||||
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
SL_IID_VOLUME
|
||||
};
|
||||
|
||||
const SLboolean req[2] = {
|
||||
SL_BOOLEAN_TRUE,
|
||||
SL_BOOLEAN_FALSE,
|
||||
};
|
||||
|
||||
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("CreateAudioPlayer failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* realize the player */
|
||||
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("RealizeAudioPlayer failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* get the play interface */
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("SL_IID_PLAY interface get failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* get the buffer queue interface */
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("SL_IID_BUFFERQUEUE interface get failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* register callback on the buffer queue */
|
||||
/* context is '(SDL_PrivateAudioData *)this->hidden' */
|
||||
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, this->hidden);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("RegisterCallback failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* get the effect send interface */
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND, &bqPlayerEffectSend);
|
||||
if (SL_RESULT_SUCCESS != result)
|
||||
{
|
||||
|
||||
LOGE("SL_IID_EFFECTSEND interface get failed");
|
||||
goto failed;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 /* mute/solo is not supported for sources that are known to be mono, as this is */
|
||||
/* get the mute/solo interface */
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
(void) result;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* get the volume interface */
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("SL_IID_VOLUME interface get failed");
|
||||
/* goto failed; */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create the audio buffer semaphore */
|
||||
audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1);
|
||||
if (!audiodata->playsem) {
|
||||
LOGE("cannot create Semaphore!");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Create the sound buffers */
|
||||
audiodata->mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
|
||||
if (audiodata->mixbuff == NULL) {
|
||||
LOGE("mixbuffer allocate - out of memory");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_BUFFERS; i++) {
|
||||
audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
|
||||
}
|
||||
|
||||
/* set the player's state to playing */
|
||||
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
LOGE("Play set state failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
|
||||
openslES_DestroyPCMPlayer(this);
|
||||
|
||||
return SDL_SetError("Open device failed!");
|
||||
}
|
||||
|
||||
static void
|
||||
openslES_DestroyPCMPlayer(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
|
||||
SLresult result;
|
||||
|
||||
/* set the player's state to 'stopped' */
|
||||
if (bqPlayerPlay != NULL) {
|
||||
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
SDL_SetError("Stopped set state failed");
|
||||
}
|
||||
}
|
||||
|
||||
/* destroy buffer queue audio player object, and invalidate all associated interfaces */
|
||||
if (bqPlayerObject != NULL) {
|
||||
|
||||
(*bqPlayerObject)->Destroy(bqPlayerObject);
|
||||
|
||||
bqPlayerObject = NULL;
|
||||
bqPlayerPlay = NULL;
|
||||
bqPlayerBufferQueue = NULL;
|
||||
#if 0
|
||||
bqPlayerEffectSend = NULL;
|
||||
bqPlayerMuteSolo = NULL;
|
||||
bqPlayerVolume = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (audiodata->playsem) {
|
||||
SDL_DestroySemaphore(audiodata->playsem);
|
||||
audiodata->playsem = NULL;
|
||||
}
|
||||
|
||||
if (audiodata->mixbuff) {
|
||||
SDL_free(audiodata->mixbuff);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||
{
|
||||
this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
if (iscapture) {
|
||||
LOGI("openslES_OpenDevice( ) %s for capture", devname);
|
||||
return openslES_CreatePCMRecorder(this);
|
||||
} else {
|
||||
LOGI("openslES_OpenDevice( ) %s for playing", devname);
|
||||
return openslES_CreatePCMPlayer(this);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
openslES_CloseDevice(_THIS)
|
||||
{
|
||||
/* struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden; */
|
||||
|
||||
if (this->iscapture) {
|
||||
LOGI("openslES_CloseDevice( ) for capture");
|
||||
openslES_DestroyPCMRecorder(this);
|
||||
} else {
|
||||
LOGI("openslES_CloseDevice( ) for playing");
|
||||
openslES_DestroyPCMPlayer(this);
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
openslES_WaitDevice(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
|
||||
|
||||
LOGV("openslES_WaitDevice( )");
|
||||
|
||||
/* Wait for an audio chunk to finish */
|
||||
/* WaitForSingleObject(this->hidden->audio_sem, INFINITE); */
|
||||
SDL_SemWait(audiodata->playsem);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*/ n playn sem */
|
||||
/* getbuf 0 - 1 */
|
||||
/* fill buff 0 - 1 */
|
||||
/* play 0 - 0 1 */
|
||||
/* wait 1 0 0 */
|
||||
/* getbuf 1 0 0 */
|
||||
/* fill buff 1 0 0 */
|
||||
/* play 0 0 0 */
|
||||
/* wait */
|
||||
/* */
|
||||
/* okay.. */
|
||||
|
||||
static Uint8 *
|
||||
openslES_GetDeviceBuf(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
|
||||
|
||||
LOGV("openslES_GetDeviceBuf( )");
|
||||
return audiodata->pmixbuff[audiodata->next_buffer];
|
||||
}
|
||||
|
||||
static void
|
||||
openslES_PlayDevice(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
|
||||
SLresult result;
|
||||
|
||||
LOGV("======openslES_PlayDevice( )======");
|
||||
|
||||
/* Queue it up */
|
||||
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size);
|
||||
|
||||
audiodata->next_buffer++;
|
||||
if (audiodata->next_buffer >= NUM_BUFFERS) {
|
||||
audiodata->next_buffer = 0;
|
||||
}
|
||||
|
||||
/* If Enqueue fails, callback won't be called.
|
||||
* Post the semphore, not to run out of buffer */
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
SDL_SemPost(audiodata->playsem);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
openslES_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
LOGI("openslES_Init() called");
|
||||
|
||||
if (!openslES_CreateEngine()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGI("openslES_Init() - set pointers");
|
||||
|
||||
/* Set the function pointers */
|
||||
/* impl->DetectDevices = openslES_DetectDevices; */
|
||||
impl->OpenDevice = openslES_OpenDevice;
|
||||
impl->CloseDevice = openslES_CloseDevice;
|
||||
impl->PlayDevice = openslES_PlayDevice;
|
||||
impl->GetDeviceBuf = openslES_GetDeviceBuf;
|
||||
impl->Deinitialize = openslES_DestroyEngine;
|
||||
impl->WaitDevice = openslES_WaitDevice;
|
||||
|
||||
/* and the capabilities */
|
||||
impl->HasCaptureSupport = 0; /* TODO */
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
/* impl->OnlyHasDefaultInputDevice = 1; */
|
||||
|
||||
LOGI("openslES_Init() - succes");
|
||||
|
||||
/* this audio target is available. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
AudioBootStrap openslES_bootstrap = {
|
||||
"openslES", "opensl ES audio driver", openslES_Init, 0
|
||||
};
|
||||
|
||||
void openslES_ResumeDevices()
|
||||
{
|
||||
if (bqPlayerPlay != NULL) {
|
||||
/* set the player's state to 'playing' */
|
||||
SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
SDL_SetError("openslES_ResumeDevices failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void openslES_PauseDevices()
|
||||
{
|
||||
if (bqPlayerPlay != NULL) {
|
||||
/* set the player's state to 'paused' */
|
||||
SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED);
|
||||
if (SL_RESULT_SUCCESS != result) {
|
||||
SDL_SetError("openslES_PauseDevices failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_OPENSLES */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
50
Engine/lib/sdl/src/audio/openslES/SDL_openslES.h
Normal file
50
Engine/lib/sdl/src/audio/openslES/SDL_openslES.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_openslesaudio_h
|
||||
#define _SDL_openslesaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
#define NUM_BUFFERS 2 /* -- Don't lower this! */
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
Uint8 *mixbuff;
|
||||
int next_buffer;
|
||||
Uint8 *pmixbuff[NUM_BUFFERS];
|
||||
SDL_sem *playsem;
|
||||
#if 0
|
||||
SDL_sem *recsem;
|
||||
#endif
|
||||
};
|
||||
|
||||
void openslES_ResumeDevices(void);
|
||||
void openslES_PauseDevices(void);
|
||||
|
||||
#endif /* _SDL_openslesaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -109,7 +109,7 @@ static pa_operation * (*PULSEAUDIO_pa_stream_drain) (pa_stream *,
|
|||
pa_stream_success_cb_t, void *);
|
||||
static int (*PULSEAUDIO_pa_stream_peek) (pa_stream *, const void **, size_t *);
|
||||
static int (*PULSEAUDIO_pa_stream_drop) (pa_stream *);
|
||||
static pa_operation * (*PULSEAUDIO_pa_stream_flush) (pa_stream *,
|
||||
static pa_operation * (*PULSEAUDIO_pa_stream_flush) (pa_stream *,
|
||||
pa_stream_success_cb_t, void *);
|
||||
static int (*PULSEAUDIO_pa_stream_disconnect) (pa_stream *);
|
||||
static void (*PULSEAUDIO_pa_stream_unref) (pa_stream *);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -161,21 +161,6 @@ WASAPI_DetectDevices(void)
|
|||
WASAPI_EnumerateEndpoints();
|
||||
}
|
||||
|
||||
static int
|
||||
WASAPI_GetPendingBytes(_THIS)
|
||||
{
|
||||
UINT32 frames = 0;
|
||||
|
||||
/* it's okay to fail here; we'll deal with failures in the audio thread. */
|
||||
/* FIXME: need a lock around checking this->hidden->client */
|
||||
if (this->hidden->client != NULL) { /* definitely activated? */
|
||||
if (FAILED(IAudioClient_GetCurrentPadding(this->hidden->client, &frames))) {
|
||||
return 0; /* oh well. */
|
||||
}
|
||||
}
|
||||
return ((int) frames) * this->hidden->framesize;
|
||||
}
|
||||
|
||||
static SDL_INLINE SDL_bool
|
||||
WasapiFailed(_THIS, const HRESULT err)
|
||||
{
|
||||
|
|
@ -327,8 +312,8 @@ static void
|
|||
WASAPI_WaitDevice(_THIS)
|
||||
{
|
||||
while (RecoverWasapiIfLost(this) && this->hidden->client && this->hidden->event) {
|
||||
/*SDL_Log("WAITDEVICE");*/
|
||||
if (WaitForSingleObjectEx(this->hidden->event, INFINITE, FALSE) == WAIT_OBJECT_0) {
|
||||
DWORD waitResult = WaitForSingleObjectEx(this->hidden->event, 200, FALSE);
|
||||
if (waitResult == WAIT_OBJECT_0) {
|
||||
const UINT32 maxpadding = this->spec.samples;
|
||||
UINT32 padding = 0;
|
||||
if (!WasapiFailed(this, IAudioClient_GetCurrentPadding(this->hidden->client, &padding))) {
|
||||
|
|
@ -337,7 +322,7 @@ WASAPI_WaitDevice(_THIS)
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (waitResult != WAIT_TIMEOUT) {
|
||||
/*SDL_Log("WASAPI FAILED EVENT!");*/
|
||||
IAudioClient_Stop(this->hidden->client);
|
||||
SDL_OpenedAudioDeviceDisconnected(this);
|
||||
|
|
@ -725,6 +710,12 @@ WASAPI_ThreadDeinit(_THIS)
|
|||
WASAPI_PlatformThreadDeinit(this);
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_BeginLoopIteration(_THIS)
|
||||
{
|
||||
/* no-op. */
|
||||
}
|
||||
|
||||
static void
|
||||
WASAPI_Deinitialize(void)
|
||||
{
|
||||
|
|
@ -759,7 +750,6 @@ WASAPI_Init(SDL_AudioDriverImpl * impl)
|
|||
impl->OpenDevice = WASAPI_OpenDevice;
|
||||
impl->PlayDevice = WASAPI_PlayDevice;
|
||||
impl->WaitDevice = WASAPI_WaitDevice;
|
||||
impl->GetPendingBytes = WASAPI_GetPendingBytes;
|
||||
impl->GetDeviceBuf = WASAPI_GetDeviceBuf;
|
||||
impl->CaptureFromDevice = WASAPI_CaptureFromDevice;
|
||||
impl->FlushCapture = WASAPI_FlushCapture;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -351,10 +351,42 @@ WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
|
|||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPWSTR devid;
|
||||
char *devname;
|
||||
} EndpointItem;
|
||||
|
||||
static int sort_endpoints(const void *_a, const void *_b)
|
||||
{
|
||||
LPWSTR a = ((const EndpointItem *) _a)->devid;
|
||||
LPWSTR b = ((const EndpointItem *) _b)->devid;
|
||||
if (!a && b) {
|
||||
return -1;
|
||||
} else if (a && !b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (SDL_TRUE) {
|
||||
if (*a < *b) {
|
||||
return -1;
|
||||
} else if (*a > *b) {
|
||||
return 1;
|
||||
} else if (*a == 0) {
|
||||
break;
|
||||
}
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
WASAPI_EnumerateEndpointsForFlow(const SDL_bool iscapture)
|
||||
{
|
||||
IMMDeviceCollection *collection = NULL;
|
||||
EndpointItem *items;
|
||||
UINT i, total;
|
||||
|
||||
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
|
||||
|
|
@ -369,22 +401,36 @@ WASAPI_EnumerateEndpointsForFlow(const SDL_bool iscapture)
|
|||
return;
|
||||
}
|
||||
|
||||
items = (EndpointItem *) SDL_calloc(total, sizeof (EndpointItem));
|
||||
if (!items) {
|
||||
return; /* oh well. */
|
||||
}
|
||||
|
||||
for (i = 0; i < total; i++) {
|
||||
EndpointItem *item = items + i;
|
||||
IMMDevice *device = NULL;
|
||||
if (SUCCEEDED(IMMDeviceCollection_Item(collection, i, &device))) {
|
||||
LPWSTR devid = NULL;
|
||||
if (SUCCEEDED(IMMDevice_GetId(device, &devid))) {
|
||||
char *devname = GetWasapiDeviceName(device);
|
||||
if (devname) {
|
||||
WASAPI_AddDevice(iscapture, devname, devid);
|
||||
SDL_free(devname);
|
||||
}
|
||||
CoTaskMemFree(devid);
|
||||
if (SUCCEEDED(IMMDevice_GetId(device, &item->devid))) {
|
||||
item->devname = GetWasapiDeviceName(device);
|
||||
}
|
||||
IMMDevice_Release(device);
|
||||
}
|
||||
}
|
||||
|
||||
/* sort the list of devices by their guid so list is consistent between runs */
|
||||
SDL_qsort(items, total, sizeof (*items), sort_endpoints);
|
||||
|
||||
/* Send the sorted list on to the SDL's higher level. */
|
||||
for (i = 0; i < total; i++) {
|
||||
EndpointItem *item = items + i;
|
||||
if ((item->devid) && (item->devname)) {
|
||||
WASAPI_AddDevice(iscapture, item->devname, item->devid);
|
||||
}
|
||||
SDL_free(item->devname);
|
||||
CoTaskMemFree(item->devid);
|
||||
}
|
||||
|
||||
SDL_free(items);
|
||||
IMMDeviceCollection_Release(collection);
|
||||
}
|
||||
|
||||
|
|
@ -405,12 +451,6 @@ WASAPI_PlatformDeleteActivationHandler(void *handler)
|
|||
SDL_assert(!"This function should have only been called on WinRT.");
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_BeginLoopIteration(_THIS)
|
||||
{
|
||||
/* no-op. */
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__) */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -185,20 +185,9 @@ struct SDL_WasapiActivationHandler : public RuntimeClass< RuntimeClassFlags< Cla
|
|||
HRESULT
|
||||
SDL_WasapiActivationHandler::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *async)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
IUnknown *iunknown = nullptr;
|
||||
const HRESULT ret = async->GetActivateResult(&result, &iunknown);
|
||||
|
||||
if (SUCCEEDED(ret) && SUCCEEDED(result)) {
|
||||
iunknown->QueryInterface(IID_PPV_ARGS(&device->hidden->client));
|
||||
if (device->hidden->client) {
|
||||
// Just set a flag, since we're probably in a different thread. We'll pick it up and init everything on our own thread to prevent races.
|
||||
SDL_AtomicSet(&device->hidden->just_activated, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Just set a flag, since we're probably in a different thread. We'll pick it up and init everything on our own thread to prevent races.
|
||||
SDL_AtomicSet(&device->hidden->just_activated, 1);
|
||||
WASAPI_UnrefDevice(device);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
@ -236,27 +225,47 @@ WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
|
|||
IActivateAudioInterfaceAsyncOperation *async = nullptr;
|
||||
const HRESULT ret = ActivateAudioInterfaceAsync(devid, __uuidof(IAudioClient), nullptr, handler.Get(), &async);
|
||||
|
||||
if (async != nullptr) {
|
||||
async->Release();
|
||||
}
|
||||
|
||||
if (FAILED(ret)) {
|
||||
if (FAILED(ret) || async == nullptr) {
|
||||
if (async != nullptr) {
|
||||
async->Release();
|
||||
}
|
||||
handler.Get()->Release();
|
||||
WASAPI_UnrefDevice(_this);
|
||||
return WIN_SetErrorFromHRESULT("WASAPI can't activate requested audio endpoint", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
WASAPI_BeginLoopIteration(_THIS)
|
||||
{
|
||||
if (SDL_AtomicCAS(&_this->hidden->just_activated, 1, 0)) {
|
||||
if (WASAPI_PrepDevice(_this, SDL_TRUE) == -1) {
|
||||
SDL_OpenedAudioDeviceDisconnected(_this);
|
||||
}
|
||||
/* Spin until the async operation is complete.
|
||||
* If we don't PrepDevice before leaving this function, the bug list gets LONG:
|
||||
* - device.spec is not filled with the correct information
|
||||
* - The 'obtained' spec will be wrong for ALLOW_CHANGE properties
|
||||
* - SDL_AudioStreams will/will not be allocated at the right time
|
||||
* - SDL_assert(device->callbackspec.size == device->spec.size) will fail
|
||||
* - When the assert is ignored, skipping or a buffer overflow will occur
|
||||
*/
|
||||
while (!SDL_AtomicCAS(&_this->hidden->just_activated, 1, 0)) {
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
HRESULT activateRes = S_OK;
|
||||
IUnknown *iunknown = nullptr;
|
||||
const HRESULT getActivateRes = async->GetActivateResult(&activateRes, &iunknown);
|
||||
async->Release();
|
||||
if (FAILED(getActivateRes)) {
|
||||
return WIN_SetErrorFromHRESULT("Failed to get WASAPI activate result", getActivateRes);
|
||||
} else if (FAILED(activateRes)) {
|
||||
return WIN_SetErrorFromHRESULT("Failed to activate WASAPI device", activateRes);
|
||||
}
|
||||
|
||||
iunknown->QueryInterface(IID_PPV_ARGS(&_this->hidden->client));
|
||||
if (!_this->hidden->client) {
|
||||
return SDL_SetError("Failed to query WASAPI client interface");
|
||||
}
|
||||
|
||||
if (WASAPI_PrepDevice(_this, isrecovery) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -78,7 +78,7 @@ static void DetectWave##typ##Devs(void) { \
|
|||
capstyp##2W caps; \
|
||||
UINT i; \
|
||||
for (i = 0; i < devcount; i++) { \
|
||||
if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
|
||||
if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
|
||||
char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \
|
||||
if (name != NULL) { \
|
||||
SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
|
||||
|
|
@ -375,8 +375,7 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
#endif
|
||||
|
||||
/* Create the audio buffer semaphore */
|
||||
this->hidden->audio_sem =
|
||||
CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
|
||||
this->hidden->audio_sem = CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
|
||||
if (this->hidden->audio_sem == NULL) {
|
||||
return SDL_SetError("Couldn't create semaphore");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_system.h"
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -30,28 +31,39 @@ extern "C" {
|
|||
#include <EGL/eglplatform.h>
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_rect.h"
|
||||
#include "SDL_video.h"
|
||||
|
||||
/* Interface from the SDL library into the Android Java activity */
|
||||
extern void Android_JNI_SetActivityTitle(const char *title);
|
||||
extern void Android_JNI_SetWindowStyle(SDL_bool fullscreen);
|
||||
extern void Android_JNI_SetOrientation(int w, int h, int resizable, const char *hint);
|
||||
extern void Android_JNI_MinizeWindow(void);
|
||||
extern SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss(void);
|
||||
|
||||
extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);
|
||||
extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect);
|
||||
extern void Android_JNI_HideTextInput(void);
|
||||
extern SDL_bool Android_JNI_IsScreenKeyboardShown(void);
|
||||
extern ANativeWindow* Android_JNI_GetNativeWindow(void);
|
||||
extern void Android_JNI_SetSurfaceViewFormat(int format);
|
||||
|
||||
extern SDL_DisplayOrientation Android_JNI_GetDisplayOrientation(void);
|
||||
extern int Android_JNI_GetDisplayDPI(float *ddpi, float *xdpi, float *ydpi);
|
||||
|
||||
/* Audio support */
|
||||
extern int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
|
||||
extern int Android_JNI_OpenAudioDevice(int iscapture, SDL_AudioSpec *spec);
|
||||
extern void* Android_JNI_GetAudioBuffer(void);
|
||||
extern void Android_JNI_WriteAudioBuffer(void);
|
||||
extern int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen);
|
||||
extern void Android_JNI_FlushCapturedAudio(void);
|
||||
extern void Android_JNI_CloseAudioDevice(const int iscapture);
|
||||
extern void Android_JNI_AudioSetThreadPriority(int iscapture, int device_id);
|
||||
|
||||
/* Detecting device type */
|
||||
extern SDL_bool Android_IsDeXMode(void);
|
||||
extern SDL_bool Android_IsChromebook(void);
|
||||
|
||||
#include "SDL_rwops.h"
|
||||
|
||||
|
|
@ -78,14 +90,14 @@ void Android_JNI_PollInputDevices(void);
|
|||
|
||||
/* Haptic support */
|
||||
void Android_JNI_PollHapticDevices(void);
|
||||
void Android_JNI_HapticRun(int device_id, int length);
|
||||
void Android_JNI_HapticRun(int device_id, float intensity, int length);
|
||||
void Android_JNI_HapticStop(int device_id);
|
||||
|
||||
/* Video */
|
||||
void Android_JNI_SuspendScreenSaver(SDL_bool suspend);
|
||||
|
||||
/* Touch support */
|
||||
int Android_JNI_GetTouchDeviceIds(int **ids);
|
||||
void Android_JNI_SetSeparateMouseAndTouch(SDL_bool new_value);
|
||||
void Android_JNI_InitTouch(void);
|
||||
|
||||
/* Threads */
|
||||
#include <jni.h>
|
||||
|
|
@ -102,6 +114,27 @@ JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls);
|
|||
#include "SDL_messagebox.h"
|
||||
int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
/* Cursor support */
|
||||
int Android_JNI_CreateCustomCursor(SDL_Surface *surface, int hot_x, int hot_y);
|
||||
SDL_bool Android_JNI_SetCustomCursor(int cursorID);
|
||||
SDL_bool Android_JNI_SetSystemCursor(int cursorID);
|
||||
|
||||
/* Relative mouse support */
|
||||
SDL_bool Android_JNI_SupportsRelativeMouse(void);
|
||||
SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled);
|
||||
|
||||
|
||||
int SDL_GetAndroidSDKVersion(void);
|
||||
|
||||
SDL_bool SDL_IsAndroidTablet(void);
|
||||
SDL_bool SDL_IsAndroidTV(void);
|
||||
SDL_bool SDL_IsChromebook(void);
|
||||
SDL_bool SDL_IsDeXMode(void);
|
||||
|
||||
void Android_ActivityMutex_Lock(void);
|
||||
void Android_ActivityMutex_Unlock(void);
|
||||
void Android_ActivityMutex_Lock_Running(void);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -173,17 +173,29 @@ SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *
|
|||
if (conn) {
|
||||
DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method);
|
||||
if (msg) {
|
||||
int firstarg = va_arg(ap, int);
|
||||
int firstarg;
|
||||
va_list ap_reply;
|
||||
va_copy(ap_reply, ap); /* copy the arg list so we don't compete with D-Bus for it */
|
||||
firstarg = va_arg(ap, int);
|
||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) {
|
||||
DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
|
||||
if (reply) {
|
||||
firstarg = va_arg(ap, int);
|
||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap)) {
|
||||
/* skip any input args, get to output args. */
|
||||
while ((firstarg = va_arg(ap_reply, int)) != DBUS_TYPE_INVALID) {
|
||||
/* we assume D-Bus already validated all this. */
|
||||
{ void *dumpptr = va_arg(ap_reply, void*); (void) dumpptr; }
|
||||
if (firstarg == DBUS_TYPE_ARRAY) {
|
||||
{ const int dumpint = va_arg(ap_reply, int); (void) dumpint; }
|
||||
}
|
||||
}
|
||||
firstarg = va_arg(ap_reply, int);
|
||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap_reply)) {
|
||||
retval = SDL_TRUE;
|
||||
}
|
||||
dbus.message_unref(reply);
|
||||
}
|
||||
}
|
||||
va_end(ap_reply);
|
||||
dbus.message_unref(msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -298,7 +310,11 @@ SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface
|
|||
void
|
||||
SDL_DBus_ScreensaverTickle(void)
|
||||
{
|
||||
SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
|
||||
if (screensaver_cookie == 0) { /* no need to tickle if we're inhibiting. */
|
||||
/* org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. */
|
||||
SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
|
||||
SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -39,9 +39,8 @@ typedef struct SDL_DBusContext {
|
|||
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_get_is_connected)(DBusConnection *);
|
||||
dbus_bool_t (*connection_add_filter)(DBusConnection *, DBusHandleMessageFunction, void *, DBusFreeFunction);
|
||||
dbus_bool_t (*connection_try_register_object_path)(DBusConnection *, const char *,
|
||||
const DBusObjectPathVTable *, void *, DBusError *);
|
||||
dbus_bool_t (*connection_send)(DBusConnection *, DBusMessage *, dbus_uint32_t *);
|
||||
|
|
@ -51,7 +50,7 @@ typedef struct SDL_DBusContext {
|
|||
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 *);
|
||||
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_append_args_valist)(DBusMessage *, int, va_list);
|
||||
|
|
@ -61,7 +60,7 @@ typedef struct SDL_DBusContext {
|
|||
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_iter_recurse)(DBusMessageIter *, DBusMessageIter *);
|
||||
void (*message_unref)(DBusMessage *);
|
||||
void (*error_init)(DBusError *);
|
||||
dbus_bool_t (*error_is_set)(const DBusError *);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
#define ABS_MT_POSITION_X 0x35
|
||||
#define ABS_MT_POSITION_Y 0x36
|
||||
#define ABS_MT_TRACKING_ID 0x39
|
||||
#define ABS_MT_PRESSURE 0x3a
|
||||
#endif
|
||||
|
||||
typedef struct SDL_evdevlist_item
|
||||
|
|
@ -74,6 +75,7 @@ typedef struct SDL_evdevlist_item
|
|||
|
||||
int min_x, max_x, range_x;
|
||||
int min_y, max_y, range_y;
|
||||
int min_pressure, max_pressure, range_pressure;
|
||||
|
||||
int max_slots;
|
||||
int current_slot;
|
||||
|
|
@ -85,8 +87,9 @@ typedef struct SDL_evdevlist_item
|
|||
EVDEV_TOUCH_SLOTDELTA_MOVE
|
||||
} delta;
|
||||
int tracking_id;
|
||||
int x, y;
|
||||
int x, y, pressure;
|
||||
} * slots;
|
||||
|
||||
} * touchscreen_data;
|
||||
|
||||
struct SDL_evdevlist_item *next;
|
||||
|
|
@ -101,6 +104,7 @@ typedef struct SDL_EVDEV_PrivateData
|
|||
SDL_EVDEV_keyboard_state *kbd;
|
||||
} SDL_EVDEV_PrivateData;
|
||||
|
||||
#undef _THIS
|
||||
#define _THIS SDL_EVDEV_PrivateData *_this
|
||||
static _THIS = NULL;
|
||||
|
||||
|
|
@ -125,6 +129,14 @@ static Uint8 EVDEV_MouseButtons[] = {
|
|||
SDL_BUTTON_X2 + 3 /* BTN_TASK 0x117 */
|
||||
};
|
||||
|
||||
static int
|
||||
SDL_EVDEV_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
/* Mice already send relative events through this interface */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SDL_EVDEV_Init(void)
|
||||
{
|
||||
|
|
@ -158,6 +170,8 @@ SDL_EVDEV_Init(void)
|
|||
_this->kbd = SDL_EVDEV_kbd_init();
|
||||
}
|
||||
|
||||
SDL_GetMouse()->SetRelativeMouseMode = SDL_EVDEV_SetRelativeMouseMode;
|
||||
|
||||
_this->ref_count += 1;
|
||||
|
||||
return 0;
|
||||
|
|
@ -228,7 +242,7 @@ SDL_EVDEV_Poll(void)
|
|||
SDL_Scancode scan_code;
|
||||
int mouse_button;
|
||||
SDL_Mouse *mouse;
|
||||
float norm_x, norm_y;
|
||||
float norm_x, norm_y, norm_pressure;
|
||||
|
||||
if (!_this) {
|
||||
return;
|
||||
|
|
@ -263,6 +277,20 @@ SDL_EVDEV_Poll(void)
|
|||
break;
|
||||
}
|
||||
|
||||
/* BTH_TOUCH event value 1 indicates there is contact with
|
||||
a touchscreen or trackpad (earlist finger's current
|
||||
position is sent in EV_ABS ABS_X/ABS_Y, switching to
|
||||
next finger after earlist is released) */
|
||||
if (item->is_touchscreen && events[i].code == BTN_TOUCH) {
|
||||
if (item->touchscreen_data->max_slots == 1) {
|
||||
if (events[i].value)
|
||||
item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
|
||||
else
|
||||
item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_UP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Probably keyboard */
|
||||
scan_code = SDL_EVDEV_translate_keycode(events[i].code);
|
||||
if (scan_code != SDL_SCANCODE_UNKNOWN) {
|
||||
|
|
@ -307,15 +335,29 @@ SDL_EVDEV_Poll(void)
|
|||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
break;
|
||||
case ABS_X:
|
||||
if (item->is_touchscreen) /* FIXME: temp hack */
|
||||
case ABS_MT_PRESSURE:
|
||||
if (!item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].pressure = events[i].value;
|
||||
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
|
||||
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
break;
|
||||
case ABS_X:
|
||||
if (item->is_touchscreen) {
|
||||
if (item->touchscreen_data->max_slots != 1)
|
||||
break;
|
||||
item->touchscreen_data->slots[0].x = events[i].value;
|
||||
} else
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
|
||||
break;
|
||||
case ABS_Y:
|
||||
if (item->is_touchscreen) /* FIXME: temp hack */
|
||||
break;
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
|
||||
if (item->is_touchscreen) {
|
||||
if (item->touchscreen_data->max_slots != 1)
|
||||
break;
|
||||
item->touchscreen_data->slots[0].y = events[i].value;
|
||||
} else
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -351,18 +393,26 @@ SDL_EVDEV_Poll(void)
|
|||
norm_y = (float)(item->touchscreen_data->slots[j].y - item->touchscreen_data->min_y) /
|
||||
(float)item->touchscreen_data->range_y;
|
||||
|
||||
if (item->touchscreen_data->range_pressure > 0) {
|
||||
norm_pressure = (float)(item->touchscreen_data->slots[j].pressure - item->touchscreen_data->min_pressure) /
|
||||
(float)item->touchscreen_data->range_pressure;
|
||||
} else {
|
||||
/* This touchscreen does not support pressure */
|
||||
norm_pressure = 1.0f;
|
||||
}
|
||||
|
||||
switch(item->touchscreen_data->slots[j].delta) {
|
||||
case EVDEV_TOUCH_SLOTDELTA_DOWN:
|
||||
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, 1.0f);
|
||||
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, norm_pressure);
|
||||
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
||||
break;
|
||||
case EVDEV_TOUCH_SLOTDELTA_UP:
|
||||
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, 1.0f);
|
||||
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, norm_pressure);
|
||||
item->touchscreen_data->slots[j].tracking_id = -1;
|
||||
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
||||
break;
|
||||
case EVDEV_TOUCH_SLOTDELTA_MOVE:
|
||||
SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, 1.0f);
|
||||
SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, norm_pressure);
|
||||
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -397,9 +447,15 @@ SDL_EVDEV_translate_keycode(int keycode)
|
|||
scancode = linux_scancode_table[keycode];
|
||||
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
SDL_Log("The key you just pressed is not recognized by SDL. To help "
|
||||
"get this fixed, please report this to the SDL forums/mailing list "
|
||||
"<https://discourse.libsdl.org/> EVDEV KeyCode %d", keycode);
|
||||
/* BTN_TOUCH is handled elsewhere, but we might still end up here if
|
||||
you get an unexpected BTN_TOUCH from something SDL believes is not
|
||||
a touch device. In this case, we'd rather not get a misleading
|
||||
SDL_Log message about an unknown key. */
|
||||
if (keycode != BTN_TOUCH) {
|
||||
SDL_Log("The key you just pressed is not recognized by SDL. To help "
|
||||
"get this fixed, please report this to the SDL forums/mailing list "
|
||||
"<https://discourse.libsdl.org/> EVDEV KeyCode %d", keycode);
|
||||
}
|
||||
}
|
||||
|
||||
return scancode;
|
||||
|
|
@ -410,6 +466,7 @@ static int
|
|||
SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
||||
{
|
||||
int ret, i;
|
||||
unsigned long xreq, yreq;
|
||||
char name[64];
|
||||
struct input_absinfo abs_info;
|
||||
|
||||
|
|
@ -432,7 +489,24 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
|||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_info);
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_SetError("Failed to get evdev touchscreen limits");
|
||||
}
|
||||
|
||||
if (abs_info.maximum == 0) {
|
||||
item->touchscreen_data->max_slots = 1;
|
||||
xreq = EVIOCGABS(ABS_X);
|
||||
yreq = EVIOCGABS(ABS_Y);
|
||||
} else {
|
||||
item->touchscreen_data->max_slots = abs_info.maximum + 1;
|
||||
xreq = EVIOCGABS(ABS_MT_POSITION_X);
|
||||
yreq = EVIOCGABS(ABS_MT_POSITION_Y);
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, xreq, &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
|
|
@ -442,7 +516,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
|||
item->touchscreen_data->max_x = abs_info.maximum;
|
||||
item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_info);
|
||||
ret = ioctl(item->fd, yreq, &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
|
|
@ -452,13 +526,15 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
|||
item->touchscreen_data->max_y = abs_info.maximum;
|
||||
item->touchscreen_data->range_y = abs_info.maximum - abs_info.minimum;
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_PRESSURE), &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->name);
|
||||
SDL_free(item->touchscreen_data);
|
||||
return SDL_SetError("Failed to get evdev touchscreen limits");
|
||||
}
|
||||
item->touchscreen_data->max_slots = abs_info.maximum + 1;
|
||||
item->touchscreen_data->min_pressure = abs_info.minimum;
|
||||
item->touchscreen_data->max_pressure = abs_info.maximum;
|
||||
item->touchscreen_data->range_pressure = abs_info.maximum - abs_info.minimum;
|
||||
|
||||
item->touchscreen_data->slots = SDL_calloc(
|
||||
item->touchscreen_data->max_slots,
|
||||
|
|
@ -474,6 +550,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
|||
}
|
||||
|
||||
ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
|
||||
SDL_TOUCH_DEVICE_DIRECT,
|
||||
item->touchscreen_data->name);
|
||||
if (ret < 0) {
|
||||
SDL_free(item->touchscreen_data->slots);
|
||||
|
|
@ -511,8 +588,8 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
|||
*
|
||||
* this is the structure we're trying to emulate
|
||||
*/
|
||||
__u32* mt_req_code;
|
||||
__s32* mt_req_values;
|
||||
Uint32* mt_req_code;
|
||||
Sint32* mt_req_values;
|
||||
size_t mt_req_size;
|
||||
|
||||
/* TODO: sync devices other than touchscreen */
|
||||
|
|
@ -527,7 +604,7 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
|||
return;
|
||||
}
|
||||
|
||||
mt_req_values = (__s32*)mt_req_code + 1;
|
||||
mt_req_values = (Sint32*)mt_req_code + 1;
|
||||
|
||||
*mt_req_code = ABS_MT_TRACKING_ID;
|
||||
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
||||
|
|
@ -592,6 +669,24 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
|||
}
|
||||
}
|
||||
|
||||
*mt_req_code = ABS_MT_PRESSURE;
|
||||
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
||||
if (ret < 0) {
|
||||
SDL_free(mt_req_code);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
||||
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
||||
item->touchscreen_data->slots[i].pressure != mt_req_values[i]) {
|
||||
item->touchscreen_data->slots[i].pressure = mt_req_values[i];
|
||||
if (item->touchscreen_data->slots[i].delta ==
|
||||
EVDEV_TOUCH_SLOTDELTA_NONE) {
|
||||
item->touchscreen_data->slots[i].delta =
|
||||
EVDEV_TOUCH_SLOTDELTA_MOVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
||||
if (ret < 0) {
|
||||
SDL_free(mt_req_code);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include "../../SDL_internal.h"
|
||||
|
||||
#include "SDL_evdev_kbd.h"
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#ifdef SDL_INPUT_LINUXKD
|
||||
|
||||
|
|
@ -34,6 +35,8 @@
|
|||
#include <linux/vt.h>
|
||||
#include <linux/tiocl.h> /* for TIOCL_GETSHIFTSTATE */
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "SDL_evdev_kbd_default_accents.h"
|
||||
#include "SDL_evdev_kbd_default_keymap.h"
|
||||
|
|
@ -191,13 +194,157 @@ static int SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SDL_EVDEV_keyboard_state * kbd_cleanup_state = NULL;
|
||||
static int kbd_cleanup_sigactions_installed = 0;
|
||||
static int kbd_cleanup_atexit_installed = 0;
|
||||
|
||||
static struct sigaction old_sigaction[NSIG];
|
||||
|
||||
static int fatal_signals[] =
|
||||
{
|
||||
/* Handlers for SIGTERM and SIGINT are installed in SDL_QuitInit. */
|
||||
SIGHUP, SIGQUIT, SIGILL, SIGABRT,
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGBUS,
|
||||
SIGSYS
|
||||
};
|
||||
|
||||
static void kbd_cleanup(void)
|
||||
{
|
||||
SDL_EVDEV_keyboard_state* kbd = kbd_cleanup_state;
|
||||
if (kbd == NULL) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_state = NULL;
|
||||
|
||||
ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EVDEV_kbd_reraise_signal(int sig)
|
||||
{
|
||||
raise(sig);
|
||||
}
|
||||
|
||||
siginfo_t* SDL_EVDEV_kdb_cleanup_siginfo = NULL;
|
||||
void* SDL_EVDEV_kdb_cleanup_ucontext = NULL;
|
||||
|
||||
static void kbd_cleanup_signal_action(int signum, siginfo_t* info, void* ucontext)
|
||||
{
|
||||
struct sigaction* old_action_p = &(old_sigaction[signum]);
|
||||
sigset_t sigset;
|
||||
|
||||
/* Restore original signal handler before going any further. */
|
||||
sigaction(signum, old_action_p, NULL);
|
||||
|
||||
/* Unmask current signal. */
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, signum);
|
||||
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
|
||||
|
||||
/* Save original signal info and context for archeologists. */
|
||||
SDL_EVDEV_kdb_cleanup_siginfo = info;
|
||||
SDL_EVDEV_kdb_cleanup_ucontext = ucontext;
|
||||
|
||||
/* Restore keyboard. */
|
||||
kbd_cleanup();
|
||||
|
||||
/* Reraise signal. */
|
||||
SDL_EVDEV_kbd_reraise_signal(signum);
|
||||
}
|
||||
|
||||
static void kbd_unregister_emerg_cleanup()
|
||||
{
|
||||
int tabidx, signum;
|
||||
|
||||
kbd_cleanup_state = NULL;
|
||||
|
||||
if (!kbd_cleanup_sigactions_installed) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_sigactions_installed = 0;
|
||||
|
||||
for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
|
||||
struct sigaction* old_action_p;
|
||||
struct sigaction cur_action;
|
||||
signum = fatal_signals[tabidx];
|
||||
old_action_p = &(old_sigaction[signum]);
|
||||
|
||||
/* Examine current signal action */
|
||||
if (sigaction(signum, NULL, &cur_action))
|
||||
continue;
|
||||
|
||||
/* Check if action installed and not modifed */
|
||||
if (!(cur_action.sa_flags & SA_SIGINFO)
|
||||
|| cur_action.sa_sigaction != &kbd_cleanup_signal_action)
|
||||
continue;
|
||||
|
||||
/* Restore original action */
|
||||
sigaction(signum, old_action_p, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void kbd_cleanup_atexit(void)
|
||||
{
|
||||
/* Restore keyboard. */
|
||||
kbd_cleanup();
|
||||
|
||||
/* Try to restore signal handlers in case shared library is being unloaded */
|
||||
kbd_unregister_emerg_cleanup();
|
||||
}
|
||||
|
||||
static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state * kbd)
|
||||
{
|
||||
int tabidx, signum;
|
||||
|
||||
if (kbd_cleanup_state != NULL) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_state = kbd;
|
||||
|
||||
if (!kbd_cleanup_atexit_installed) {
|
||||
/* Since glibc 2.2.3, atexit() (and on_exit(3)) can be used within a shared library to establish
|
||||
* functions that are called when the shared library is unloaded.
|
||||
* -- man atexit(3)
|
||||
*/
|
||||
atexit(kbd_cleanup_atexit);
|
||||
kbd_cleanup_atexit_installed = 1;
|
||||
}
|
||||
|
||||
if (kbd_cleanup_sigactions_installed) {
|
||||
return;
|
||||
}
|
||||
kbd_cleanup_sigactions_installed = 1;
|
||||
|
||||
for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
|
||||
struct sigaction* old_action_p;
|
||||
struct sigaction new_action;
|
||||
signum = fatal_signals[tabidx];
|
||||
old_action_p = &(old_sigaction[signum]);
|
||||
if (sigaction(signum, NULL, old_action_p))
|
||||
continue;
|
||||
|
||||
/* Skip SIGHUP and SIGPIPE if handler is already installed
|
||||
* - assume the handler will do the cleanup
|
||||
*/
|
||||
if ((signum == SIGHUP || signum == SIGPIPE)
|
||||
&& (old_action_p->sa_handler != SIG_DFL
|
||||
|| (void (*)(int))old_action_p->sa_sigaction != SIG_DFL))
|
||||
continue;
|
||||
|
||||
new_action = *old_action_p;
|
||||
new_action.sa_flags |= SA_SIGINFO;
|
||||
new_action.sa_sigaction = &kbd_cleanup_signal_action;
|
||||
sigaction(signum, &new_action, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_EVDEV_keyboard_state *
|
||||
SDL_EVDEV_kbd_init(void)
|
||||
{
|
||||
SDL_EVDEV_keyboard_state *kbd;
|
||||
int i;
|
||||
char flag_state;
|
||||
char shift_state[2] = {TIOCL_GETSHIFTSTATE, 0};
|
||||
char shift_state[ sizeof (long) ] = {TIOCL_GETSHIFTSTATE, 0};
|
||||
|
||||
kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
|
||||
if (!kbd) {
|
||||
|
|
@ -238,10 +385,20 @@ SDL_EVDEV_kbd_init(void)
|
|||
kbd->key_maps = default_key_maps;
|
||||
}
|
||||
|
||||
/* Mute the keyboard so keystrokes only generate evdev events
|
||||
* and do not leak through to the console
|
||||
*/
|
||||
ioctl(kbd->console_fd, KDSKBMODE, K_OFF);
|
||||
/* Allow inhibiting keyboard mute with env. variable for debugging etc. */
|
||||
if (getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) {
|
||||
/* Mute the keyboard so keystrokes only generate evdev events
|
||||
* and do not leak through to the console
|
||||
*/
|
||||
ioctl(kbd->console_fd, KDSKBMODE, K_OFF);
|
||||
|
||||
/* Make sure to restore keyboard if application fails to call
|
||||
* SDL_Quit before exit or fatal signal is raised.
|
||||
*/
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) {
|
||||
kbd_register_emerg_cleanup(kbd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DUMP_ACCENTS
|
||||
|
|
@ -260,6 +417,8 @@ SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
|
|||
return;
|
||||
}
|
||||
|
||||
kbd_unregister_emerg_cleanup();
|
||||
|
||||
if (kbd->console_fd >= 0) {
|
||||
/* Restore the original keyboard mode */
|
||||
ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
|
||||
|
|
@ -350,17 +509,19 @@ static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
|
|||
|
||||
static int vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
return ((kbd->ledflagstate >> flag) & 1);
|
||||
return (kbd->ledflagstate & flag) != 0;
|
||||
}
|
||||
|
||||
static void set_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate |= 1 << flag;
|
||||
kbd->ledflagstate |= flag;
|
||||
ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
|
||||
}
|
||||
|
||||
static void clr_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate &= ~(1 << flag);
|
||||
kbd->ledflagstate &= ~flag;
|
||||
ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
|
||||
}
|
||||
|
||||
static void chg_vc_kbd_lock(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
|
|
@ -375,7 +536,8 @@ static void chg_vc_kbd_slock(SDL_EVDEV_keyboard_state *kbd, int flag)
|
|||
|
||||
static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
|
||||
{
|
||||
kbd->ledflagstate ^= 1 << flag;
|
||||
kbd->ledflagstate ^= flag;
|
||||
ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -609,7 +771,10 @@ SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int d
|
|||
shift_final = (kbd->shift_state | kbd->slockstate) ^ kbd->lockstate;
|
||||
key_map = kbd->key_maps[shift_final];
|
||||
if (!key_map) {
|
||||
/* Unsupported shift state (e.g. ctrl = 4, alt = 8), just reset to the default state */
|
||||
kbd->shift_state = 0;
|
||||
kbd->slockstate = 0;
|
||||
kbd->lockstate = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -19,6 +19,9 @@
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_evdev_kbd_h_
|
||||
#define SDL_evdev_kbd_h_
|
||||
|
||||
struct SDL_EVDEV_keyboard_state;
|
||||
typedef struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state;
|
||||
|
||||
|
|
@ -26,4 +29,6 @@ extern SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void);
|
|||
extern void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down);
|
||||
extern void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state);
|
||||
|
||||
#endif /* SDL_evdev_kbd_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
113
Engine/lib/sdl/src/core/linux/SDL_threadprio.c
Normal file
113
Engine/lib/sdl/src/core/linux/SDL_threadprio.c
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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 __LINUX__
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
#if !SDL_THREADS_DISABLED
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <pthread.h>
|
||||
#include "SDL_system.h"
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
#include "SDL_dbus.h"
|
||||
/* d-bus queries to org.freedesktop.RealtimeKit1. */
|
||||
#define RTKIT_DBUS_NODE "org.freedesktop.RealtimeKit1"
|
||||
#define RTKIT_DBUS_PATH "/org/freedesktop/RealtimeKit1"
|
||||
#define RTKIT_DBUS_INTERFACE "org.freedesktop.RealtimeKit1"
|
||||
|
||||
static pthread_once_t rtkit_initialize_once = PTHREAD_ONCE_INIT;
|
||||
static Sint32 rtkit_min_nice_level = -20;
|
||||
|
||||
static void
|
||||
rtkit_initialize()
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
/* Try getting minimum nice level: this is often greater than PRIO_MIN (-20). */
|
||||
if (!dbus || !SDL_DBus_QueryPropertyOnConnection(dbus->system_conn, RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "MinNiceLevel",
|
||||
DBUS_TYPE_INT32, &rtkit_min_nice_level)) {
|
||||
rtkit_min_nice_level = -20;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
rtkit_setpriority(pid_t thread, int nice_level)
|
||||
{
|
||||
Uint64 ui64 = (Uint64)thread;
|
||||
Sint32 si32 = (Sint32)nice_level;
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
pthread_once(&rtkit_initialize_once, rtkit_initialize);
|
||||
|
||||
if (si32 < rtkit_min_nice_level)
|
||||
si32 = rtkit_min_nice_level;
|
||||
|
||||
if (!dbus || !SDL_DBus_CallMethodOnConnection(dbus->system_conn,
|
||||
RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "MakeThreadHighPriority",
|
||||
DBUS_TYPE_UINT64, &ui64, DBUS_TYPE_INT32, &si32, DBUS_TYPE_INVALID,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif /* dbus */
|
||||
#endif /* threads */
|
||||
|
||||
|
||||
/* this is a public symbol, so it has to exist even if threads are disabled. */
|
||||
int
|
||||
SDL_LinuxSetThreadPriority(Sint64 threadID, int priority)
|
||||
{
|
||||
#if SDL_THREADS_DISABLED
|
||||
return SDL_Unsupported();
|
||||
#else
|
||||
if (setpriority(PRIO_PROCESS, (id_t)threadID, priority) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
/* Note that this fails if you're trying to set high priority
|
||||
and you don't have root permission. BUT DON'T RUN AS ROOT!
|
||||
|
||||
You can grant the ability to increase thread priority by
|
||||
running the following command on your application binary:
|
||||
sudo setcap 'cap_sys_nice=eip' <application>
|
||||
|
||||
Let's try setting priority with RealtimeKit...
|
||||
|
||||
README and sample code at: http://git.0pointer.net/rtkit.git
|
||||
*/
|
||||
if (rtkit_setpriority((pid_t)threadID, priority)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SDL_SetError("setpriority() failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __LINUX__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -63,7 +63,7 @@ SDL_UDEV_load_syms(void)
|
|||
{
|
||||
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
|
||||
#define SDL_UDEV_SYM(x) \
|
||||
if (!SDL_UDEV_load_sym(#x, (void **) (char *) & _this->x)) return -1
|
||||
if (!SDL_UDEV_load_sym(#x, (void **) (char *) & _this->syms.x)) return -1
|
||||
|
||||
SDL_UDEV_SYM(udev_device_get_action);
|
||||
SDL_UDEV_SYM(udev_device_get_devnode);
|
||||
|
|
@ -100,7 +100,7 @@ static SDL_bool
|
|||
SDL_UDEV_hotplug_update_available(void)
|
||||
{
|
||||
if (_this->udev_mon != NULL) {
|
||||
const int fd = _this->udev_monitor_get_fd(_this->udev_mon);
|
||||
const int fd = _this->syms.udev_monitor_get_fd(_this->udev_mon);
|
||||
if (SDL_IOReady(fd, SDL_FALSE, 0)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
|
@ -130,21 +130,21 @@ SDL_UDEV_Init(void)
|
|||
* Listen for input devices (mouse, keyboard, joystick, etc) and sound devices
|
||||
*/
|
||||
|
||||
_this->udev = _this->udev_new();
|
||||
_this->udev = _this->syms.udev_new();
|
||||
if (_this->udev == NULL) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("udev_new() failed");
|
||||
}
|
||||
|
||||
_this->udev_mon = _this->udev_monitor_new_from_netlink(_this->udev, "udev");
|
||||
_this->udev_mon = _this->syms.udev_monitor_new_from_netlink(_this->udev, "udev");
|
||||
if (_this->udev_mon == NULL) {
|
||||
SDL_UDEV_Quit();
|
||||
return SDL_SetError("udev_monitor_new_from_netlink() failed");
|
||||
}
|
||||
|
||||
_this->udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "input", NULL);
|
||||
_this->udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "sound", NULL);
|
||||
_this->udev_monitor_enable_receiving(_this->udev_mon);
|
||||
_this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "input", NULL);
|
||||
_this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "sound", NULL);
|
||||
_this->syms.udev_monitor_enable_receiving(_this->udev_mon);
|
||||
|
||||
/* Do an initial scan of existing devices */
|
||||
SDL_UDEV_Scan();
|
||||
|
|
@ -170,11 +170,11 @@ SDL_UDEV_Quit(void)
|
|||
if (_this->ref_count < 1) {
|
||||
|
||||
if (_this->udev_mon != NULL) {
|
||||
_this->udev_monitor_unref(_this->udev_mon);
|
||||
_this->syms.udev_monitor_unref(_this->udev_mon);
|
||||
_this->udev_mon = NULL;
|
||||
}
|
||||
if (_this->udev != NULL) {
|
||||
_this->udev_unref(_this->udev);
|
||||
_this->syms.udev_unref(_this->udev);
|
||||
_this->udev = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -202,28 +202,28 @@ SDL_UDEV_Scan(void)
|
|||
return;
|
||||
}
|
||||
|
||||
enumerate = _this->udev_enumerate_new(_this->udev);
|
||||
enumerate = _this->syms.udev_enumerate_new(_this->udev);
|
||||
if (enumerate == NULL) {
|
||||
SDL_UDEV_Quit();
|
||||
SDL_SetError("udev_enumerate_new() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
_this->udev_enumerate_add_match_subsystem(enumerate, "input");
|
||||
_this->udev_enumerate_add_match_subsystem(enumerate, "sound");
|
||||
_this->syms.udev_enumerate_add_match_subsystem(enumerate, "input");
|
||||
_this->syms.udev_enumerate_add_match_subsystem(enumerate, "sound");
|
||||
|
||||
_this->udev_enumerate_scan_devices(enumerate);
|
||||
devs = _this->udev_enumerate_get_list_entry(enumerate);
|
||||
for (item = devs; item; item = _this->udev_list_entry_get_next(item)) {
|
||||
const char *path = _this->udev_list_entry_get_name(item);
|
||||
struct udev_device *dev = _this->udev_device_new_from_syspath(_this->udev, path);
|
||||
_this->syms.udev_enumerate_scan_devices(enumerate);
|
||||
devs = _this->syms.udev_enumerate_get_list_entry(enumerate);
|
||||
for (item = devs; item; item = _this->syms.udev_list_entry_get_next(item)) {
|
||||
const char *path = _this->syms.udev_list_entry_get_name(item);
|
||||
struct udev_device *dev = _this->syms.udev_device_new_from_syspath(_this->udev, path);
|
||||
if (dev != NULL) {
|
||||
device_event(SDL_UDEV_DEVICEADDED, dev);
|
||||
_this->udev_device_unref(dev);
|
||||
_this->syms.udev_device_unref(dev);
|
||||
}
|
||||
}
|
||||
|
||||
_this->udev_enumerate_unref(enumerate);
|
||||
_this->syms.udev_enumerate_unref(enumerate);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -305,7 +305,7 @@ static void get_caps(struct udev_device *dev, struct udev_device *pdev, const ch
|
|||
unsigned long v;
|
||||
|
||||
SDL_memset(bitmask, 0, bitmask_len*sizeof(*bitmask));
|
||||
value = _this->udev_device_get_sysattr_value(pdev, attr);
|
||||
value = _this->syms.udev_device_get_sysattr_value(pdev, attr);
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -340,8 +340,8 @@ guess_device_class(struct udev_device *dev)
|
|||
/* 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);
|
||||
while (pdev && !_this->syms.udev_device_get_sysattr_value(pdev, "capabilities/ev")) {
|
||||
pdev = _this->syms.udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL);
|
||||
}
|
||||
if (!pdev) {
|
||||
return 0;
|
||||
|
|
@ -405,28 +405,28 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
|||
const char *path;
|
||||
SDL_UDEV_CallbackList *item;
|
||||
|
||||
path = _this->udev_device_get_devnode(dev);
|
||||
path = _this->syms.udev_device_get_devnode(dev);
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
subsystem = _this->udev_device_get_subsystem(dev);
|
||||
subsystem = _this->syms.udev_device_get_subsystem(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");
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_JOYSTICK;
|
||||
}
|
||||
|
||||
val = _this->udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_MOUSE;
|
||||
}
|
||||
|
||||
val = _this->udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN");
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN");
|
||||
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
||||
devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN;
|
||||
}
|
||||
|
|
@ -437,14 +437,14 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
|||
|
||||
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");
|
||||
val = _this->syms.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) {
|
||||
/* Fall back to old style input classes */
|
||||
val = _this->udev_device_get_property_value(dev, "ID_CLASS");
|
||||
val = _this->syms.udev_device_get_property_value(dev, "ID_CLASS");
|
||||
if (val != NULL) {
|
||||
if (SDL_strcmp(val, "joystick") == 0) {
|
||||
devclass = SDL_UDEV_DEVICE_JOYSTICK;
|
||||
|
|
@ -481,11 +481,11 @@ SDL_UDEV_Poll(void)
|
|||
}
|
||||
|
||||
while (SDL_UDEV_hotplug_update_available()) {
|
||||
dev = _this->udev_monitor_receive_device(_this->udev_mon);
|
||||
dev = _this->syms.udev_monitor_receive_device(_this->udev_mon);
|
||||
if (dev == NULL) {
|
||||
break;
|
||||
}
|
||||
action = _this->udev_device_get_action(dev);
|
||||
action = _this->syms.udev_device_get_action(dev);
|
||||
|
||||
if (SDL_strcmp(action, "add") == 0) {
|
||||
/* Wait for the device to finish initialization */
|
||||
|
|
@ -496,7 +496,7 @@ SDL_UDEV_Poll(void)
|
|||
device_event(SDL_UDEV_DEVICEREMOVED, dev);
|
||||
}
|
||||
|
||||
_this->udev_device_unref(dev);
|
||||
_this->syms.udev_device_unref(dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -547,6 +547,22 @@ SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
|
|||
|
||||
}
|
||||
|
||||
const SDL_UDEV_Symbols *
|
||||
SDL_UDEV_GetUdevSyms(void)
|
||||
{
|
||||
if (SDL_UDEV_Init() < 0) {
|
||||
SDL_SetError("Could not initialize UDEV");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &_this->syms;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UDEV_ReleaseUdevSyms(void)
|
||||
{
|
||||
SDL_UDEV_Quit();
|
||||
}
|
||||
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -64,22 +64,13 @@ typedef struct SDL_UDEV_CallbackList {
|
|||
struct SDL_UDEV_CallbackList *next;
|
||||
} SDL_UDEV_CallbackList;
|
||||
|
||||
typedef struct SDL_UDEV_PrivateData
|
||||
{
|
||||
const char *udev_library;
|
||||
void *udev_handle;
|
||||
struct udev *udev;
|
||||
struct udev_monitor *udev_mon;
|
||||
int ref_count;
|
||||
SDL_UDEV_CallbackList *first, *last;
|
||||
|
||||
/* Function pointers */
|
||||
typedef struct SDL_UDEV_Symbols {
|
||||
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);
|
||||
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);
|
||||
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 *);
|
||||
|
|
@ -100,6 +91,19 @@ typedef struct SDL_UDEV_PrivateData
|
|||
void (*udev_unref)(struct udev *);
|
||||
struct udev_device * (*udev_device_new_from_devnum)(struct udev *udev, char type, dev_t devnum);
|
||||
dev_t (*udev_device_get_devnum) (struct udev_device *udev_device);
|
||||
} SDL_UDEV_Symbols;
|
||||
|
||||
typedef struct SDL_UDEV_PrivateData
|
||||
{
|
||||
const char *udev_library;
|
||||
void *udev_handle;
|
||||
struct udev *udev;
|
||||
struct udev_monitor *udev_mon;
|
||||
int ref_count;
|
||||
SDL_UDEV_CallbackList *first, *last;
|
||||
|
||||
/* Function pointers */
|
||||
SDL_UDEV_Symbols syms;
|
||||
} SDL_UDEV_PrivateData;
|
||||
|
||||
extern int SDL_UDEV_Init(void);
|
||||
|
|
@ -110,8 +114,8 @@ extern void SDL_UDEV_Poll(void);
|
|||
extern void SDL_UDEV_Scan(void);
|
||||
extern int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb);
|
||||
extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb);
|
||||
|
||||
|
||||
extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void);
|
||||
extern void SDL_UDEV_ReleaseUdevSyms(void);
|
||||
|
||||
|
||||
#endif /* HAVE_LIBUDEV_H */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
@ -31,6 +31,9 @@
|
|||
#ifndef _WIN32_WINNT_VISTA
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT_WIN7
|
||||
#define _WIN32_WINNT_WIN7 0x0601
|
||||
#endif
|
||||
|
||||
|
||||
/* Sets an error message based on an HRESULT */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue